ci: headless server smoke test on every PR - #70
Merged
Conversation
Launches dist-headless/main/index.js on an ephemeral port, parses the [web-client] URL out of stdout, then verifies four things: 1. web client root serves 200 with the expected HTML marker 2. auth gate rejects requests without ?token= 3. a WebSocket client can connect with the token 4. SIGTERM exits cleanly within 5s (no zombies) Catches the entire "the tarball can't even boot" class of bug — the recent agentjesus module-resolution regression and the earlier web-client-bundle-missing regression would both have failed here. Builds against dist-headless/, not the tarball; full tarball validation is a follow-up. Also fixes a related bug: the user-facing [web-client] / [ws-transport] log lines printed port 0 verbatim when --port 0 was passed, even though the server was actually listening on the OS-assigned ephemeral port. The smoke test depends on the printed URL being correct, so resolve the real port via webHttpServer.address() in the listen callback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The smoke logic was an 85-line shell block inlined in ci.yml — a pain to edit (no syntax highlighting, awkward to run locally, hard to diff) and overlapped with the existing scripts/web-smoke.mjs + scripts/ws-smoke.mjs which already do HTTP + WS validation. Move it into scripts/smoke-headless.sh as a thin orchestrator: launch the server, parse the URL out of the log, delegate to the existing .mjs smokes for HTTP + WS, then SIGTERM + clean-shutdown check. CI step shrinks to `bash scripts/smoke-headless.sh`. Local repro is now a one-liner: npm run build:headless && bash scripts/smoke-headless.sh Co-Authored-By: Claude Opus 4.7 (1M context) <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.
Summary
.github/workflows/ci.ymlthat launches the freshly-built headless server (dist-headless/main/index.js) on an ephemeral port, then verifies four end-to-end properties:HarnessHTML marker?token=SIGTERMexits cleanly within 5s (no zombie processes)src/main/index.ts: when--port 0is passed (the smoke test relies on this), the[web-client] open …/[ws-transport] enabled on …log lines printed port0verbatim, even though the server was actually listening on the OS-assigned ephemeral port. Resolved viawebHttpServer.address()in thelistencallback.Why
Neither
typecheck + build + tests(PR CI added in #66) norvitestexercises the headless boot path. The recent agentjesus regression (Cannot find module '@anthropic-ai/claude-code-linux-x64/package.json'on first json-mode tab) and the earlier "web-client bundle not found" tarball-layout bug both rode to a tag-pushed release because the only end-to-end check was a human running the install script. Both would have failed this smoke immediately.Scope
dist-headless/, not the tarball. Tarball validation (extract +bin/harness-serverboot) is a follow-up.headless-release.ymlalready validates each platform's build on tag push.Test plan
npm run build:headlessoutput passes all four checks (server up,web-client root OK,auth gate OK (401),ws connect OK,clean shutdown OK).actionlint .github/workflows/ci.ymlclean.npm run typecheckclean.🤖 Generated with Claude Code