Skip to content
This repository was archived by the owner on May 30, 2026. It is now read-only.

fix: make action builds reproducible and drop license sidecars - #96

Merged
C. Spencer Beggs (spencerbeggs) merged 2 commits into
mainfrom
fix/94-idempotent-builds
May 30, 2026
Merged

C. Spencer Beggs (spencerbeggs) merged 2 commits into
mainfrom
fix/94-idempotent-builds

Conversation

@spencerbeggs

Copy link
Copy Markdown
Contributor

Fixes both issues reported in #94.

Non-idempotent builds — when build.ignore was set, the ignore stub was written to a random mkdtemp directory whose absolute path rspack embedded in the bundle as a module id, so building the same source twice produced byte-different output and noisy diffs in committed action code. The stub now lives at a deterministic node_modules/.cache/github-action-builder/ignore-stub.mjs path (project-local, preserving the symlink-safety property from the #81 design), so repeated builds are byte-identical.

License sidecars — bundled third-party license banners are kept inline via output.legalComments: "inline" instead of being extracted to *.LICENSE.txt sidecar files, removing the extra committed file while preserving attribution.

Adds integration regression tests: one builds a fixture twice and asserts byte-identical main.js; one asserts no *.LICENSE.txt and that the notice stays inline. Full unit + integration suite green, typecheck green.

Closes #94

Signed-off-by: C. Spencer Beggs spencer@savvyweb.systems

When build.ignore was set, the ignore stub went to a random mkdtemp dir whose path rspack embedded in the bundle, so the same source built twice produced byte-different output. The stub now uses a deterministic node_modules/.cache path, so repeated builds are byte-identical.

Bundled third-party license banners are kept inline via output.legalComments instead of being extracted to *.LICENSE.txt sidecar files, removing the extra committed file while preserving attribution.

Closes #94
Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>

@savvy-web-bot savvy-web-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Current Commit: 3e8e612

Summary

Clean, well-scoped fix for both issues in #94. The root cause diagnosis is correct: rspack embeds the stub path verbatim as the module id, so mkdtemp made the bundle non-deterministic. Moving to a fixed node_modules/.cache path is the right call — project-local (preserving the #81 symlink-safety property), deterministic, and the writeFile helper already creates parent directories with mkdirSync({ recursive: true }), so no extra scaffolding is needed. The legalComments: "inline" addition is minimal and correct.

The integration tests are well-structured: isolated mkdtempSync copies prevent fixture contamination, and the two-build hash comparison is a reliable regression gate.

Two items to clean up before merging:

Issues

.gitignore — duplicate entry and wrong comment

See inline comment on .gitignore lines 34–38. .claude/settings.local.json is listed twice, and the section comment ("Temporary api-extractor files created during build") is a copy-paste artifact that describes none of the entries under it.

idempotent-build.int.test.ts — debug writes left in

See inline comment on lines 76–78. The writeFileSync calls to /tmp/issue94-*.js were useful while debugging but should be removed before merge. The writeFileSync import at line 9 becomes unused once they're gone.

Checks

All five validation checks passed: PR Title Validation, Conventional Commits, Code Quality, Markdown, Tests ✓

Comment thread .gitignore Outdated
Comment on lines +34 to +38
# Temporary api-extractor files created during build
.claude/settings.local.json
.claude/scheduled_tasks.lock
.claude/plans
.claude/cache

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two problems with this block:

  1. Duplicate entry — .claude/settings.local.json already appears on line 33 (under # Claude AI files). The new entry on line 35 is an exact duplicate and can be dropped.

  2. Misleading comment — # Temporary api-extractor files created during build describes none of the entries below it. These are Claude AI runtime files. The comment should either be removed or corrected (e.g. # Claude AI runtime files).

Comment on lines +76 to +78
// Dump both bundles for out-of-band diffing while diagnosing the bug.
writeFileSync("/tmp/issue94-a.js", first);
writeFileSync("/tmp/issue94-b.js", second);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three lines are debug diagnostic artifacts — the comment even says "while diagnosing the bug." They should be removed before merging. The writes to /tmp are harmless but the writeFileSync import at line 9 becomes unused once they're gone, so that import should be cleaned up too.

Drop the duplicate .claude/settings.local.json entry and the misleading api-extractor comment from .gitignore, and remove the leftover /tmp debug dumps and now-unused writeFileSync import from the idempotency test.

Signed-off-by: C. Spencer Beggs <spencer@savvyweb.systems>
@spencerbeggs
C. Spencer Beggs (spencerbeggs) merged commit 3a389c9 into main May 30, 2026
16 of 18 checks passed
@spencerbeggs
C. Spencer Beggs (spencerbeggs) deleted the fix/94-idempotent-builds branch May 30, 2026 03:40
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Non-idepoment Builds

1 participant