ci: guard PRs against boot-script byte drift and deploy-dep breakage#7562
Draft
santicomp2014 wants to merge 1 commit into
Draft
ci: guard PRs against boot-script byte drift and deploy-dep breakage#7562santicomp2014 wants to merge 1 commit into
santicomp2014 wants to merge 1 commit into
Conversation
Two failure classes from the 2026-07-01 incident (#7557 -> #7560/#7561) were invisible to PR CI because the production build and the deploy script's dependency chain only run post-merge in the Release workflow: - a build-tooling transitive (serialize-javascript v6->v7) changed the boot script's bytes, invalidating the CSP script-src sha256 where the client is embedded inline -> browsers blocked the client in prod; - a fast-xml-parser pin broke @aws-sdk's parsing of S3 responses, blocking every deploy. This adds a `prod-build-guard` PR job that: 1. builds the production bundles for the PR and its base branch and fails if the boot script's code bytes drift (asset cache-buster fingerprints are normalized away; the `boot-bytes-approved` label acknowledges intentional changes); 2. smoke-checks the deploy-time dependency chain on every PR (deploy-to-s3.js import chain + the AWS SDK XML parser accepting the `
` entity S3 returns). It also makes the boot build deterministic: generateManifest fills the manifest in file-read-completion order, which varies per run, and the boot bundle inlines that JSON -- the manifest is now rewritten with sorted keys so identical inputs produce identical boot bytes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7562 +/- ##
=======================================
Coverage 99.62% 99.62%
=======================================
Files 285 285
Lines 11971 11971
Branches 2920 2920
=======================================
Hits 11926 11926
Misses 45 45 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Why
The 2026-07-01 incident (#7557 → hotfix #7560, rollback #7561) had two failure modes that were invisible to PR CI, because the production build and the deploy script's dependency chain run for the first time post-merge in the Release workflow:
serialize-javascriptv6→v7, pulled in viaresolutions) changed the boot script's bytes, so the CSPscript-srcsha256 gating the client's inline bootstrap no longer matched → browsers blocked the client in prod (~37 min partial outage).fast-xml-parser: 5.7.0pin made@aws-sdk's S3 response parsing reject the
entity S3 returns → every deploy blocked.Several currently-open Dependabot PRs (#7546 rollup/terser majors, #7544 babel group) touch the same toolchain and are green for the same vacuous reason. This PR is the guard that makes them safely mergeable.
What this adds
A
prod-build-guardjob in PR CI that:yarn build) for both the PR and its base branch;build/boot-template.js/build/boot.js). Asset cache-buster fingerprints (?abc123) are normalized away first, so routine asset changes don't trip it — only drift in the boot code (the incident class) fails. Intentional changes are acknowledged with theboot-bytes-approvedlabel, which downgrades the failure to a warning;scripts/check-deploy-deps.js(constructs the S3 client and regression-tests the XML parser against an S3-style
response — the exact 2026-07-01 deploy bug) plusdeploy-to-s3.js --helpto exercise the deploy script's full import chain.A determinism fix the guard surfaced:
generateManifest(from@hypothesis/frontend-build) fills the manifest object in file-read-completion order, which varies run to run, and the boot bundle inlines that JSON — so two builds of identical source produced different boot bytes. The gulpfile now rewritesbuild/manifest.jsonwith sorted keys before the boot bundle is built. (Proper long-term fix belongs upstream infrontend-build; follow-up worth opening there.)Verification (local)
yarn buildruns produced differentboot-template.jshashes (manifest key order raced). After: identical hashes across rebuilds.node scripts/check-deploy-deps.jspasses;node scripts/deploy-to-s3.js --helpexits 0.prettier/eslint/tscclean on the changed files.Notes for review
boot.jsbytes once. That is strictly less churn than today (ordering is currently random every build, so releases already reshuffle it and prod tolerates it). Theboot-bytes-approvedlabel demonstrates the acknowledgement flow.pull_request(skipped when this workflow isworkflow_called from Release).Prod build & boot hash guardto the branch-protection required checks (repo admin).🤖 Generated with Claude Code