Compare commits
4 commits
push-zrqlr
...
main
Author | SHA1 | Date | |
---|---|---|---|
e5d1a0751a | |||
6b0b78e496 | |||
7d7a576f50 | |||
ca72db2a3b |
25 changed files with 195 additions and 215080 deletions
|
@ -2,7 +2,7 @@
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
|
|
||||||
[*.{nix,json,sh,js}]
|
[*.{nix,json,sh}]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
|
@ -8,7 +8,7 @@ jobs:
|
||||||
check:
|
check:
|
||||||
- treefmt
|
- treefmt
|
||||||
steps:
|
steps:
|
||||||
- uses: 'https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # v4
|
- uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
|
||||||
- name: Run checks
|
- name: Run checks
|
||||||
run: |
|
run: |
|
||||||
nix --version
|
nix --version
|
||||||
|
@ -18,25 +18,23 @@ jobs:
|
||||||
runs-on: nixos
|
runs-on: nixos
|
||||||
needs: check
|
needs: check
|
||||||
steps:
|
steps:
|
||||||
- uses: 'https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # v4
|
- uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
|
||||||
- run: nix --version
|
- run: nix --version
|
||||||
- name: Create Size Report
|
- name: Create Size Report
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
system: x86_64-linux
|
|
||||||
# Create a comment on the associated PR
|
# Create a comment on the associated PR
|
||||||
comment-on-pr: ${{ github.ref_name != 'main' }}
|
comment-on-pr: 'false'
|
||||||
# Generate artifacts on main (to speed up comparisons)
|
# Generate artifacts on main (to speed up comparisons)
|
||||||
# generate-artifact: ${{ github.ref_name == 'main' }}
|
# generate-artifact: ${{ github.ref_name == 'main' }}
|
||||||
# Always generate artifacts for testing purposes
|
# Always generate artifacts for testing purposes
|
||||||
generate-artifact: 'true'
|
generate-artifact: 'true'
|
||||||
# Generate comparisons to main
|
# This job's name (so we can find the previous artifacts)
|
||||||
do-comparison: 'true'
|
|
||||||
# This job's name (so we can find the artifacts)
|
|
||||||
job-name: report-size
|
job-name: report-size
|
||||||
report-download-check:
|
report-download-check:
|
||||||
runs-on: nixos
|
runs-on: nixos
|
||||||
needs: report-size
|
needs: report-size-push
|
||||||
|
if: github.event_name == 'push'
|
||||||
steps:
|
steps:
|
||||||
- name: Download previous report
|
- name: Download previous report
|
||||||
uses: https://git.salame.cl/actions/download-artifact@d8d0a99033603453ad2255e58720b460a0555e1e # v4
|
uses: https://git.salame.cl/actions/download-artifact@d8d0a99033603453ad2255e58720b460a0555e1e # v4
|
||||||
|
|
|
@ -7,7 +7,7 @@ jobs:
|
||||||
check-renovaterc:
|
check-renovaterc:
|
||||||
runs-on: nixos
|
runs-on: nixos
|
||||||
steps:
|
steps:
|
||||||
- uses: 'https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683' # v4
|
- uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
|
||||||
- name: Validate renovaterc.json
|
- name: Validate renovaterc.json
|
||||||
run: |
|
run: |
|
||||||
nix --version
|
nix --version
|
||||||
|
|
33
.forgejo/workflows/test-pr.yml
Normal file
33
.forgejo/workflows/test-pr.yml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
jobs:
|
||||||
|
report-size-pr:
|
||||||
|
runs-on: nixos
|
||||||
|
steps:
|
||||||
|
- uses: "https://git.salame.cl/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683" # v4
|
||||||
|
- run: nix --version
|
||||||
|
- name: Create Size Report
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
# Create a comment on the associated PR
|
||||||
|
comment-on-pr: 'true'
|
||||||
|
# Generate artifacts on main (to speed up comparisons)
|
||||||
|
# generate-artifact: ${{ github.ref_name == 'main' }}
|
||||||
|
# Always generate artifacts for testing purposes
|
||||||
|
generate-artifact: 'true'
|
||||||
|
# Generate comparisons to main
|
||||||
|
do-comparison: 'true'
|
||||||
|
# Get the previous artifacts from report-size-push (since those run on main)
|
||||||
|
job-name: report-size
|
||||||
|
artifact-name: report.json
|
||||||
|
report-download-check-pr:
|
||||||
|
runs-on: nixos
|
||||||
|
needs: report-size-pr
|
||||||
|
steps:
|
||||||
|
- name: Download previous report
|
||||||
|
uses: https://git.salame.cl/actions/download-artifact@d8d0a99033603453ad2255e58720b460a0555e1e # v4
|
||||||
|
with:
|
||||||
|
name: report.json
|
||||||
|
- name: Verify report exists
|
||||||
|
run: |
|
||||||
|
cat report.json
|
3
.gitattributes
vendored
3
.gitattributes
vendored
|
@ -1,3 +0,0 @@
|
||||||
* text=auto eol=lf
|
|
||||||
|
|
||||||
dist/** -diff linguist-generated=true
|
|
103
.gitignore
vendored
103
.gitignore
vendored
|
@ -1,104 +1 @@
|
||||||
result*
|
result*
|
||||||
|
|
||||||
# Dependency directory
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Bower dependency directory (https://bower.io/)
|
|
||||||
bower_components
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# TypeScript v1 declaration files
|
|
||||||
typings/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variables file
|
|
||||||
.env
|
|
||||||
.env.test
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# next.js build output
|
|
||||||
.next
|
|
||||||
|
|
||||||
# nuxt.js build output
|
|
||||||
.nuxt
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# OS metadata
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
||||||
|
|
||||||
# Ignore built ts files
|
|
||||||
__tests__/runner/*
|
|
||||||
|
|
||||||
# IDE files
|
|
||||||
.idea
|
|
||||||
*.code-workspace
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
.DS_Store
|
|
||||||
.licenses/
|
|
||||||
dist/
|
|
||||||
node_modules/
|
|
||||||
coverage/
|
|
|
@ -1,15 +0,0 @@
|
||||||
# See: https://prettier.io/docs/en/configuration
|
|
||||||
printWidth: 80
|
|
||||||
tabWidth: 2
|
|
||||||
useTabs: false
|
|
||||||
semi: false
|
|
||||||
singleQuote: true
|
|
||||||
quoteProps: as-needed
|
|
||||||
jsxSingleQuote: false
|
|
||||||
trailingComma: none
|
|
||||||
bracketSpacing: true
|
|
||||||
bracketSameLine: true
|
|
||||||
arrowParens: always
|
|
||||||
proseWrap: always
|
|
||||||
htmlWhitespaceSensitivity: css
|
|
||||||
endOfLine: lf
|
|
32
README.md
32
README.md
|
@ -2,11 +2,9 @@
|
||||||
|
|
||||||
Use `nix path-info` to query the size of flake outputs and produce a report.
|
Use `nix path-info` to query the size of flake outputs and produce a report.
|
||||||
|
|
||||||
This repost can be posted to a PR (as formatted markdown) and/or uploaded as a
|
This repost can be posted to a PR (as formatted markdown) and/or uploaded as a workflow artifact.
|
||||||
workflow artifact.
|
|
||||||
|
|
||||||
Requires `nix`, `jq`, `curl`, `sed`, `gunzip`, `tar` and `coreutils` to be in
|
Requires `nix`, `jq`, `curl`, `sed`, `gunzip`, `tar` and `coreutils` to be in the runner's path.
|
||||||
the runner's path.
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
@ -41,32 +39,26 @@ For more details see the [action.yaml](./action.yml) file.
|
||||||
**Definitions:**
|
**Definitions:**
|
||||||
|
|
||||||
- `Name`: the name of the package/configuration.
|
- `Name`: the name of the package/configuration.
|
||||||
- `Size`: the closure size (size on disk/NAR size + all transitive
|
- `Size`: the closure size (size on disk/NAR size + all transitive dependencies).
|
||||||
dependencies).
|
|
||||||
- `NAR Size`: the size of the build output (package without the dependencies).
|
- `NAR Size`: the size of the build output (package without the dependencies).
|
||||||
- `[NAR] Size Change`: the amount changed compared to the main branch.
|
- `[NAR] Size Change`: the amount changed compared to the main branch.
|
||||||
|
|
||||||
**Tips on reading this data:**
|
**Tips on reading this data:**
|
||||||
|
|
||||||
- For NixOS configurations you generally care only about the `Size` (closure
|
- For NixOS configurations you generally care only about the `Size` (closure size/size on disk).
|
||||||
size/size on disk).
|
|
||||||
- Reduce the `Size` by disabling unneeded services/default packages.
|
- Reduce the `Size` by disabling unneeded services/default packages.
|
||||||
- For Packages you care about both the `Size` and the `NAR Size`.
|
- For Packages you care about both the `Size` and the `NAR Size`.
|
||||||
- Reduce the `NAR Size` by reducing the size of the build outputs, e.g. don't
|
- Reduce the `NAR Size` by reducing the size of the build outputs, e.g. don't copy unnecessary data to the $out dir, optimize binaries for size, etc.
|
||||||
copy unnecessary data to the $out dir, optimize binaries for size, etc.
|
|
||||||
- Reduce the `Size` by reducing the dependencies (e.g. `buildInputs`).
|
- Reduce the `Size` by reducing the dependencies (e.g. `buildInputs`).
|
||||||
- Don't worry too much about size, some dependencies are deduplicated, e.g.
|
- Don't worry too much about size, some dependencies are deduplicated, e.g. `glibc` adds ~40MiB to the `Size`, but is generally shared by ~every binary on the system, so, chances are, you are already including it from somewhere else and statically linking with e.g. `musl` is not gonna improve things.
|
||||||
`glibc` adds ~40MiB to the `Size`, but is generally shared by ~every binary
|
|
||||||
on the system, so, chances are, you are already including it from somewhere
|
|
||||||
else and statically linking with e.g. `musl` is not gonna improve things.
|
|
||||||
|
|
||||||
# NixOS Configurations
|
# NixOS Configurations
|
||||||
|
|
||||||
| Name | Size | Size Change | NAR Size | NAR Size Change |
|
| Name | Size | Size Change | NAR Size | NAR Size Change |
|
||||||
| -------- | ----: | ----------: | -------: | --------------: |
|
|------|-----:|------------:|---------:|----------------:|
|
||||||
| `gemini` | 11Gi | -2.4Mi | 28Ki | 0 |
|
| `gemini` | 11Gi | -2.4Mi | 28Ki | 0 |
|
||||||
| `leo` | 1.6Gi | 0 | 25Ki | 0 |
|
| `leo` | 1.6Gi | 0 | 25Ki | 0 |
|
||||||
| `libra` | 9.4Gi | -2.4Mi | 28Ki | 0 |
|
| `libra` | 9.4Gi | -2.4Mi | 28Ki | 0 |
|
||||||
| `taurus` | 7.6Gi | 0 | 34Ki | 0 |
|
| `taurus` | 7.6Gi | 0 | 34Ki | 0 |
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
60
action.yml
60
action.yml
|
@ -32,9 +32,6 @@ inputs:
|
||||||
|
|
||||||
This is a no-op in case no PR is associated with the current branch.
|
This is a no-op in case no PR is associated with the current branch.
|
||||||
default: 'true'
|
default: 'true'
|
||||||
system:
|
|
||||||
description: |
|
|
||||||
The nix system name to query the packages of (e.g. x86_64-linux)
|
|
||||||
# Generate workflow artifact
|
# Generate workflow artifact
|
||||||
generate-artifact:
|
generate-artifact:
|
||||||
description: Export the generated markdown document as a workflow artifact.
|
description: Export the generated markdown document as a workflow artifact.
|
||||||
|
@ -68,5 +65,58 @@ inputs:
|
||||||
default: ${{ github.base_ref }}
|
default: ${{ github.base_ref }}
|
||||||
outputs:
|
outputs:
|
||||||
runs:
|
runs:
|
||||||
using: node20
|
using: 'composite'
|
||||||
main: dist/index.js
|
steps:
|
||||||
|
- name: Run
|
||||||
|
id: pr-number
|
||||||
|
env:
|
||||||
|
BASE_BRANCH: ${{ inputs.base-branch }}
|
||||||
|
COMMENT: ${{ inputs.comment-on-pr }}
|
||||||
|
DO_COMPARISON: ${{ inputs.do-comparison }}
|
||||||
|
GENERATE_ARTIFACT: ${{ inputs.generate-artifact }}
|
||||||
|
JOB_NAME: ${{ inputs.job-name }}
|
||||||
|
run: |
|
||||||
|
"$GITHUB_ACTION_PATH/scripts/run.sh"
|
||||||
|
- name: Find previous comment (if present)
|
||||||
|
# We want to generate a comment and we we able to find the PR number
|
||||||
|
if: inputs.comment-on-pr == 'true' && steps.pr-number.outputs.pr-number != ''
|
||||||
|
id: find-comment
|
||||||
|
uses: https://github.com/peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3
|
||||||
|
with:
|
||||||
|
issue-number: ${{ steps.pr-number.outputs.pr-number }}
|
||||||
|
direction: first
|
||||||
|
body-includes: "<!-- AUTOGENERATED by nix-flake-outputs-size action -->"
|
||||||
|
- name: Create report and comment on PR
|
||||||
|
# We want to generate a comment and we we able to find the PR number
|
||||||
|
if: inputs.comment-on-pr == 'true' && steps.pr-number.outputs.pr-number != ''
|
||||||
|
env:
|
||||||
|
ARTIFACT_NAME: ${{ inputs.artifact-name }}
|
||||||
|
BASE_BRANCH: ${{ inputs.base-branch }}
|
||||||
|
COMMENT_ID: ${{ steps.find-comment.outputs.comment-id }}
|
||||||
|
DO_COMPARISON: ${{ inputs.do-comparison }}
|
||||||
|
JOB_NAME: ${{ inputs.job-name }}
|
||||||
|
PR_ID: ${{ steps.pr-number.outputs.pr-number }}
|
||||||
|
run: |
|
||||||
|
. "$GITHUB_ACTION_PATH/scripts/utils.sh"
|
||||||
|
|
||||||
|
# Try to do a comparison report
|
||||||
|
if [ "$DO_COMPARISON" = 'true' ]; then
|
||||||
|
if "$GITHUB_ACTION_PATH/scripts/retrieve-old-report.sh" && [ -f old-report.json ]; then
|
||||||
|
log "Reporting on sizes and comparing to sizes in $BASE_BRANCH"
|
||||||
|
|
||||||
|
"$GITHUB_ACTION_PATH/scripts/comment_on_pr.sh" report.json old-report.json
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
error 'Failed to do comparison, fallback to posting the report without them'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Just report values
|
||||||
|
log 'Reporting on sizes'
|
||||||
|
"$GITHUB_ACTION_PATH/scripts/comment_on_pr.sh" report.json
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: https://git.salame.cl/actions/upload-artifact@v4
|
||||||
|
if: inputs.generate-artifact == 'true'
|
||||||
|
with:
|
||||||
|
path: report.json
|
||||||
|
name: ${{ inputs.artifact-name }}
|
||||||
|
|
202419
dist/index.js
vendored
202419
dist/index.js
vendored
File diff suppressed because one or more lines are too long
1
dist/index.js.map
vendored
1
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
|
@ -1,61 +0,0 @@
|
||||||
// See: https://eslint.org/docs/latest/use/configure/configuration-files
|
|
||||||
|
|
||||||
import { fixupPluginRules } from '@eslint/compat'
|
|
||||||
import { FlatCompat } from '@eslint/eslintrc'
|
|
||||||
import js from '@eslint/js'
|
|
||||||
import _import from 'eslint-plugin-import'
|
|
||||||
import jest from 'eslint-plugin-jest'
|
|
||||||
import prettier from 'eslint-plugin-prettier'
|
|
||||||
import globals from 'globals'
|
|
||||||
import path from 'node:path'
|
|
||||||
import { fileURLToPath } from 'node:url'
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url)
|
|
||||||
const __dirname = path.dirname(__filename)
|
|
||||||
const compat = new FlatCompat({
|
|
||||||
baseDirectory: __dirname,
|
|
||||||
recommendedConfig: js.configs.recommended,
|
|
||||||
allConfig: js.configs.all
|
|
||||||
})
|
|
||||||
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
ignores: ['**/coverage', '**/dist', '**/linter', '**/node_modules']
|
|
||||||
},
|
|
||||||
...compat.extends(
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:jest/recommended',
|
|
||||||
'plugin:prettier/recommended'
|
|
||||||
),
|
|
||||||
{
|
|
||||||
plugins: {
|
|
||||||
import: fixupPluginRules(_import),
|
|
||||||
jest,
|
|
||||||
prettier
|
|
||||||
},
|
|
||||||
|
|
||||||
languageOptions: {
|
|
||||||
globals: {
|
|
||||||
...globals.node,
|
|
||||||
...globals.jest,
|
|
||||||
Atomics: 'readonly',
|
|
||||||
SharedArrayBuffer: 'readonly'
|
|
||||||
},
|
|
||||||
|
|
||||||
ecmaVersion: 2023,
|
|
||||||
sourceType: 'module'
|
|
||||||
},
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
camelcase: 'off',
|
|
||||||
'eslint-comments/no-use': 'off',
|
|
||||||
'eslint-comments/no-unused-disable': 'off',
|
|
||||||
'i18n-text/no-en': 'off',
|
|
||||||
'import/no-namespace': 'off',
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-shadow': 'off',
|
|
||||||
'no-unused-vars': 'off',
|
|
||||||
'prettier/prettier': 'error'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -26,12 +26,10 @@
|
||||||
# Setup formatters
|
# Setup formatters
|
||||||
treefmt = {
|
treefmt = {
|
||||||
# Ignore images
|
# Ignore images
|
||||||
settings.global.excludes = [
|
settings.global.excludes = [ "*.png" ];
|
||||||
"*.png"
|
|
||||||
"dist/*"
|
|
||||||
];
|
|
||||||
projectRootFile = "flake.nix";
|
projectRootFile = "flake.nix";
|
||||||
programs = {
|
programs = {
|
||||||
|
mdformat.enable = true;
|
||||||
nixfmt.enable = true;
|
nixfmt.enable = true;
|
||||||
shfmt.enable = true;
|
shfmt.enable = true;
|
||||||
shellcheck.enable = true;
|
shellcheck.enable = true;
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
// See: https://jestjs.io/docs/configuration
|
|
||||||
|
|
||||||
/** @type {import('jest').Config} */
|
|
||||||
const jestConfig = {
|
|
||||||
clearMocks: true,
|
|
||||||
collectCoverage: true,
|
|
||||||
collectCoverageFrom: ['./src/**'],
|
|
||||||
coverageDirectory: './coverage',
|
|
||||||
coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
|
|
||||||
coverageReporters: ['json-summary', 'text', 'lcov'],
|
|
||||||
// Uncomment the below lines if you would like to enforce a coverage threshold
|
|
||||||
// for your action. This will fail the build if the coverage is below the
|
|
||||||
// specified thresholds.
|
|
||||||
// coverageThreshold: {
|
|
||||||
// global: {
|
|
||||||
// branches: 100,
|
|
||||||
// functions: 100,
|
|
||||||
// lines: 100,
|
|
||||||
// statements: 100
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
moduleFileExtensions: ['js'],
|
|
||||||
reporters: ['default'],
|
|
||||||
testEnvironment: 'node',
|
|
||||||
testMatch: ['**/*.test.js'],
|
|
||||||
testPathIgnorePatterns: ['/dist/', '/node_modules/'],
|
|
||||||
verbose: true
|
|
||||||
}
|
|
||||||
|
|
||||||
export default jestConfig
|
|
12141
package-lock.json
generated
12141
package-lock.json
generated
File diff suppressed because it is too large
Load diff
66
package.json
66
package.json
|
@ -1,66 +0,0 @@
|
||||||
{
|
|
||||||
"name": "nix-flake-outputs-size-report",
|
|
||||||
"description": "Use 'nix-path-info' to query the size of outputs and produce a markdown report",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"author": "Jalil David Salamé Messina",
|
|
||||||
"type": "module",
|
|
||||||
"private": true,
|
|
||||||
"homepage": "https://git.salame.cl/jalil/nix-flake-outputs-size#readme",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://git.salame.cl/jalil/nix-flake-outputs-size.git"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://git.salame.cl/jalil/nix-flake-outputs-size/issues"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"actions"
|
|
||||||
],
|
|
||||||
"exports": {
|
|
||||||
".": "./dist/index.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"bundle": "npm run format:write && npm run package",
|
|
||||||
"ci-test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest",
|
|
||||||
"coverage": "npx make-coverage-badge --output-path ./badges/coverage.svg",
|
|
||||||
"format:write": "npx prettier --write .",
|
|
||||||
"format:check": "npx prettier --check .",
|
|
||||||
"lint": "npx eslint .",
|
|
||||||
"local-action": "npx @github/local-action . src/main.js .env",
|
|
||||||
"package": "npx rollup --config rollup.config.js",
|
|
||||||
"package:watch": "npm run package -- --watch",
|
|
||||||
"test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest",
|
|
||||||
"all": "npm run format:write && npm run lint && npm run test && npm run coverage && npm run package"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@actions/artifact": "^2.3.2",
|
|
||||||
"@actions/core": "^1.11.1",
|
|
||||||
"@actions/exec": "^1.1.1",
|
|
||||||
"@actions/github": "^6.0.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@eslint/compat": "^1.3.1",
|
|
||||||
"@github/local-action": "^3.2.1",
|
|
||||||
"@jest/globals": "^30.0.4",
|
|
||||||
"@rollup/plugin-commonjs": "^28.0.6",
|
|
||||||
"@rollup/plugin-json": "^6.1.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
||||||
"eslint": "^9.30.1",
|
|
||||||
"eslint-config-prettier": "^10.1.5",
|
|
||||||
"eslint-plugin-import": "^2.32.0",
|
|
||||||
"eslint-plugin-jest": "^29.0.1",
|
|
||||||
"eslint-plugin-prettier": "^5.5.1",
|
|
||||||
"jest": "^30.0.4",
|
|
||||||
"make-coverage-badge": "^1.2.0",
|
|
||||||
"prettier": "^3.6.2",
|
|
||||||
"prettier-eslint": "^16.4.2",
|
|
||||||
"rollup": "^4.44.2"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@rollup/rollup-linux-x64-gnu": "*"
|
|
||||||
}
|
|
||||||
}
|
|
11
report.json
11
report.json
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"packages": [
|
|
||||||
{
|
|
||||||
"name": "hello",
|
|
||||||
"size": 33159640,
|
|
||||||
"narSize": 234680
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nixosConfigurations": [],
|
|
||||||
"homeConfigurations": []
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
// See: https://rollupjs.org/introduction/
|
|
||||||
|
|
||||||
import commonjs from '@rollup/plugin-commonjs'
|
|
||||||
import json from '@rollup/plugin-json'
|
|
||||||
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
input: 'src/index.js',
|
|
||||||
output: {
|
|
||||||
esModule: true,
|
|
||||||
file: 'dist/index.js',
|
|
||||||
format: 'es',
|
|
||||||
sourcemap: true
|
|
||||||
},
|
|
||||||
plugins: [commonjs(), json(), nodeResolve({ preferBuiltins: true })]
|
|
||||||
}
|
|
||||||
|
|
||||||
export default config
|
|
|
@ -7,24 +7,25 @@ util_path="${GITHUB_ACTION_PATH:-.}/scripts/utils.sh"
|
||||||
# shellcheck source=scripts/utils.sh
|
# shellcheck source=scripts/utils.sh
|
||||||
. "${util_path}"
|
. "${util_path}"
|
||||||
|
|
||||||
group 'Retrieving Flake information'
|
|
||||||
flake_info=$(nix flake show --json --quiet --quiet)
|
|
||||||
endgroup
|
|
||||||
|
|
||||||
system=$(nix eval --impure --json --expr 'builtins.currentSystem')
|
system=$(nix eval --impure --json --expr 'builtins.currentSystem')
|
||||||
|
|
||||||
group 'Show Packages'
|
# Extract the names of a flake attrset
|
||||||
packages=$(echo "$flake_info" | jq --raw-output --argjson system "$system" 'getpath(["packages", $system]) | select(. != null) | keys[]')
|
get_names() {
|
||||||
|
nix eval --json --apply builtins.attrNames "$1" 2>/dev/null | jq --raw-output '.[]'
|
||||||
|
}
|
||||||
|
|
||||||
|
group "Show Packages for $system"
|
||||||
|
packages=$(get_names .#packages."$system")
|
||||||
[ -z "$packages" ] || log "$packages"
|
[ -z "$packages" ] || log "$packages"
|
||||||
endgroup
|
endgroup
|
||||||
|
|
||||||
group 'Show Home Manager Configurations'
|
group 'Show Home Manager Configurations'
|
||||||
hmConfigs=$(echo "$flake_info" | jq --raw-output '.homeConfigurations | select(. != null) | keys[]')
|
hmConfigs=$(get_names .#homeConfigurations)
|
||||||
[ -z "$hmConfigs" ] || log "$hmConfigs"
|
[ -z "$hmConfigs" ] || log "$hmConfigs"
|
||||||
endgroup
|
endgroup
|
||||||
|
|
||||||
group 'Show NixOS Configurations'
|
group 'Show NixOS Configurations'
|
||||||
nixosConfigs=$(echo "$flake_info" | jq --raw-output '.nixosConfigurations | select(. != null) | keys[]')
|
nixosConfigs=$(get_names .#nixosConfigurations)
|
||||||
[ -z "$nixosConfigs" ] || log "$nixosConfigs"
|
[ -z "$nixosConfigs" ] || log "$nixosConfigs"
|
||||||
endgroup
|
endgroup
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ pkgs_json() {
|
||||||
hm_configs_json() {
|
hm_configs_json() {
|
||||||
for config in $hmConfigs; do
|
for config in $hmConfigs; do
|
||||||
log "Building $config"
|
log "Building $config"
|
||||||
path=$(nix build --print-out-paths ".#homeConfigurations.$config.activationPackages")
|
path=$(nix build --print-out-paths ".#homeConfigurations.$config.config.home.activationPackage")
|
||||||
closure_size "$config" "$path"
|
closure_size "$config" "$path"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,9 @@ has_report() {
|
||||||
# If a base branch is not provided, use the default branch
|
# If a base branch is not provided, use the default branch
|
||||||
base_branch=${BASE_BRANCH:-$(default_branch)}
|
base_branch=${BASE_BRANCH:-$(default_branch)}
|
||||||
|
|
||||||
if [ "$(in_private_repo)" != 'true' ] && [ "$JOB_NAME" ]; then
|
if in_private_repo; then
|
||||||
|
warn 'Detected that this is a private repo cannot retrieve old report'
|
||||||
|
elif [ "$JOB_NAME" ]; then
|
||||||
url=$(base_report_url "$base_branch")
|
url=$(base_report_url "$base_branch")
|
||||||
|
|
||||||
log "Found previous run at: $url"
|
log "Found previous run at: $url"
|
||||||
|
@ -56,13 +58,14 @@ if [ "$(in_private_repo)" != 'true' ] && [ "$JOB_NAME" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
error "Failed to find previous report, expected at: $report_url"
|
error "Failed to find previous report, expected at: $report_url"
|
||||||
|
else
|
||||||
|
panic 'job-name is missing, therefore we cannot find the previous report'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
warn "Couldn't retrieve old report:"
|
warn "Couldn't retrieve old report:
|
||||||
warn ' This usuially happens when running on private repos'
|
note: This usually happens when running on private repos or when job-name is not set.
|
||||||
warn ' or when job-name is not set.'
|
|
||||||
warn
|
See the README for more details"
|
||||||
warn ' See the README for more details'
|
|
||||||
|
|
||||||
error "Falling back to slow method (checkout $base_branch and generate the report)"
|
error "Falling back to slow method (checkout $base_branch and generate the report)"
|
||||||
|
|
||||||
|
|
61
scripts/run.sh
Executable file
61
scripts/run.sh
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. "$GITHUB_ACTION_PATH/scripts/utils.sh"
|
||||||
|
|
||||||
|
# Input validation
|
||||||
|
if [ "$COMMENT" != "true" ] && [ "$GENERATE_ARTIFACT" != "true" ]; then
|
||||||
|
panic 'Neither comment-on-pr nor generate-artifact is set
|
||||||
|
note: this looks like an error; if it isn'"'"'t disable this action with "step.if"'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$DO_COMPARISON" = 'true' ] && [ -z "$JOB_NAME" ]; then
|
||||||
|
panic 'Requested a comparison report but job-name wasn'"'"'t set'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create Size Report (will be uploaded by the upload-artifact action)
|
||||||
|
"$GITHUB_ACTION_PATH/scripts/create-report.sh" report.json
|
||||||
|
|
||||||
|
# Nothing else to do
|
||||||
|
if [ "$COMMENT" != "true" ]; then exit 0; fi
|
||||||
|
|
||||||
|
# Find the PR for this commit so we can post a comment on it
|
||||||
|
pr_number=
|
||||||
|
case "$GITHUB_EVENT_NAME" in
|
||||||
|
"pull_request")
|
||||||
|
pr_number=$(jq .number "$GITHUB_EVENT_PATH")
|
||||||
|
log "Triggered by a pull request with index: $pr_number"
|
||||||
|
;;
|
||||||
|
"push")
|
||||||
|
log "Triggered by a push to $GITHUB_REF_NAME autodetecting PR number"
|
||||||
|
|
||||||
|
log "Get PR number for $GITHUB_REF_NAME"
|
||||||
|
prs=$(curl -X 'GET' \
|
||||||
|
"$GITHUB_API_URL/repos/$GITHUB_REPOSITORY/pulls?state=open&sort=recentupdate" \
|
||||||
|
-H "Authorization: token $GITHUB_TOKEN" \
|
||||||
|
-H 'Accept: application/json')
|
||||||
|
|
||||||
|
log "Found these open PRs: $(echo "$prs" | jq '[.[] | .number]')"
|
||||||
|
|
||||||
|
pr_number=$(echo "$prs" |
|
||||||
|
jq --arg ref "$GITHUB_REF_NAME" '.[] | select(.head.ref == $ref) | .number')
|
||||||
|
|
||||||
|
# Protect against running before a PR is made or if it is triggered on the main branch
|
||||||
|
if [ -z "$pr_number" ]; then
|
||||||
|
warn "No PR created for this commit"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "The PR we found for $GITHUB_REF_NAME is $pr_number"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
panic "Unexpected event $GITHUB_EVENT_NAME for commenting on a PR, expected push or pull_request"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
log "Expected PR URL: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/pulls/$pr_number"
|
||||||
|
|
||||||
|
# This seems to create the file???
|
||||||
|
log "GITHUB_OUTPUT=$GITHUB_OUTPUT"
|
||||||
|
log "$(ls -l "$GITHUB_OUTPUT")"
|
||||||
|
|
||||||
|
echo "pr-number=$pr_number" >>"$GITHUB_OUTPUT"
|
|
@ -12,6 +12,11 @@ error() {
|
||||||
log "\e[0;31m[WARN]:" "$@" "\e[0m"
|
log "\e[0;31m[WARN]:" "$@" "\e[0m"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic() {
|
||||||
|
error "$@"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
group() {
|
group() {
|
||||||
echo "::group::$1"
|
echo "::group::$1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
/**
|
|
||||||
* The entrypoint for the action. This file simply imports and runs the action's
|
|
||||||
* main logic.
|
|
||||||
*/
|
|
||||||
import { run } from './main.js'
|
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
run()
|
|
145
src/main.js
145
src/main.js
|
@ -1,145 +0,0 @@
|
||||||
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.trim()
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue