fix(e2e): fail the packaged leg in seconds with the real cause, not a 900s hang - #441
Conversation
… 900s hang ROOT CAUSE of a nightly that has been red since 2026-08-11: electron-builder.yml sets 'enableNodeCliInspectArguments: false' (W66 hardening, commit d4a7e3f, that same day). Playwright drives an Electron MAIN process over the NODE inspector -- its launcher passes '--inspect=0' and waits for it -- and that fuse makes Electron IGNORE --inspect. The inspector never appears, so electron.launch waits out its full 900s budget and reports nothing but a timeout. THE SHIPPED APP IS FINE. The CI call log shows it starting normally: 'DevTools listening on ws://...', then the renderer finishing load and the auto-updater reporting a result (wireAutoUpdater only fires on did-finish-load). Only Playwright's control channel is closed. Why the fuse's own comment says nothing depends on --inspect: that was measured by grepping tracked sources, and --inspect is injected at RUNTIME by playwright-core's Electron launcher, not written in any file here. A source grep structurally cannot see it. Two signals agree: the mechanism, and the exact date match between the fuse landing and the leg going red. This THROWS rather than skipping. The coverage is genuinely lost while the fuse is off, and a skip would turn a real gap into a green tick. The leg stays red -- but red in seconds, naming the cause and the three ways out (flip the fuse; build a test-only package and assert the release artifact separately; or cover the package without main-process assertions). That choice is the owner's W66 trade-off, not something to decide inside a spec file. Verified: tsc -p tsconfig.e2e.json clean; the guard resolves electron-builder.yml and fires on the current state, and a both-states control confirms it does NOT fire when the fuse is true.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01742e6dc9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const fuses = readFileSync(resolve(REPO_ROOT, 'electron-builder.yml'), 'utf8').replace( | ||
| /#[^\n]*/g, | ||
| '', | ||
| ); | ||
| if (/enableNodeCliInspectArguments:\s*false/.test(fuses)) { |
There was a problem hiding this comment.
Inspect the fuse on the packaged executable
When the suggested test-only package is built with the inspector fuse enabled while the release configuration remains hardened, this guard still reads the root electron-builder.yml, sees false, and aborts without examining the artifact. Consequently option (b) in the new diagnostic cannot restore packaged coverage and the error can misreport the effective fuse state; derive the value from the selected executable or the configuration actually used to build it.
Useful? React with 👍 / 👎.
Root cause of a nightly that has been red since 2026-08-11
electron-builder.ymlsetsenableNodeCliInspectArguments: false(W66 hardening, commitd4a7e3f1, that same day).Playwright drives an Electron main process over the Node inspector — its launcher passes
--inspect=0and waits for that inspector to come up. That fuse makes Electron ignore--inspect, so the inspector never appears andelectron.launchwaits out its full 900 s budget, reporting nothing but a timeout.The shipped app is fine. The CI call log shows it starting normally:
wireAutoUpdateronly fires ondid-finish-load, so the renderer had already finished loading. Only Playwright's control channel is closed.Why the fuse's own comment says nothing depends on
--inspectIt says: "Measured before flipping: neither NODE_OPTIONS nor
--inspectappears in ANY tracked .ts/.py/.json/.yml/.ps1/.mjs file, so nothing in this repo depends on either."That measurement was honest and still wrong:
--inspectis injected at runtime byplaywright-core's Electron launcher, not written in any file here. A source grep structurally cannot see that dependency.Two independent signals agree: the mechanism, and the exact date match between the fuse landing and the leg going red.
What this changes
Nothing about the fuse, and nothing about the app. The spec now checks the fuse first and throws in seconds with the cause and the options, instead of hanging for 15 minutes and saying only "timeout".
It throws rather than skips deliberately: the coverage is genuinely lost while the fuse is off, and a skip would turn a real gap into a green tick. The leg stays red — but red informatively.
The decision this surfaces (yours — it is the W66 trade-off)
true— restores packaged coverage, re-opens the Node-injection surface W66 closed.app.isPackaged/ asar-path checks and verify the artifact another way.I have not picked one; the spec names all three in its failure message.
Verification
tsc --noEmit -p tsconfig.e2e.jsonclean.electron-builder.ymland fires on the current state, and does not fire when the fuse istrue.