Skip to content

Make packaging smoke fail-safe against event-loop drain; pin Node < 26 - #16

Merged
tadaspetra merged 1 commit into
mainfrom
claude/dreamy-dirac-b67675
Aug 21, 2026
Merged

Make packaging smoke fail-safe against event-loop drain; pin Node < 26#16
tadaspetra merged 1 commit into
mainfrom
claude/dreamy-dirac-b67675

Conversation

@tadaspetra

Copy link
Copy Markdown
Owner

What changed

scripts/package-smoke.mjs (the package:smoke step of pnpm run check) could exit 0 without packaging anything. Under Node 26, @electron/packager's internal extract-zip call 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 the electron package's install script (path.txt is never written), making fresh installs unusable on Node 26.

  • Fail-safe runner (scripts/package-smoke-run.mjs): process.exitCode = 1 is preset up front and only reset to 0 after verified success, a beforeExit guard prints a drain diagnostic if the packager promise never settles, and success now requires the dist-smoke output directory to exist and be non-empty — a resolved packager promise alone is not proof. package-smoke.mjs is now a thin entry over the runner.
  • Tests: unit tests for 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.
  • Node pinning: .nvmrc (22) and engines: ">=20.19 <26" in package.json; CI's setup-node now reads node-version-file: '.nvmrc'. The failure mode is documented in AGENTS.md and docs/production/runbook.md.

Verification

  • Demonstrated the real failure is caught: on Node 26.7.0, pnpm package:smoke now exits 1 with Packaging smoke did not complete: the event loop drained before packaging finished… (previously: silent exit 0).
  • Full pnpm run check passes under Node 22.23.2 (checksum-verified toolchain), including a genuine Packaging smoke succeeded — run on this branch after fast-forwarding to latest main.
  • The broken local electron install (missing path.txt from the same drain) was repaired by re-running its install script under Node 22.

Reviewer notes

  • The drain guard relies on beforeExit not firing before the packager settles in the healthy path; the integration tests cover both directions with real processes.
  • engines is advisory under pnpm's defaults (warning, not error); the hard protection is the smoke script itself now failing loudly.

🤖 Generated with Claude Code

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>
@tadaspetra
tadaspetra merged commit fe31d8e into main Aug 21, 2026
2 checks passed
@tadaspetra
tadaspetra deleted the claude/dreamy-dirac-b67675 branch August 21, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant