ci: fail the build when the docs Worker exceeds a declared size budget - #275
Merged
Merged
Conversation
Nothing in this repository weighed the Worker. The only thing that checked it was the Cloudflare API, at upload time, on `main`, after merge — and the rejection lands on version creation, so nothing 500s, no page changes, and the site silently stops moving. That is how this repo ran 35 consecutive red deploys (runs #106-#140) with the `build` job green for every one of them. The `build` job already packaged the Worker with `--skipNextBuild`, but only on a push to `main`, so a pull request never packaged one and could never be told its Worker was too big. That condition is dropped; the artifact upload stays `main`-only underneath the new gate. The gate reads wrangler's own `Total Upload:` line via `wrangler deploy --dry-run` — the same accounting a real deploy prints, no API call and no credentials — rather than stat-ing files, which would re-derive which files count. Budget 61440 KiB (60 MiB), declared once with the 65536 KiB limit beside it; every percentage is computed, never typed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ChPQM8jamxLUfUAxwFpJ8S
os-bill
marked this pull request as ready for review
September 8, 2026 14:11
This was referenced Sep 8, 2026
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.
Fixes #262
.github/workflows/ci.ymlnever measured the Worker bundle. The only thing that checked it was the Cloudflare API, at upload time, onmain, after merge — and the rejection lands on version creation, so nothing 500s, no page changes, and the site just stops moving. That is how this repo ran 35 consecutive red deploys (runs #106-#140, 08-25 to 09-02) with thebuildjob green for every one of them.What changed
One file, three edits:
Package the Worker from the build this job testedloses itspush+refs/heads/maincondition. It ran only where a deploy would follow, so a pull request never packaged a Worker and could never be told its Worker was too big — the whole defect. It now runs on every event.Worker bundle fits the size budget. Reads wrangler's ownTotal Upload:line and exits 1 above a declared budget.Upload the Worker bundlekeeps itsmain-only condition, and now sits behind the gate: anif:carrying no status function impliessuccess(), so an over-budget Worker never becomes an artifact and never reachesdeploy-docs.yml.The measurement
wrangler deploy --dry-runprintsTotal Upload:from the same code path a real deploy uses — no API call, no credentials, 9s. That is deliberate over stat-ing files: stat-ing means re-deriving which files count, and that guess is the trap the card names.handler.mjsalone measures 48.48 MiB while the upload is 58553.98 KiB.Verified from
--dry-run --outdir, the uploaded set is exactly:worker.js77d9…-resvg.wasm8a4c…-Geist-Regular.ttf.bina5d4…-yoga.wasmwhich is the printed line to the hundredth.
worker.js.map(85819146 B — larger than the whole budget) and the.open-next/assetsand.open-next/cachetrees are not in it.Calibrated against a figure Cloudflare accepted. Same commit
0e26657f, run 33891143864, Worker version2170b929-5879-4b3f-b7a2-9eda750158dd:The budget
61440 KiB= 60 MiB = 93.75 % of the65536 KiBlimit. One constant, declared with the limit beside it; every percentage and headroom figure in the step output is computed from those two and never typed. The card's own banner is why that matters — it quoted89.3 %(against 65536) and~5.3 MiB headroom(against 64000) in one paragraph, two ceilings, about 1.5 MiB of phantom room.It clears two bars:
No warn tier, deliberately. Every band between today's 89.35 % and the 93.75 % budget is under 4.5 points wide and the bundle is already inside it, so a warning would be lit from its first run and read as wallpaper. The reading is printed to the step summary on every run instead, which is what a warn tier was wanted for.
Demonstrated red
A probe that cannot fail is indistinguishable from one that passed, so the gate was ablated before it was trusted. Both legs ran the step body extracted from the parsed
ci.yml, not a draft copy.Padding the real bundle by 4 MiB — mutation confirmed on disk (marker present, 2278 to 4196623 bytes) rather than by an editor's exit code:
95.60 % lands within 98 KiB of run #105's pre-outage 62747.87 KiB, so this is close to a reconstruction of the state that preceded the outage. The measured size moved by 4096.03 KiB against a 4096 KiB pad — the gate tracks the artifact byte for byte, not a cached or hardcoded number.
Restoring the bundle (
sha256 d05223bf…, byte-identical, marker count 0) returned it toexit 0at58553.98 KiB.Negative control — wrangler output with the
Total Upload:line absent:An unreadable measurement is a finding, never a skip. A gate that silently weighs nothing passes forever.
Cost
Not a second build —
--skipNextBuildre-packages the.nexttreepnpm turbo run buildalready produced, which is the cheap option the card hoped for. Measured on this branch:turbo run build(already paid)A pull request pays about 33s more than before, not another 101s.
Scope
deploy-docs.yml,rollback-docs.ymlandsmoke-docs.mjsare untouched. The new-version-ID assertion already exists indeploy-docs.yml. The pre-merge rendering check on #274 is out of scope here and #274 remains open.ci.yml, and merging tomainpublishes the docs site.🤖 Generated with Claude Code
https://claude.ai/code/session_01ChPQM8jamxLUfUAxwFpJ8S
Generated by Claude Code