Repository navigation
Add just verify-deploy, which asks an environment whether its deploy worked - #613
Conversation
This comment has been minimized.
This comment has been minimized.
fd1ec5f to
83f0a1a
Compare
This comment has been minimized.
This comment has been minimized.
83f0a1a to
021c679
Compare
This comment has been minimized.
This comment has been minimized.
…worked Checking a deploy was a procedure spread across a CLAUDE.md paragraph and six memory notes, each recording a trap: Cloudflare answers 1010 to a script without a browser User-Agent, localhost curls on the droplets answer 400, /api/health reads degraded hourly and after every restart, the server answers 5xx and publishes an empty feed while it restarts and then takes minutes to refill the map, a status code cannot tell a bundle from the SPA fallback, and a lazily loaded page's change is not in the index chunk. Worktree sessions load none of that memory, so each trap was found again. deploy/verify-deploy.py encodes them. It reads the environment's hostnames, and the flags and RETINA_ENV it should report, from that environment's compose overlay, and the origin marker from deploy/origin-marker.sh, so none can drift from its source. It polls health, the public map's feed, the public node list and, on the fleet's box, the unfiltered feed together for up to --wait minutes, failing only what is still wrong at the end; reads a degraded health as a warning; checks the marker on every /api/ answer; walks every script and stylesheet the page reaches; and with --expect-string finds a string in any of them. It only reads, and only public hostnames. Its verdict rests on public reads because /api/test/* answers only an administrator or the radar key since #608: - The map is judged on aircraft-live.json, the real-node feed the public map draws on every deployed host, not the unfiltered aircraft.json. An empty public map with real nodes connected warns, since real nodes can solve nothing for hours; a feed that errors, stops or has the wrong shape fails, and so does a box with no real node connected. - On the fleet's box the unfiltered feed must carry aircraft a synthetic node saw, so real nodes' aircraft cannot stand in for the fleet. - /api/health's synthetic_fleet and polled_radar_polling, read against the overlay, tell prod, staging and test apart without a key. - RETINA_ENV and task health need the dashboard, so they run only when the radar key is in VERIFY_DEPLOY_RADAR_KEY. Otherwise they are reported as skipped, and the summary says they were not passed. The key goes in one header to that one route, is never followed through a redirect, and is redacted from an answer's body before anything quotes it. No public endpoint reports the deployed commit, so it cannot say what shipped beyond --expect-string; ClickUp 123zgec4n48 carries exposing one. The connected real nodes are listed for comparison with a run before the deploy, and the in-browser look at the map stays a human check. ClickUp: 123zgec4mxu Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
021c679 to
a089caf
Compare
This comment has been minimized.
This comment has been minimized.
|
Claude finished @jehanazad's task in 13m 1s —— View job Claude's review of #613Todo list
SummaryThis is a Five findings from this pass, none blocking but worth a look:
Nothing here blocks the PR — #1 and #2 are the two I'd actually want addressed (both are plausible false-negative/false-positive paths in a deploy gate), #3 and #4 are latent/masked today, and #5 is pure polish. Fix this → |
ClickUp: 2.5 Add a verify-deploy command for each environment
Stacked on #617, in the stack main ← #595 ← #602 ← #620 ← #607 ← #617 ← #613 ← #596, which lands in one deploy.
Summary
Checking a deploy was a manual procedure spread over a CLAUDE.md paragraph and six memory notes.
just verify-deploy <prod|staging|test>asks the environment itself, over its public hostnames only, and exits non-zero with a reason:deploy/origin-marker.sh. The server's own answers are then read back against both./api/health'ssynthetic_fleetandpolled_radar_pollingare read against the overlay. Between them they tell prod, staging and test apart without a key.--waitminutes. That rides out a restart's 5xx answers, unpublished feed and empty map. A 4xx, or a certificate it cannot check, ends the wait. A failed read on the last poll alone, after a good one, is forgiven as a blip.degradedas the baseline it is, so it warns rather than fails.aircraft-live.json, the real-node feed the map draws on every deployed host, not on the unfilteredaircraft.json.aircraft.jsonmust carry aircraft that a connected synthetic node saw, so real nodes' aircraft cannot stand in for the fleet. A fleet that is not connected fails./api/test/dashboardanswers only an administrator or the radar key. RETINA_ENV and task health are read from it only when the key is inVERIFY_DEPLOY_RADAR_KEY. Without the key they are reported asSKIP, and the summary line says they were skipped, not passed. The key goes in one header to that one route, and a redirect is never followed with it. It is redacted from the answer's body before anything quotes it, and again from every report line.--expect-stringand--expect-absentsearch all of them and the page itself.CLAUDE.md's deploy paragraph and ONBOARDING now point at it. No public endpoint reports the deployed commit, so the script cannot say which commit shipped. 123zgec4n48 carries that, and it is best built on 1.6's
deploy/deploy.sh.Testing
backend/tests/test_verify_deploy.pyhas 86 tests against a fake environment. Every branch was checked by deliberately breaking it: 70 such changes, and each one turns at least one test red. Among them:reprwould escape. It travels only in the dashboard request's header, and that request does not follow redirects.SKIProw and "skipped, not passed", and the dashboard is not asked.deploy/page-asset.sh.polled_radar_polling=True, staging neither flag, testsynthetic_fleet=Truewith 23 fleet aircraft. On prod,--expect-string ps-sim-anomalouswas found in a lazy chunk (PhysicsPage-*.js). The keyed path has run only against the fake, since nobody here holds the key.-m "not external" -n 4 --dist worksteal) on this branch rebased ontomain: 5225 passed, 2 skipped. The last amend touched only the script, its tests and CLAUDE.md, and the test file passes under the repo's conftest.Review notes
mainafter Answer the test router's reads only for an administrator or the radar key #608. The CLAUDE.md paragraph keeps main'ststand User-Agent sentences and adds this command beside them.deploy/page-asset.shanddeploy/origin-marker.shchange only their header comments. They no longer claim to be the single implementation.🤖 Generated with Claude Code