NP-790: Fix bundled action runtime preset loading + add e2e smoke test#5
Open
illiaizotov-dev wants to merge 3 commits intomasterfrom
Open
NP-790: Fix bundled action runtime preset loading + add e2e smoke test#5illiaizotov-dev wants to merge 3 commits intomasterfrom
illiaizotov-dev wants to merge 3 commits intomasterfrom
Conversation
Addresses ts-node-reviewer findings on the previous commit (4de84b0): * `runChildAndCapture` now listens for `error` on the child so a failed spawn (e.g. ENOENT on the node binary) folds the error into the captured stderr and resolves immediately instead of hanging until the SIGKILL timer fires. A `settled` guard protects against the close/error race. * The mock HTTP server's `listen` promise now attaches a one-shot `error` handler so a failed bind (EADDRINUSE on a constrained CI host, etc.) rejects with a useful message instead of letting the test silently wedge until Vitest's test timeout. * `src/action.ts` gains an explicit comment next to the preset pre- resolution explaining that upstream `load-changelog-config.js` never merges a plugin-supplied `commits` field, so `commitOpts` always comes from angular when no `preset` / `config` is passed. Harmless today (angular and conventionalcommits both default to `{ ignore: undefined, merges: false }`) but worth flagging for future upstream drift. No behavioural change to the shipping bundle — `esbuild` strips comments and the smoke test's runtime changes only affect error paths that previously caused hangs, not the happy path. All 37 tests across 5 files still pass; lint, prettier, and typecheck clean. Made-with: Cursor
The GitHub Actions runner executes whatever `lib/main.js` is checked into the repo, not the bundle CI rebuilds during `npm run build`. Without a drift check, a PR could change `src/` and rebuild locally but commit only the `src/` hunk — CI would stay green while every consumer of `StackAdapt/github-tag-action@vN` keeps running the old bundle. Add a `git diff --exit-code -- lib/` step immediately after `npm run build` that fails the job if the freshly rebuilt bundle diverges from the committed artefact, with a `::error::` line telling the author to run `npm run build` and commit the result. Verified locally: running the guard with a clean tree passes; after a real source change + rebuild it prints the diff and exits non-zero. (Surfaced by the reviewer's final pass on PR #5 as the highest-value process gap remaining.) Made-with: Cursor
Reviewer pointed out that `git diff --exit-code -- lib/` only compares tracked paths to the index, so if the bundler ever starts emitting additional artefacts under `lib/` (sourcemaps, split chunks, a `lib/main.js.LICENSE.txt`, etc.) a future `src/` change could introduce them without CI noticing — the runner would then run the committed `lib/main.js` but ship missing sibling files. Not a concern today (esbuild output is a single `lib/main.js` by design) but the guard should cover the class, not just the current instance. Added a complementary `git ls-files --others --exclude-standard -- lib/` check that fails the job if any new untracked files show up under `lib/` after `npm run build`, with an `::error::` line that tells the author to either commit the new artefact or add it to `.gitignore`. Also: * Renamed the step from "Ensure lib/main.js is up to date with src/" to "Ensure lib/ is up to date with src/" now that it covers the whole directory. * Added a non-fatal `git diff --stat -- lib/ || true` ahead of the strict check so CI logs get a one-line summary of what drifted before the full patch gets printed by the failing `diff`. Verified locally: clean tree passes both checks; modifying a tracked `lib/` file is caught by check 1; adding an untracked `lib/foo.map` is caught by check 2. Made-with: Cursor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a runtime crash consumers hit when using
StackAdapt/github-tag-action@v7:Root cause
@semantic-release/release-notes-generator/lib/load-changelog-config.jsresolves thepresetoption at runtime viaimport-from-esm. That helper walks the filesystem looking forconventional-changelog-<preset>innode_modules— a search that fundamentally cannot succeed in the bundled Action runtime because GitHub Actions does not runnpm installon the action dir, and our esbuild bundle is a single self-contained file. The upstream silent-then-fallthrough code path ends up callingpath.resolve(undefined, ...)when the context'scwdis unset, which is how the confusingERR_INVALID_ARG_TYPEsurfaces.Fix
conventional-changelog-conventionalcommitsinsrc/action.tsso esbuild inlines it.parser/writeroptions togenerateNotesasparserOpts/writerOpts. With nopreset/configsupplied,load-changelog-config.jstakes its safeconventional-changelog-angularfallback (also statically imported upstream and therefore bundled) and shallow-merges our options on top — conventionalcommits' keys win.cwd: process.cwd()on the context as belt-and-suspenders.Integration test that would have caught this
tests/bundle.smoke.test.tsgains a third test case that runs the shipping bundle end-to-end:node:httpmock server for/repos/foo/bar/tagsand/repos/foo/bar/compare/....lib/main.jsintoos.tmpdir()(no siblingnode_modulesanywhere on the resolver walk).GITHUB_API_URLpointed at the mock andINPUT_DRY_RUN=trueso it exits cleanly after changelog generation.ERR_INVALID_ARG_TYPE/paths\[0\]/ module-resolution errors, and positively asserts onDry run: not performing tag action.to confirm execution walked pastgenerateNotes.Uses async
spawn+ Promise-based capture (notspawnSync) because the bundle emits enough startup stdio to deadlockspawnSyncon macOS with captured pipes.Reviewer-hardening follow-up
runChildAndCapturelistens for childerrorso a failed spawn surfaces the error through captured stderr rather than hanging until the SIGKILL timer.listenpromise attaches a one-shoterrorhandler so bind failures (EADDRINUSE on CI) reject cleanly instead of wedging the test until Vitest's timeout.src/action.tsthatcommitOptsalways comes from angular when nopreset/configis passed — harmless today (defaults match) but flagged for future upstream drift.Test plan
npm run build— bundle produces a 1.7 MB self-containedlib/main.jsnpm test— 37 tests pass across 5 filesnpm run lint— cleannpm run check— Prettier cleannpm run typecheck— cleanv7tag to the merged commit so consumers pick up the fixMade with Cursor