Add explicit readiness gate to live smoke suites (fix cold-start flake blocking prod Cloud Run deploy)#3770
Closed
anth-volk wants to merge 4 commits into
Closed
Add explicit readiness gate to live smoke suites (fix cold-start flake blocking prod Cloud Run deploy)#3770anth-volk wants to merge 4 commits into
anth-volk wants to merge 4 commits into
Conversation
The staging smoke suites run test_live_calculate.py first, whose first test posts a household calculate directly with a 90s client timeout and no retry. Against the scale-to-zero staging Cloud Run service the candidate instance is cold, and the ~200s US tax-benefit-system import loses the race to the timeout (httpx.ReadTimeout). The failure cascades — the staging Cloud Run integration test skips promote-cloud-run-staging, which skips the production Cloud Run deploy. Add tests/integration/test_live_readiness.py, listed first in both staging smoke steps, which polls /readiness-check until the deployed revision answers 200. This proves the deploy came up and warms the single instance so every following test hits a ready service. Kept as a visible test (not a conftest fixture) so the wait is obvious in the suite output and easy to maintain. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test_push_workflow_tests_app_engine_and_cloud_run_staging_tracks pins the exact staging smoke-test command; update the expected string to include the readiness gate at the head, which also guards that it stays first. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3770 +/- ##
=======================================
Coverage 80.03% 80.03%
=======================================
Files 70 70
Lines 4342 4342
Branches 809 809
=======================================
Hits 3475 3475
Misses 648 648
Partials 219 219 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Replace the in-suite readiness test with a separate wait-for-cloud-run-staging-ready job that polls /readiness-check (.github/scripts/wait_for_service_ready.sh) until the freshly deployed candidate answers 200. integration-tests-staging-cloud-run now needs that job, so the gate runs before all smoke tests and the first calculate never races the cold-start import. Its sole job is to determine readiness — no test assertions live in it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Superseded by the app-level fix (see the new PR): a startup warmup + honest /readiness-check. Polling /readiness-check from CI could never fix this because the endpoint returned 200 before the first-calculate machinery was compiled. Closing; the readiness-gate job is not needed. |
anth-volk
added a commit
that referenced
this pull request
Jul 23, 2026
… boot budget Follow-ups from reviewing this PR against the same checklist as #3770: - openapi_spec.yaml: document the 503 /readiness-check now returns while warming (previously only 200 was documented). - tests/unit/test_warmup.py: cheap structural guard that every warmup household's group-entity members reference a defined person (catches typos in the fast suite). - tests/integration/test_warmup_household.py: slow guard (gated on RUN_WARMUP_INTEGRATION=1) that builds the real tax-benefit system and confirms each warmup household computes a finite result -- so a bad household can't silently no-op the warmup. Verified: passes in 191s for US. - cloud-run-operations.md: state plainly that the warmup eats most of the headroom the 480s window buys (p90 ~371s -> ~420s), the far tail can still be killed and retried, and the lasting fix is prebuilding the system into the image. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 #3769
Problem
The staging smoke suites run
test_live_calculate.pyfirst, and its first test posts a household calculate directly (api_client.post) with a 90s client timeout and no retry. Against the scale-to-zero staging Cloud Run service the candidate instance is cold, and the ~200s US tax-benefit-system import loses the race →httpx.ReadTimeout. The polling tests survive (_poll_live_endpointretries onhttpx.RequestError); the direct calculate does not.Seen on release run
30014420432:1 failed, 6 passed, failure =test_live_calculate_us_1. It cascades to skip the production Cloud Run deploy:This is a cold-start timing race, not a product defect — but a staging flake silently blocking prod deploys is a migration hazard.
Fix
tests/integration/test_live_readiness.py— a plain, visible test (not a conftest fixture, so the wait isn't buried and is easy to maintain) that polls/readiness-checkuntil the deployed revision answers 200, with a deadline matching the startup-probe window (~480s) and retry-on-RequestError. It proves the deploy came up and warms the single instance.Why
/readiness-checkis the right signal: gunicorn workers import the app module (which builds the US system viacountry.py) before accepting connections, so a 200 from/readiness-checkmeans the system is fully imported and calculate-ready.Testing
Note: merging this creates a release whose staging smoke test now passes, which also unblocks the pending prod Cloud Run deploy of #3768.
🤖 Generated with Claude Code