WIP: refactor: port to JS
Some checks failed
/ check (treefmt) (push) Successful in 4s
/ report-size (push) Failing after 1s
/ report-download-check (push) Has been skipped

This should hopefully reduce the complexity of the action
This commit is contained in:
Jalil David Salamé Messina 2025-07-10 22:03:45 +02:00
parent a26909cb8c
commit 0be52794ad
Signed by: jalil
GPG key ID: F016B9E770737A0B
20 changed files with 215059 additions and 109 deletions

145
src/main.js Normal file
View file

@ -0,0 +1,145 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as github from '@actions/github'
import { DefaultArtifactClient } from '@actions/artifact'
import * as fs from 'node:fs/promises'
/**
* The main function for the action.
*
* @returns {Promise<void>} Resolves when the action is complete.
*/
export async function run() {
try {
const comment = core.getBooleanInput('comment-on-pr', { required: false })
const upload = core.getBooleanInput('generate-artifact', {
required: false
})
const artifactName = core.getInput('artifact-name', { required: false })
const compare = core.getBooleanInput('do-comparison', { required: false })
const jobName = core.getInput('job-name', { required: false })
const baseBranch = core.getInput('base-branch', { required: false })
const system = core.getInput('system', { required: true })
if (!comment && !upload) {
core.error(
'Both comment-on-pr and generate-artifact were set to false, nothing to do, consider disabling the action instead'
)
core.setFailed('Neither commenting nor uploading a report ... why?')
return
}
const flakeInfo = JSON.parse(
await collectOutput('nix', ['flake', 'show', '--json'])
)
core.debug(`nix flake show --json: ${flakeInfo}`)
const report = await core.group('Generating size report', () =>
generateReport(flakeInfo, system)
)
if (upload) {
const artifact = new DefaultArtifactClient()
await fs.writeFile(artifactName, JSON.stringify(report))
const { id, size } = artifact.uploadArtifact(artifactName, [artifactName])
core.info(`Uploaded report ${artifactName} (${size}B) with id ${id}`)
}
// Done
if (!comment) {
return
}
// TODO: compare reports and create comment
} catch (error) {
// Fail the workflow run if an error occurs
if (error instanceof Error) core.setFailed(error.message)
}
}
async function generateReport(flakeInfo, system) {
const packages = getPackages(flakeInfo, system)
const hmConfigs = getKeys(flakeInfo, 'homeConfigurations')
const nixosConfigs = getKeys(flakeInfo, 'nixosConfigurations')
core.info(`packages: ${packages}`)
core.info(`homeConfigurations: ${hmConfigs}`)
core.info(`nixosConfigurations: ${nixosConfigs}`)
const pkgSizes = await core.group('Calculating size of packages', () =>
calculateSizeOf(packages, (pkg) => `.#${pkg}`)
)
const hmConfigsSizes = await core.group(
'Calculating size of Home-Manager Configurations',
() =>
calculateSizeOf(
hmConfigs,
(config) => `.#homeConfigurations.${config}.activationPackages`
)
)
const nixosConfigsSizes = await core.group(
'Calculating size of NixOS Configurations',
() =>
calculateSizeOf(
nixosConfigs,
(config) =>
`.#nixosConfigurations.${config}.config.system.build.toplevel`
)
)
return {
packages: pkgSizes,
nixosConfigurations: nixosConfigsSizes,
homeConfigurations: hmConfigsSizes
}
}
async function calculateSizeOf(names, nameToInstallable) {
let sizes = []
for (const name of names) {
sizes.push(await calculateSize(nameToInstallable(name)))
}
return sizes
}
/**
* Get the packages from a `nix flake show --json` blob
*
* @returns {Array<String>} the packages in the current flake for the specific system
*/
function getPackages(flakeInfo, system) {
return 'packages' in flakeInfo ? getKeys(flakeInfo.packages, system) : []
}
function getKeys(flakeInfo, key) {
return key in flakeInfo ? Object.keys(flakeInfo[key]) : []
}
async function calculateSize(installable) {
const path = await collectOutput('nix', [
'build',
'--print-out-paths',
installable
])
const data = JSON.parse(
await collectOutput('nix', ['path-info', '--closure-size', '--json', path])
)
data.path = path
return data
}
async function collectOutput(cmd, args) {
let output = ''
await exec.exec(cmd, args, {
listeners: {
stdout: (data) => {
output += data.toString()
}
}
})
return output
}