Make packaging smoke fail-safe against event-loop drain; pin Node < 26 - #16
Merged
Conversation
Under Node 26, @electron/packager's extract-zip call stalls without rejecting, draining the event loop so package-smoke.mjs exited 0 with no packaging done — a silent false green in the required check suite (the same stall breaks electron's install script). - scripts/package-smoke-run.mjs: preset exitCode=1, beforeExit drain diagnostic, and require non-empty dist-smoke output before success; package-smoke.mjs is now a thin entry over it - unit tests for the runner + integration tests spawning real child processes proving exit codes for hang/success/empty/reject - pin supported Node via .nvmrc (22) and engines (>=20.19 <26); CI reads .nvmrc; document the failure mode in AGENTS.md and the runbook Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What changed
scripts/package-smoke.mjs(thepackage:smokestep ofpnpm run check) could exit 0 without packaging anything. Under Node 26,@electron/packager's internalextract-zipcall stalls while extracting the Electron zip without ever rejecting, so Node's event loop drains and the process exits 0 — no success log, no error, a silent false green in the required verification suite. The same stall breaks theelectronpackage's install script (path.txtis never written), making fresh installs unusable on Node 26.scripts/package-smoke-run.mjs):process.exitCode = 1is preset up front and only reset to 0 after verified success, abeforeExitguard prints a drain diagnostic if the packager promise never settles, and success now requires thedist-smokeoutput directory to exist and be non-empty — a resolved packager promise alone is not proof.package-smoke.mjsis now a thin entry over the runner.tests/unit/package-smoke-run.test.mjs) and integration tests (tests/integration/package-smoke-exit.test.mjs) that spawn real child processes wired exactly like the production entry, proving actual process exit codes for hang (drain) / success / empty-output / rejection..nvmrc(22) andengines: ">=20.19 <26"inpackage.json; CI's setup-node now readsnode-version-file: '.nvmrc'. The failure mode is documented inAGENTS.mdanddocs/production/runbook.md.Verification
pnpm package:smokenow exits 1 withPackaging smoke did not complete: the event loop drained before packaging finished…(previously: silent exit 0).pnpm run checkpasses under Node 22.23.2 (checksum-verified toolchain), including a genuinePackaging smoke succeeded— run on this branch after fast-forwarding to latestmain.path.txtfrom the same drain) was repaired by re-running its install script under Node 22.Reviewer notes
beforeExitnot firing before the packager settles in the healthy path; the integration tests cover both directions with real processes.enginesis advisory under pnpm's defaults (warning, not error); the hard protection is the smoke script itself now failing loudly.🤖 Generated with Claude Code