Repository navigation
feat(ci): check in a browser that the site renders, before and after merges - #12236
Merged
Merged
Conversation
…merges On 2026-10-22 vite 8.1.6 (#12225) passed every PR check and its deploy, and left every page on anyplot.ai blank for about 45 minutes: Rolldown's runtime helper sat in a chunk cycle and the bundle threw `TypeError: t is not a function` at module load (fixed by #12235). The app-image job only proved that nginx serves the shell. scripts/site-smoke.mjs loads pages in headless Chromium and fails on a status other than 200, an uncaught page error, or an empty #root, and checks the API's /health. Two layers use it: - the app-image job runs it against the built gate-off container, with the runner's Google Chrome, whenever the container's inputs change, so a dependency bump that breaks the boot fails its PR; - a CLAUDE.md rule, with the recipe in the open-pr skill and the Dependabot batch command, runs it against production after every merge; a FAIL is an incident and stops further merges. Checked locally: against the current app image it passes (one CORS console error from the foreign origin, reported as a warning only), against an image built from 20c1457 (vite 8.1.6) it fails with `pageerror: t is not a function` and an empty page, against production it passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdMSqLR5ww4ji74EUSmk9M
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdMSqLR5ww4ji74EUSmk9M
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The smoke can accept failed routes, misclassify browser-launch failures, and verify an older deployment under the fixed-delay guidance.
3 open issues
What changed in this PR
Adds browser smoke checks to catch runtime failures that image builds and deployment checks missed during the Vite-related outage.
Changes:
- Adds a Chromium script that checks page responses, uncaught errors, rendered text, and API health.
- Runs the smoke against the built app container in CI.
- Documents post-merge verification and sequential Dependabot merge checks.
| File | Description |
|---|---|
scripts/site-smoke.mjs |
Implements browser rendering and API health checks. |
docs/reference/repository.md |
Lists the new smoke script. |
CLAUDE.md |
Requires browser verification after merges. |
changelog.d/site-smoke-after-merge.md |
Records the new verification process. |
agentic/commands/dependabot.md |
Adds sequential merge and post-deploy checks. |
.github/workflows/ci-image.yml |
Runs the browser smoke against the built container. |
.claude/skills/open-pr/SKILL.md |
Documents smoke execution and failure handling. |
.claude/guardrails.md |
Explains the outage and verification rationale. |
Review effort: Balanced
The companion-file test requires every guardrails.md section to name the CLAUDE.md obligations it elaborates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdMSqLR5ww4ji74EUSmk9M
…t start Copilot review of #12236: - the app's error boundary keeps the masthead and footer around a failed route, so the text threshold alone could pass it; the smoke now waits for the network to settle and fails on the boundary's text; - a browser that exists but will not launch checked nothing, so it exits 2, not 1 (an incident); - elapsed time does not prove a deploy is serving: the recipe waits for the watcher's SUCCESS, and without gcloud compares the entry bundle the script now prints, reporting the check as unconfirmed until it changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdMSqLR5ww4ji74EUSmk9M
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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
TypeError: t is not a functionat module load; fixed by fix(app): bump vite to 8.3.5 to fix blank site (runtime chunk cycle) #12235). Nothing in CI or the post-merge routine ran the bundle.scripts/site-smoke.mjs: loads/,/plotsand/scatter-basicin headless Chromium and fails on a status other than 200, an uncaught page error, or an empty#root; checksapi.anyplot.ai/health. It never downloads a browser (CHROME_PATH, the cloud container's Chromium, or the Playwright MCP's).app-imagejob ofci-image.ymlruns it against the built gate-off container with the runner's Google Chrome, whenever the container's inputs change (package.json,yarn.lock,vite.config.ts, ...), which is every frontend dependency bump.CLAUDE.mdrule (owner request, 2026-10-22) with the recipe in/open-pr§4 and the Dependabot batch command: after every merge, once its deploys finish, run the smoke against production; a FAIL is an incident and stops further merges. The Dependabot command also merges lock-file PRs one at a time and smokes after eachapp/bump. The incident narrative is in.claude/guardrails.md.Plan
N/A. The owner asked on 2026-10-22, after the outage, for a rule or skill so a blank site never goes unnoticed again.
Test plan
VITE_API_URL=https://api.anyplot.ai), gate-off container on :8081,SITE=http://localhost:8081 API=none MIN_TEXT=50 node scripts/site-smoke.mjs /: OK (text=2736, one CORS console error reported as a warning)FAIL ... text=0 ... pageerror: t is not a function, exit 1uv run pytest tests/unit/workflows(766 passed),uv run ruff check ., changelog checkBuild app image and smoke the origin gaterun exercises the new step on the runner (ci-image.yml changes trigger the job).github/workflows/beyond this PR's own run; the CLAUDE.md rule has no twin in.github/copilot-instructions.md, which does not carry the merge routine.🤖 Generated with Claude Code
https://claude.ai/code/session_01GdMSqLR5ww4ji74EUSmk9M