Harden prod backend Cloud Run deploy workflow (#9164)#9169
Conversation
Add preflight/repair scripts, offline rendered-env validation, pre-deploy-check.sh CI gate, and workflow modes for traffic repair and Cloud Run-only deploys so failed revisions cannot wedge spec.traffic. Verification: backend/scripts/pre-deploy-check.sh; python3 backend/scripts/check_workflow_contracts.py; 25 unit tests in deploy safety suite. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c386fe0f42
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| --expect-cloud-run-traffic backend-sync=${{ steps.capture-backend-sync-revision.outputs.revision }} \ | ||
| --expect-cloud-run-traffic backend-integration=${{ steps.capture-backend-integration-revision.outputs.revision }} | ||
| --expect-cloud-run-traffic backend-integration=${{ steps.capture-backend-integration-revision.outputs.revision }} \ | ||
| | tee /tmp/cloud-run-deploy-status.txt || true |
There was a problem hiding this comment.
Do not mask failed prod traffic verification
In the prod deploy path I inspected, this command is the only post-shift readback that verifies status.traffic is 100% on the captured revisions; backend/scripts/deploy_status_report.py returns non-zero on describe errors, spec/status mismatches, or stale traffic. Because its output is piped to tee and followed by || true (and the workflow does not enable pipefail), any of those failures is swallowed after the update-traffic commands, so the workflow can report a successful prod deploy even when Cloud Run is still serving the old revision. Keep the summary generation but preserve the Python exit status on the success path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
10 issues found across 19 files
Confidence score: 2/5
- In
.github/workflows/gcp_backend.ymland.github/workflows/gcp_backend_auto_dev.yml,deploy_status_report.pyis force-succeeded with|| true, so traffic/revision mismatches can still produce a green deploy result and let a bad rollout pass unnoticed—remove|| true(or only tolerate failures in explicitly non-blocking paths) before merging. backend/scripts/preflight-cloud-run-deploy.pycurrently accepts blankSERVICE/REVISIONand throws a traceback for bad--wait-revision-readyinput, which can turn fast validation errors into long noisy waits and harder CI diagnosis—fail fast on empty values and route parse failures throughparser.error(...).- Offline/state-driven repair flow is inconsistent across
backend/scripts/deploy_status_report.pyandbackend/scripts/repair_cloud_run_traffic.py: savedproject/regionare dropped, so generated repair commands can target the wrong Cloud Run service—propagate state-derived project/region through report and repair command generation before merging. - Guardrails are a bit late or brittle in
.github/workflows/gcp_backend.ymlandbackend/scripts/pre-deploy-check.sh(environment validation timing, Python runtime drift), andbackend/tests/unit/test_preflight_cloud_run_deploy.pyleaks module state; these can cause avoidable CI surprises—add early dispatch/runtime validation and cleansys.modulesvia the existing snapshot fixture to de-risk follow-up runs.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/gcp_backend.yml">
<violation number="1" location=".github/workflows/gcp_backend.yml:46">
P2: The environment name is only checked inside the job, so an invalid dispatch value can still reach the job-level `environment:` binding before the validation step runs. Moving the validation into a workflow-level dispatch filter or encoding the allowed values in the input itself would avoid binding an invalid environment.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| jobs: | ||
| repair-traffic: | ||
| if: ${{ github.event.inputs.mode == 'repair-traffic-only' }} | ||
| environment: ${{ github.event.inputs.environment }} |
There was a problem hiding this comment.
P2: The environment name is only checked inside the job, so an invalid dispatch value can still reach the job-level environment: binding before the validation step runs. Moving the validation into a workflow-level dispatch filter or encoding the allowed values in the input itself would avoid binding an invalid environment.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/gcp_backend.yml, line 46:
<comment>The environment name is only checked inside the job, so an invalid dispatch value can still reach the job-level `environment:` binding before the validation step runs. Moving the validation into a workflow-level dispatch filter or encoding the allowed values in the input itself would avoid binding an invalid environment.</comment>
<file context>
@@ -19,13 +19,78 @@ on:
jobs:
+ repair-traffic:
+ if: ${{ github.event.inputs.mode == 'repair-traffic-only' }}
+ environment: ${{ github.event.inputs.environment }}
+ permissions:
+ contents: 'read'
</file context>
Remove || true from post-deploy traffic verification, harden preflight/repair scripts, propagate Cloud Run project/region through offline state, rename render_backend_runtime_env for import consistency, and fix desktop import guard paths after Onboarding/ move. Merged main for backend unit test harness updates. Co-authored-by: Cursor <cursoragent@cursor.com>
GitHub Actions lint runners use system python3 (3.12.x) while .python-version pins 3.11.15; keep the exact-version guard for local dev only. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
1 issue found across 17 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/gcp_backend.yml">
<violation number="1" location=".github/workflows/gcp_backend.yml:46">
P2: The environment name is only checked inside the job, so an invalid dispatch value can still reach the job-level `environment:` binding before the validation step runs. Moving the validation into a workflow-level dispatch filter or encoding the allowed values in the input itself would avoid binding an invalid environment.</violation>
</file>
<file name="backend/tests/unit/test_preflight_cloud_run_deploy.py">
<violation number="1" location="backend/tests/unit/test_preflight_cloud_run_deploy.py:9">
P2: The new test code imports from `tests.unit.memory_import_isolation`, which is a deprecated module the project is actively migrating away from. The project's test isolation guidelines (AGENTS.md, test_isolation.md) explicitly state not to extend this module and instead use `backend/testing/import_isolation.py` (`stub_modules` context manager) or `monkeypatch.setattr` on lazy-held singletons. Since this is adding *new* usage of the deprecated module, consider using `backend/testing/import_isolation.stub_modules` with `load_module_fresh` instead — or, since the production scripts already have clean top-level imports (stdlib only), the snapshot/restore may not be needed at all.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
|
@cursor address CI failure and review comment |
|
Addressed both the CI failure and the review comment. CI failureThe Backend unit suite failed on the fast-unit duration guard, not on a test assertion: That test does heavier work ( Review commentRemoved the deprecated Verification
Pushed as |
- Allowlist test_repo_rendered_cloud_run_matches_manifest (0.19s CPU on CI). - Simplify preflight deploy tests to match validator importlib pattern without memory_import_isolation snapshot/restore. Co-authored-by: David Zhang <Git-on-my-level@users.noreply.github.com>


Summary
gcp_backend.ymlagainst wedged Cloud Run traffic (spec.trafficon failed revisions) with preflight secret/traffic checks, revision readiness gating,repair-traffic-onlymode, andcloud-run-onlydeploy target.SERVICE_ACCOUNT_JSON,POSTHOG_PROJECT_API_KEY) that causedSecretsAccessCheckFailedon revision create.pre-deploy-check.sh(hermetic + optional live),repair_cloud_run_traffic.py,preflight-cloud-run-deploy.py, offline--check-rendered-cloud-runvalidation, and prod hotfix runbook.Pre-deploy validation (no deploy required)
cd backend CLOUD_RUN_VPC_NETWORK=offline-check-network \ CLOUD_RUN_VPC_SUBNET=offline-check-subnet \ ./scripts/pre-deploy-check.shWith gcloud auth for live read-only checks:
CI runs the hermetic path via
lint.ymlwhen deploy-safety files change.Test plan
backend/scripts/pre-deploy-check.sh(hermetic)python3 backend/scripts/check_workflow_contracts.pytest_backend_runtime_env_validator,test_repair_cloud_run_traffic,test_preflight_cloud_run_deploy,test_deploy_status_reportvalidate-backend-runtime-env.py --env prod --check-workflows --check-rendered-cloud-rungcp_backend.ymlwithmode=repair-traffic-onlyagainst dev (optional)gcp_backend.ymlwithdeploy_targets=cloud-run-onlyagainst dev after merge (optional)Closes #9164
Made with Cursor