{"id":36964701,"url":"https://github.com/ext/artifact-size-analyzer","last_synced_at":"2026-01-13T19:43:19.022Z","repository":{"id":328426690,"uuid":"1111460032","full_name":"ext/artifact-size-analyzer","owner":"ext","description":"Zero-opinion tool to analyze and compare artifact sizes across branches and CI runs.","archived":false,"fork":false,"pushed_at":"2026-01-11T13:38:44.000Z","size":692,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T14:59:45.342Z","etag":null,"topics":["artifact","build","bundle","ci","pull-requests","size"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ext.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"ext"}},"created_at":"2025-12-07T01:17:16.000Z","updated_at":"2026-01-11T13:38:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ext/artifact-size-analyzer","commit_stats":null,"previous_names":["ext/pull-request-bundle-analyzer"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/ext/artifact-size-analyzer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ext%2Fartifact-size-analyzer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ext%2Fartifact-size-analyzer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ext%2Fartifact-size-analyzer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ext%2Fartifact-size-analyzer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ext","download_url":"https://codeload.github.com/ext/artifact-size-analyzer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ext%2Fartifact-size-analyzer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28397826,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["artifact","build","bundle","ci","pull-requests","size"],"created_at":"2026-01-13T19:43:18.362Z","updated_at":"2026-01-13T19:43:19.015Z","avatar_url":"https://github.com/ext.png","language":"TypeScript","funding_links":["https://github.com/sponsors/ext"],"categories":[],"sub_categories":[],"readme":"# Artifact size analyzer\n\nA small, zero-opinion tool to analyze and compare the sizes of build artifacts across branches and CI runs.\nIdeal for pull requests — it highlights size regressions and tracks compressed and uncompressed artifact sizes.\n\n- ✅ Configurable: include/exclude files and compression algorithms\n- ✅ Agnostic: works with any language or toolchain\n- ✅ Multi-artifact: measure multiple artifacts in one pass\n- ✅ Outputs: JSON, Markdown, and plain text (for Actions, CLI, and API)\n\n![Screenshot of a pull request comment made by this GitHub Action](https://raw.githubusercontent.com/ext/artifact-size-analyzer/refs/heads/main/example-comment.png)\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Configuration file](#configuration-file)\n- [Using with GitHub Actions](#using-with-github-actions)\n- [Using with CLI](#using-with-cli)\n- [Using with API](#using-with-api)\n- [Development](#development)\n\n## Installation\n\nInstall as a dev dependency (recommended):\n\n```bash\nnpm install --save-dev artifact-size-analyzer\n```\n\n## Configuration file\n\nThe config file describes artifacts to analyze.\n\n```json\n{\n  \"artifacts\": [\n    {\n      \"id\": \"app\",\n      \"name\": \"app\",\n      \"include\": \"dist/**/*.js\"\n    }\n  ]\n}\n```\n\n### Options\n\n#### `artifacts[].id`\n\nType: `string`  \nRequired: yes\n\nUnique identifier for this artifact.\n\n#### `artifacts[].name`\n\nType: `string`  \nRequired: yes\n\nDisplay name for this artifact.\n\n#### `artifacts[].include`\n\nType: `string | string[]`  \nRequired: no  \nDefault: `[]`\n\nFiles to include for this artifact (globs supported).\n\n#### `artifacts[].exclude`\n\nType: `string | string[]`  \nRequired: no  \nDefault: `[]`\n\nFiles to exclude for this artifact (globs supported).\n\n#### `artifacts[].compression`\n\nType: `string | string[] | false`  \nRequired: no  \nDefault: `[\"gzip\", \"brotli\"]`\n\nCompression algorithm(s) to enable for this artifact or `false` to disable compression.\n\nSupported compression algorithms:\n\n- `gzip`\n- `brotli`\n\n## Using with GitHub Actions\n\nThe recommended pattern is three jobs:\n\n- **Analyze (base)**: on the pull request target branch run the `analyze` action to produce a baseline.\n- **Analyze (current)**: on the PR head ref, run the `analyze` action to produce artifact data for the current commit.\n- **Compare**: run the `compare` action to compare the two artifacts.\n\n\u003e [!IMPORTANT]\n\u003e Both the `analyze` and `compare` actions assume you perform the `checkout` and `setup-node` steps in the workflow (see example workflow below).\n\nOn target branch:\n\n```yaml\n- name: Run analyzer\n  uses: ext/artifact-size-analyzer/analyze@v1\n  with:\n    config-file: ./example-config.json\n    artifact-name: base-size\n```\n\nOn head branch:\n\n```yaml\n- name: Run analyzer\n  uses: ext/artifact-size-analyzer/analyze@v1\n  with:\n    config-file: ./example-config.json\n    artifact-name: current-size\n```\n\nTo compare:\n\n```yaml\n- name: Compare results\n  id: compare\n  uses: ext/artifact-size-analyzer/compare@v1\n  with:\n    base-artifact: base-size\n    current-artifact: current-size\n```\n\nExample workflow:\n\n\u003cdetails\u003e\n\u003csummary\u003eartifact-size.yml\u003c/summary\u003e\n\n```yaml\nname: Artifact size\n\non:\n  pull_request:\n    types: [opened, synchronize, reopened]\n\njobs:\n  analyze-base:\n    name: Analyze (base)\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout target branch\n        uses: actions/checkout@v6\n        with:\n          ref: ${{ github.event.pull_request.base.ref }}\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v6\n\n      - name: Install \u0026 build\n        run: |\n          npm ci\n          npm run build\n\n      - name: Run analyzer\n        uses: ext/artifact-size-analyzer/analyze@v1\n        with:\n          config-file: ./example-config.json\n          artifact-name: base-size\n\n  analyze-current:\n    name: Analyze (current)\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout head ref\n        uses: actions/checkout@v6\n        with:\n          ref: ${{ github.event.pull_request.head.ref }}\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v6\n\n      - name: Install \u0026 build\n        run: |\n          npm ci\n          npm run build\n\n      - name: Run analyzer (current)\n        uses: ext/artifact-size-analyzer/analyze@v1\n        with:\n          config-file: ./example-config.json\n          artifact-name: current-size\n\n  compare:\n    name: Compare\n    runs-on: ubuntu-latest\n    needs: [analyze-base, analyze-current]\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v6\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v6\n\n      - name: Compare results\n        id: compare\n        uses: ext/artifact-size-analyzer/compare@v1\n        with:\n          base-artifact: base-size\n          current-artifact: current-size\n\n      - name: Print markdown\n        run: |\n          echo \"Compare markdown output:\"\n          echo \"========================\"\n          echo \"${{ steps.compare.outputs.markdown }}\"\n```\n\n\u003c/details\u003e\n\nThe output from the `compare` action can be used in a pull request comment, this example uses [`marocchino/sticky-pull-request-comment`](https://github.com/marocchino/sticky-pull-request-comment) but you can use any you like.\n\n````yaml\n- name: Post sticky PR comment\n  uses: marocchino/sticky-pull-request-comment@v2\n  with:\n    header: artifact-size-analyzer\n    message: |\n      ${{ steps.compare.outputs.markdown }}\n\n      \u003cdetails\u003e\u003csummary\u003eRaw JSON\u003c/summary\u003e\n\n      ```json\n      ${{ steps.compare.outputs.json }}\n      ```\n\n      \u003c/details\u003e\n````\n\n### Analyze inputs\n\n#### `artifact-name`\n\nType: `string`  \nRequired: yes\n\nName of the GitHub artifact to upload.\n\n#### `config-file`\n\nType: `string`  \nRequired: yes\n\nPath to the artifact configuration.\n\n#### `output-file`\n\nType: `string`  \nRequired: no  \nDefault: `temp/artifact-size.json`\n\nPath to the output file to be produced by the analyzer.\nCan optionally specify the format as a prefix `format:filename`, where `format` is `json`, `markdown`, or `text`.\n\nTo use the `compare` action the format must be `json`.\n\n#### `no-header`\n\nType: `boolean`  \nRequired: no  \nDefault: `false`\n\nWhen set to `true`, disables the header in output for formats with headers such as Markdown.\n\nUse this when you want to prepend your own heading or other content before the size table.\n\n#### `version`\n\nType: `string`  \nRequired: no\n\nOptional npm package version (e.g. `1.2.3`).\nWhen provided, the action runs `npx artifact-size-analyzer@\u003cversion\u003e`.\n\nBy default it uses the installed version.\n\n#### `config-from`\n\nType: `string`  \nRequired: no  \nDefault: `head`\n\nWhich branch to use for the configuration file:\n\n- `head`: Uses the PR head branch (default)\n- `target`: Uses the PR target branch\n- `local`: Uses the currently checked out branch\n\n### Compare inputs\n\n#### `base-artifact`\n\nType: `string`  \nRequired: yes\n\nGitHub artifact name for the base run (uploaded by `analyze`).\n\n#### `current-artifact`\n\nType: `string`  \nRequired: yes\n\nGitHub artifact name for the current run (uploaded by `analyze`).\n\n#### `base-name`\n\nType: `string`  \nRequired: no  \nDefault: `artifact-size.json`\n\nFile name inside the base artifact that contains the analyzer output.\n\nThis should match the filename from the `output-file` input of the analyzer action.\n\nNote: `base-name` and `current-name` refer to the path of the analyzer file inside the uploaded artifact; they must match the path passed to `analyze`'s `--output-file`.\n\n#### `current-name`\n\nType: `string`  \nRequired: no  \nDefault: `artifact-size.json`\n\nFile name inside the current artifact that contains the analyzer output.\n\nThis should match the filename from the `output-file` input of the analyzer action.\n\n#### `version`\n\nType: `string`  \nRequired: no\n\nOptional npm package version (e.g. `1.2.3`).\nWhen provided, the action runs `npx artifact-size-analyzer@\u003cversion\u003e`.\n\nBy default it uses the installed version.\n\n#### `no-header`\n\nType: `boolean`  \nRequired: no  \nDefault: `false`\n\nWhen set to `true`, disables the header in output for formats with headers such as Markdown.\n\nUse this when you want to prepend your own heading or other content before the size table.\n\n#### `unchanged`\n\nType: `string`  \nRequired: no  \nDefault: `collapse`\n\nControls how artifacts with unchanged sizes are handled:\n\n- `show`: Display all artifacts\n- `hide`: Hide unchanged artifacts from output\n- `collapse`: Show unchanged artifacts in a collapsible `\u003cdetails\u003e` section (default)\n\nUse `collapse` for pull request comments to keep the main table focused while still showing all artifacts in an expandable section.\n\n### Compare outputs\n\n#### `json`\n\nType: `string`\n\nThe comparison result formatted as JSON.\n\n#### `markdown`\n\nType: `string`\n\nThe comparison result formatted as Markdown.\n\n#### `text`\n\nType: `string`\n\nThe comparison result formatted as plain text.\n\n## Using with CLI\n\nCreate a baseline (on the default branch):\n\n```bash\nnpx artifact-size-analyzer analyze -c example-config.json -f json -o temp/base.json\n```\n\nAnalyze current artifact(s) (on the feature branch):\n\n```bash\nnpx artifact-size-analyzer analyze -c example-config.json -f json -o temp/current.json\n```\n\nCompare the results:\n\n```bash\nnpx artifact-size-analyzer compare --base temp/base.json --current temp/current.json\n```\n\n### Usage\n\n```bash\nnpx artifact-size-analyzer \u003ccommand\u003e [options]\n```\n\nwhere `command` is one of:\n\n- `analyze`: Analyze artifacts defined in a config file.\n- `compare`: Compare two previously saved analysis outputs.\n\n### Analyze\n\nAnalyze artifacts from a config file and print results or write to a file.\n\n```bash\nnpx artifact-size-analyzer analyze -c example-config.json\nnpx artifact-size-analyzer analyze -c example-config.json -f json -o temp/base.json\n```\n\nOptions:\n\n- `-c, --config-file \u003cpath\u003e`: Path to the config file (required)\n- `-f, --format \u003ctext|json|markdown\u003e`: Output format (default: `text`)\n- `-o, --output-file \u003cformat:filename|filename\u003e`: Write output to file instead of stdout. Can be specified multiple times. If `format` is omitted the value from `--format` is used.\n\n### Compare\n\nCompare two saved results and print the diff.\nThe files should be the JSON outputs produced by `analyze -f json`.\n\n```bash\nnpx artifact-size-analyzer compare --base base.json --current current.json -f text\n```\n\nOptions:\n\n- `--base \u003cpath\u003e`: Baseline JSON file produced by `analyze` (required)\n- `--current \u003cpath\u003e`: Current JSON file produced by `analyze` (required)\n- `-f, --format \u003ctext|json|markdown\u003e`: Output format (default: `text`)\n- `--unchanged \u003cshow|hide|collapse\u003e`: Control how artifacts with unchanged sizes are handled (default: `show`)\n  - `show`: Display all artifacts\n  - `hide`: Hide unchanged artifacts from output\n  - `collapse`: Show unchanged artifacts in a collapsible `\u003cdetails\u003e` section\n- `-o, --output-file \u003cpath\u003e`: Write output to file instead of stdout\n\n## Using with API\n\nProgrammatic usage is supported via the library exports.\n\nTo analyze an artifact:\n\n```ts\nimport { analyzeArtifact } from \"artifact-size-analyzer\";\n\n/* compression algorithm options */\nconst compression = {\n  gzip: false,\n  brotli: false,\n};\n\n/* artifact configuration (similar to the configuration file) */\nconst artifact = {\n  id: \"dist\",\n  name: \"dist\",\n  include: [\"dist/**/*.js\"],\n  exclude: [],\n};\n\n/* analyzes the configured artifact */\nconst result = await analyzeArtifact(artifact, { cwd: process.cwd(), compression });\n\nconsole.log(\"Result:\", result);\n```\n\nTo compare two artifacts:\n\n```ts\nimport fs from \"node:fs/promises\";\nimport { type ArtifactSize, compareArtifact } from \"artifact-size-analyzer\";\n\n/* previously saved output from `analyzeArtifact()` */\nconst base = JSON.parse(await fs.readFile(\"base.json\", \"utf8\")) as ArtifactSize;\nconst current = JSON.parse(await fs.readFile(\"current.json\", \"utf8\")) as ArtifactSize;\n\n/* compares the two artifacts */\nconst result = compareArtifact(base, current);\n\nconsole.log(\"Result:\", result);\n```\n\nYou can format the output of `analyzeArtifact` and `compareArtifact()` using `formatArtifact()` and `formatDiff()`:\n\n```ts\nimport { formatDiff } from \"artifact-size-analyzer\";\n\nconst output = formatDiff([result], \"markdown\");\nconsole.log(output);\n```\n\nOther noteworthy functions:\n\n- `readConfigFile()` reads, validates and normalizes a configuration file.\n- `compareArtifacts()` takes two arrays of base and current artifacts and runs `compareArtifact()` on each pair (based on `id`).\n\n## Development\n\nBuild the project locally:\n\n```bash\nnpm install\nnpm run build\n```\n\nRun tests and linting during development:\n\n```bash\nnpm test\nnpm run eslint\nnpm run prettier:check\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fext%2Fartifact-size-analyzer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fext%2Fartifact-size-analyzer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fext%2Fartifact-size-analyzer/lists"}