Skip to content

Commit c7ccc79

Browse files
authored
feat: support npm release history baselines (#14)
1 parent 0ab1edd commit c7ccc79

42 files changed

Lines changed: 1321 additions & 155 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ body:
2626
id: inputs
2727
attributes:
2828
label: Action inputs
29-
description: Include values such as `path`, `tarball-uri`, `files`, `output-file`, and whether `comment-pr` is enabled. Redact private URLs if needed.
29+
description: Include values such as `path`, `package-name`, `files`, `output-file`, and whether `comment-pr` is enabled.
3030
render: yaml
3131
validations:
3232
required: false

.github/workflows/bundle-size.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ jobs:
9494
uses: ./
9595
with:
9696
path: "bundle-size-fixture"
97-
tarball-uri: "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz"
97+
package-name: "is-number"
9898
files: |
9999
index.js
100100
output-file: "bundle-size-comparison.json"

AGENTS.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ This repo is a TypeScript GitHub Action for comparing bundle sizes. The action r
88

99
Core behavior today:
1010

11-
- Accepts a `tarball-uri` baseline archive.
11+
- Accepts an npm `package-name` baseline.
1212
- Accepts newline-delimited `files` to compare.
1313
- Resolves local files under `path`.
14+
- Resolves npm release tarballs for the latest release plus up to 10 previous stable releases.
1415
- Resolves tarball files relative to the archive root, stripping a single shared top-level directory such as `package/`.
1516
- Measures gzip-compressed byte size.
1617
- Writes a JSON comparison report.
@@ -24,6 +25,7 @@ Current modules:
2425

2526
- `src/action.ts`: orchestrates the GitHub Action run and action outputs.
2627
- `src/config.ts`: reads and validates `@actions/core` inputs.
28+
- `src/npm.ts`: resolves npm package metadata and release tarball baselines.
2729
- `src/paths.ts`: normalizes configured paths and prevents path traversal.
2830
- `src/tarball.ts`: downloads tarballs and extracts regular files from `.tar.gz` archives.
2931
- `src/comparison.ts`: computes gzip sizes and per-file/totals deltas.
@@ -56,7 +58,7 @@ When asked to commit changes in this repository, use Conventional Commit message
5658
- Runtime dependencies should stay small. Prefer Node built-ins when they are clear and maintainable.
5759
- Do not assume the caller has installed dependencies at action runtime.
5860
- Do not build the target project inside the action; workflows should build artifacts before invoking this action.
59-
- Treat missing configured files as errors. A comparison report should only be produced from trustworthy inputs.
61+
- Treat missing configured local files and latest-release baseline files as errors. Historical previous-release missing files may be reported as incomplete context.
6062

6163
## Tarball And Path Handling
6264

@@ -103,13 +105,13 @@ This repo uses OpenSpec for scoped changes.
103105

104106
When implementing a spec-driven change, read proposal, design, specs, and tasks before editing. Mark tasks complete as they are implemented. If a change introduces or modifies requirements, sync the delta spec into `openspec/specs/` before archiving.
105107

106-
The current tarball gzip behavior is captured in `openspec/specs/tarball-gzip-comparison/spec.md`.
108+
The current tarball gzip behavior is captured in `openspec/specs/tarball-gzip-comparison/spec.md`. Npm release baseline behavior is captured in `openspec/specs/npm-release-baselines/spec.md` after the corresponding change is archived.
107109

108110
## Workflow Lessons Learned
109111

110112
- Keep action code modular early. A single `index.ts` becomes difficult to review once config parsing, tarball handling, path safety, gzip measurement, reporting, and GitHub outputs are all mixed together.
111113
- Preserve `path` as the local project root. New inputs should not overload it.
112-
- Treat the tarball URI as an explicit baseline contract. Do not add package-manager shorthand such as `npm:axios@latest` unless a spec/proposal calls for registry resolution.
114+
- Treat the npm package name as the release baseline contract. Do not add package-manager shorthand such as `npm:axios@latest` unless a spec/proposal calls for it.
113115
- Build comparison files on PRs from already-built local artifacts. On GitHub pull requests, the checkout/build represents the merge result when using the default PR merge ref.
114116
- Avoid target-size enforcement in the current capability. Reporting and enforcing are different product behaviors and should remain separate changes.
115117
- Keep `dist/index.js` synchronized with `src/`; otherwise the committed action will not match the reviewed TypeScript.

COLLABORATOR_GUIDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ For issues and discussions:
5757
- Keep unsupported feature requests open only when they fit the project direction.
5858
- Close issues that are duplicates, out of scope, or cannot be reproduced after reasonable follow-up.
5959

60-
This action compares already-built files. If a report is wrong, first verify the configured `path`, `files`, `tarball-uri`, and `output-file` values before assuming comparison logic is faulty.
60+
This action compares already-built files. If a report is wrong, first verify the configured `path`, `files`, `package-name`, and `output-file` values before assuming comparison logic is faulty.
6161

6262
## Security Reports
6363

CONTRIBUTING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing
22

3-
Thanks for helping improve `axios/bundle-size`. This repository contains a TypeScript GitHub Action that compares gzip bundle sizes against a tarball baseline.
3+
Thanks for helping improve `axios/bundle-size`. This repository contains a TypeScript GitHub Action that compares gzip bundle sizes against npm release baselines.
44

55
Please follow the [Code of Conduct](./CODE_OF_CONDUCT.md) when participating in this project.
66

@@ -36,6 +36,7 @@ Keep `src/index.ts` thin. Prefer focused modules for behavior:
3636

3737
- `src/action.ts`: action orchestration and outputs.
3838
- `src/config.ts`: action input parsing and validation.
39+
- `src/npm.ts`: npm registry release resolution.
3940
- `src/paths.ts`: path normalization and traversal protection.
4041
- `src/tarball.ts`: tarball download and parsing.
4142
- `src/comparison.ts`: gzip size calculation and report construction.
@@ -47,7 +48,7 @@ Keep `src/index.ts` thin. Prefer focused modules for behavior:
4748
- Keep changes small and focused.
4849
- Add or update tests for behavior changes.
4950
- Preserve the JSON report as machine-readable output.
50-
- Treat configured paths, tarball contents, and pull request input as untrusted.
51+
- Treat configured paths, npm metadata, tarball contents, and pull request input as untrusted.
5152
- Avoid new runtime dependencies unless there is a clear need.
5253
- Do not make the action build the caller's project; workflows should build artifacts before invoking this action.
5354

README.md

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Bundle Size Action
22

3-
A custom GitHub Action that compares gzip bundle sizes for built artifacts against matching files from a tarball baseline.
3+
A custom GitHub Action that compares gzip bundle sizes for built artifacts against matching files from npm release baselines.
44

55
---
66

@@ -47,8 +47,8 @@ There is no normal `lib/` workflow. Vite bundles the action directly from TypeSc
4747
| Name | Required | Default | Description |
4848
|------|----------|---------|-------------|
4949
| `path` | No | `.` | Path to the local project root containing built artifacts. |
50-
| `tarball-uri` | Yes | | HTTP(S) URI of the `.tar.gz` baseline archive to compare against. |
51-
| `files` | Yes | | Newline-delimited file paths to compare in the local project and tarball baseline. |
50+
| `package-name` | Yes | | npm package name whose latest and previous releases provide baseline archives. |
51+
| `files` | Yes | | Newline-delimited file paths to compare in the local project and npm release baselines. |
5252
| `output-file` | No | `bundle-size-comparison.json` | Path, relative to `path`, where the JSON comparison report will be written. |
5353
| `comment-pr` | No | `false` | Post or update a bundle size summary comment on pull requests. |
5454
| `github-token` | No | | GitHub token used to post pull request comments when `comment-pr` is enabled. |
@@ -60,8 +60,8 @@ There is no normal `lib/` workflow. Vite bundles the action directly from TypeSc
6060
| `size` | Total current gzip size in bytes for all compared files. |
6161
| `comparison-file` | Absolute path to the generated JSON comparison file. |
6262
| `total-current-gzip-size` | Total current gzip size in bytes for all compared files. |
63-
| `total-baseline-gzip-size` | Total baseline gzip size in bytes for all compared files. |
64-
| `total-delta-gzip-size` | Difference in gzip bytes between current and baseline totals. |
63+
| `total-baseline-gzip-size` | Total latest-release baseline gzip size in bytes for all compared files. |
64+
| `total-delta-gzip-size` | Difference in gzip bytes between current and latest-release baseline totals. |
6565

6666
---
6767

@@ -84,7 +84,7 @@ steps:
8484
uses: axios/bundle-size@main
8585
with:
8686
path: '.'
87-
tarball-uri: 'https://registry.npmjs.org/axios/-/axios-1.6.8.tgz'
87+
package-name: 'axios'
8888
files: |
8989
dist/axios.js
9090
dist/axios.min.js
@@ -109,7 +109,7 @@ steps:
109109
- name: Compare Bundle Size
110110
uses: axios/bundle-size@main
111111
with:
112-
tarball-uri: 'https://registry.npmjs.org/axios/-/axios-1.6.8.tgz'
112+
package-name: 'axios'
113113
files: |
114114
dist/axios.js
115115
dist/axios.min.js
@@ -124,7 +124,9 @@ The comparison file is JSON:
124124
```json
125125
{
126126
"metric": "gzip",
127+
"packageName": "axios",
127128
"baseline": {
129+
"version": "1.6.8",
128130
"uri": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz"
129131
},
130132
"localRoot": "/home/runner/work/project/project",
@@ -142,17 +144,52 @@ The comparison file is JSON:
142144
"currentBytes": 14512,
143145
"deltaBytes": 279,
144146
"deltaPercent": 1.96
145-
}
147+
},
148+
"history": [
149+
{
150+
"version": "1.6.8",
151+
"uri": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
152+
"latest": true,
153+
"complete": true,
154+
"missingFiles": [],
155+
"files": [
156+
{
157+
"path": "dist/axios.min.js",
158+
"baselineBytes": 14233,
159+
"currentBytes": 14512,
160+
"deltaBytes": 279,
161+
"deltaPercent": 1.96
162+
}
163+
],
164+
"totals": {
165+
"baselineBytes": 14233,
166+
"currentBytes": 14512,
167+
"deltaBytes": 279,
168+
"deltaPercent": 1.96
169+
}
170+
},
171+
{
172+
"version": "1.6.7",
173+
"uri": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
174+
"latest": false,
175+
"complete": false,
176+
"missingFiles": ["dist/axios.min.js"],
177+
"files": [],
178+
"totals": null
179+
}
180+
]
146181
}
147182
```
148183

184+
The latest npm release is the primary baseline for top-level `baseline`, `files`, `totals`, and action outputs. The `history` array includes the latest release plus up to 10 previous stable releases ordered by npm publish time. Previous releases that do not contain every configured file are marked as incomplete instead of failing the action.
185+
149186
Because this repository *is* the action, a workflow inside the same repo can reference it with `./` after preparing local files to compare:
150187

151188
```yaml
152189
- uses: ./
153190
with:
154191
path: 'bundle-size-fixture'
155-
tarball-uri: 'https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz'
192+
package-name: 'is-number'
156193
files: |
157194
index.js
158195
```
@@ -222,17 +259,18 @@ node dist/index.js
222259
To simulate GitHub Actions inputs locally, set the corresponding environment variables before running:
223260

224261
```bash
225-
INPUT_PATH="." \
226-
INPUT_TARBALL_URI="https://registry.npmjs.org/axios/-/axios-1.6.8.tgz" \
227-
INPUT_FILES=$'dist/axios.js\ndist/axios.min.js' \
228-
node dist/index.js
262+
env \
263+
'INPUT_PATH=.' \
264+
'INPUT_PACKAGE-NAME=axios' \
265+
INPUT_FILES=$'dist/axios.js\ndist/axios.min.js' \
266+
node dist/index.js
229267
```
230268

231269
---
232270

233271
## Current Behavior
234272

235-
The action downloads the configured tarball, reads regular file entries, strips a single shared top-level directory such as `package/`, and compares the configured paths against local files under `path`. It measures gzip-compressed bytes for each file and writes a JSON report. It does not enforce budgets or target sizes.
273+
The action fetches npm registry metadata for `package-name`, resolves the `latest` dist-tag plus up to 10 previous stable releases, downloads each selected release tarball, reads regular file entries, strips a single shared top-level directory such as `package/`, and compares the configured paths against local files under `path`. It measures gzip-compressed bytes for each file and writes a JSON report. It does not enforce budgets or target sizes.
236274

237275
Suggested next steps:
238276

@@ -241,7 +279,7 @@ Suggested next steps:
241279
| Threshold validation | Accept `max-size` input; call `core.setFailed` on breach |
242280
| Artifact uploads | Use `actions/upload-artifact` to persist the size report |
243281
| Multi-framework support | Auto-detect `vite.config.*`, `webpack.config.*`, etc. |
244-
| Package URI resolution | Resolve package manager aliases such as `npm:axios@latest` |
282+
| Private registry auth | Authenticate npm metadata and tarball requests |
245283

246284
---
247285

SECURITY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Out of scope examples:
5757

5858
## Secure Usage
5959

60-
- Use immutable `https:` tarball URLs for `tarball-uri` when possible.
60+
- Configure the intended npm `package-name` and review reports for the resolved latest release version.
6161
- Keep `files` and `output-file` relative to the configured `path` root.
6262
- Use minimal workflow permissions. JSON-only comparisons should not need write permissions.
6363
- Enable `comment-pr` only when PR comments are needed, and pass the default `${{ github.token }}` unless a stronger token is strictly required.

0 commit comments

Comments
 (0)