Skip to content

ci: headless server smoke test on every PR - #70

Merged
frenchie4111 merged 2 commits into
mainfrom
ci-headless-smoke-test
May 25, 2026
Merged

ci: headless server smoke test on every PR#70
frenchie4111 merged 2 commits into
mainfrom
ci-headless-smoke-test

Conversation

@frenchie4111

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a smoke-test step to .github/workflows/ci.yml that launches the freshly-built headless server (dist-headless/main/index.js) on an ephemeral port, then verifies four end-to-end properties:
    1. web client root serves 200 with the expected Harness HTML marker
    2. auth gate rejects requests without ?token=
    3. a WebSocket client can connect using the token
    4. SIGTERM exits cleanly within 5s (no zombie processes)
  • Fixes a related bug in src/main/index.ts: when --port 0 is passed (the smoke test relies on this), the [web-client] open … / [ws-transport] enabled on … log lines printed port 0 verbatim, even though the server was actually listening on the OS-assigned ephemeral port. Resolved via webHttpServer.address() in the listen callback.
  • CLAUDE.md note added under the Releasing section.

Why

Neither typecheck + build + tests (PR CI added in #66) nor vitest exercises 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

  • v1: builds against dist-headless/, not the tarball. Tarball validation (extract + bin/harness-server boot) is a follow-up.
  • Linux x64 only (the existing runner). Multi-arch matrix is a follow-up; the existing headless-release.yml already validates each platform's build on tag push.
  • No UI / Electron smoke (would need display server + Playwright + larger scope).

Test plan

  • Local repro of the full smoke flow against npm run build:headless output passes all four checks (server up, web-client root OK, auth gate OK (401), ws connect OK, clean shutdown OK).
  • actionlint .github/workflows/ci.yml clean.
  • npm run typecheck clean.
  • CI on this PR runs the new step green.

🤖 Generated with Claude Code

frenchie4111 and others added 2 commits May 22, 2026 22:38
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>
@frenchie4111
frenchie4111 merged commit 79e1007 into main May 25, 2026
1 check passed
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