Skip to content

Upgrade the v1 Cloud SQL schema and seed the v2 database side by side in the release run - #4130

Merged
anth-volk merged 2 commits into
masterfrom
parallel-database-steps
Oct 30, 2026
Merged

anth-volk merged 2 commits into
masterfrom
parallel-database-steps

Conversation

@anth-volk

@anth-volk anth-volk commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #4129

Stacked on #4127.

Summary

  • seed-v2-staging-database no longer needs migrate-v1-staging-cloud-sql, and seed-v2-production-database no longer needs migrate-v1-production-cloud-sql. In each environment the two database jobs start together.
  • deploy-cloud-run-candidate needs migrate-v1-production-cloud-sql as well as seed-v2-production-database. deploy-cloud-run-staging already needed both staging jobs. No candidate is built until both databases are upgraded.
  • docs/engineering/skills/alembic-migrations.md records the order, and that a release that stops can now leave either database upgraded without the other.
  • test_v1_upgrade_and_v2_seeding_run_side_by_side checks, for staging and production, that neither database job needs the other, that both start after the same job, and that the v1 upgrade keeps deployment_environment, its <environment>-database GitHub environment and secrets: inherit. test_seeding_success_is_required_before_candidate_creation checks that each candidate deploy needs both. The other order tests are updated to match.

No inline ruff suppressions are added.

Why the seeding waited for the upgrade

I found no dependency between the two jobs:

  • The code. migrate-v1-cloud-sql.yml signs in to Google Cloud as GCP_DB_MIGRATION_SERVICE_ACCOUNT, starts the Cloud SQL Auth Proxy and runs migrate_v1_cloud_sql.sh. That script reads the Cloud SQL credentials from Secret Manager, takes a backup when revisions are pending, and upgrades and verifies the v1 schema. seed-v2-database.yml has no Google Cloud sign-in, no proxy and no v1 credentials. Every step reads only V2_MIGRATION_DATABASE_URL or V2_DATA_WRITE_DATABASE_URL, and the modules they run (policy_migration_qualification, household_migration_qualification, user_association_migration_qualification, privilege_reconciliation, catalog.initialization) import only v2 models and settings. No v2 Alembic revision reads MySQL.
  • The history. git log -S finds the order in two commits. 78e380bbd (Implement Stage 9 v2 metadata catalog and preview routes #3808, Stage 9) added initialize-v2-staging with needs: [publish-git-tag, migrate-v1-cloud-sql], when one v1 upgrade job ran before staging; its production twin waited for no v1 upgrade. f410bcac1 (Implement Phase 10 API v2 policy migration #3813, Phase 10) split the v1 upgrade per environment, kept the staging order and made the production seeding wait for the production upgrade. Neither commit message, PR description nor the Stage 9 to 12A migration docs says why. Stage 10 and Stage 11 require only that both schemas are applied before the candidate is built, and the Stage 11 staging qualification ran the two schema workflows separately.

What changes when a release stops: today a v1 upgrade failure stops the release before the v2 seeding starts. Now the seeding may already have upgraded the v2 schema and published the catalog when the v1 upgrade fails, so the serving revision can run with an upgraded v2 database and the previous v1 schema. It already runs with both databases upgraded from the seeding until promotion, and with only the v1 database upgraded when the seeding fails before its schema upgrade step. Nothing in the v1 upgrade depends on v2 state, and the serving revision's v1 queries use only the v1 schema.

Job dependencies on a release run

Before:

staging:     publish-git-tag -> migrate-v1-staging-cloud-sql (2.0) -> seed-v2-staging-database (5.9) -> deploy-cloud-run-staging
production:  ensure-production-model-... -> migrate-v1-production-cloud-sql (1.8) -> seed-v2-production-database (5.7) -> deploy-cloud-run-candidate

After:

staging:     publish-git-tag -+-> migrate-v1-staging-cloud-sql (2.0) ---+
                              +-> seed-v2-staging-database (5.9) -------+-> deploy-cloud-run-staging (also needs release-tests, #4125)
production:  ensure-production-model-... -+-> migrate-v1-production-cloud-sql (1.8) ---+
                                          +-> seed-v2-production-database (5.7) -------+-> deploy-cloud-run-candidate

Expected saving (minutes, measured medians of releases #2577 to #2608): 1.8 in production. In staging, up to 2.0 once the release tests are no longer the longer branch: with #4125 alone they take about as long as the staging database jobs, so the staging saving appears only with #4134, which shortens the tests. About 3.8 in all with the whole stack.

Environment variables

No job moves and no wiring changes. Each reusable workflow keeps its own environment: and gets the caller's secrets through secrets: inherit.

Job Variable Provider How it reaches the step
v1 upgrade DEPLOYMENT_ENVIRONMENT caller's with: deployment_environment job env: from inputs.
v1 upgrade POLICYENGINE_DB_INSTANCE_CONNECTION_NAME, POLICYENGINE_DB_READONLY_PASSWORD_SECRET, POLICYENGINE_DB_MIGRATION_PASSWORD_SECRET staging-database / production-database environment variables (the first overrides the repository variable of the same name) job env: with environment: ${{ inputs.github_environment }}
v1 upgrade PRODUCTION_POLICYENGINE_DB_INSTANCE_CONNECTION_NAME, PRODUCTION_POLICYENGINE_DB_READONLY_PASSWORD_SECRET, PRODUCTION_POLICYENGINE_DB_MIGRATION_PASSWORD_SECRET repository variables job env:
v1 upgrade GCP_WORKLOAD_IDENTITY_PROVIDER repository secret secrets: inherit, then with: of google-github-actions/auth
v1 upgrade GCP_DB_MIGRATION_SERVICE_ACCOUNT repository variable with: of google-github-actions/auth
v1 upgrade OIDC token GitHub permissions: id-token: write in the reusable job
seeding DEPLOYMENT_ENVIRONMENT caller's with: deployment_environment job env: from inputs.
seeding V2_SUPABASE_PROJECT_REF, V2_SUPABASE_ENVIRONMENT staging / production environment variables job env: with environment: ${{ inputs.deployment_environment }}
seeding PRODUCTION_V2_SUPABASE_PROJECT_REF repository variable job env:
seeding V2_MIGRATION_DATABASE_URL, V2_DATA_WRITE_DATABASE_URL staging / production environment secrets secrets: inherit, then step env:

All names were confirmed with read-only gh api calls that list names only (actions/secrets, actions/variables, and environments/<name>/secrets and /variables for staging, production, staging-database and production-database).

Google Cloud sign-in: only the v1 upgrade signs in, and it keeps its staging-database or production-database environment, so its OIDC token is unchanged. The seeding job does not sign in.

Unverified until the first release after merge

push.yml runs only on pushes to master, so this pull request's CI does not run these jobs.

Testing

  • Red: 7517416 (tests only). pytest tests/unit/v2/test_metadata_deployment.py tests/unit/test_app_engine_decommission.py tests/unit/test_cloud_run_push_workflow.py: 4 failed, 25 passed.
  • Green: 3c966ef. The same command: 29 passed.
  • The structure tests for the workflow and its scripts (the eight modules listed in Run the release tests in their own job, beside the checks and the staging database jobs #4125): 107 passed.
  • ruff format --check . and ruff check . with the ruff version uv.lock pins (0.15.12): clean.
  • python scripts/run_quality_guards.py: passed. python -m scripts.rules guard --base-ref origin/master: passed. The rules tool's tests: OK. python -m scripts.rules render: no diff.
  • uv lock --check: passed. push.yml parses as YAML and passes actionlint.

🤖 Generated with Claude Code

@anth-volk
anth-volk added this pull request to stack #4128 October 29, 2026 19:37
@anth-volk anth-volk changed the title parallel database steps Upgrade the v1 Cloud SQL schema and seed the v2 database side by side in the release run Oct 29, 2026
@anth-volk
anth-volk force-pushed the parallel-database-steps branch from 3c966ef to fb00c49 Compare October 29, 2026 19:52
@anth-volk
anth-volk force-pushed the parallel-database-steps branch from fb00c49 to 3c966ef Compare October 29, 2026 20:13
Base automatically changed from live-staging-test-workers to master October 29, 2026 21:01
anth-volk and others added 2 commits October 30, 2026 01:01
In staging and in production, the v2 seeding job waits for the v1 Cloud
SQL schema upgrade, though neither reads the other's database. These
tests describe the next step: each seeding job starts with its v1
upgrade, both keep their environments and secrets, and each Cloud Run
candidate deploy needs both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The v2 seeding jobs waited for the v1 schema upgrade in both
environments. The order came in with the Stage 9 catalog (#3808), when
one v1 upgrade job ran before staging, and was kept when #3813 split it
per environment; neither says why. Neither job reads the other's
database: migrate-v1-cloud-sql.yml connects only to Cloud SQL through
its proxy, and seed-v2-database.yml only to the v2 database, with no
Cloud SQL proxy, GCP sign-in or v1 credentials.

Each seeding job now starts with its v1 upgrade. deploy-cloud-run-staging
already needed both; deploy-cloud-run-candidate now needs
migrate-v1-production-cloud-sql as well as the production seeding, so
neither candidate is built until both databases are upgraded. The jobs
keep their environments and secrets: inherit. alembic-migrations.md
records the order, and that a release which stops can now leave either
database upgraded without the other.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.13%. Comparing base (426ed09) to head (3a7ed9a).
⚠️ Report is 12 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #4130       +/-   ##
===========================================
+ Coverage   50.56%   88.13%   +37.56%     
===========================================
  Files         257      273       +16     
  Lines       14864    16299     +1435     
  Branches     2378     2668      +290     
===========================================
+ Hits         7516    14365     +6849     
+ Misses       6718     1268     -5450     
- Partials      630      666       +36     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@anth-volk
anth-volk marked this pull request as ready for review October 30, 2026 12:54
@anth-volk
anth-volk merged commit 6241d58 into master Oct 30, 2026
15 checks passed
@anth-volk
anth-volk deleted the parallel-database-steps branch October 30, 2026 12:54

This branch was successfully deployed

1 active deployment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade the v1 Cloud SQL schema and seed the v2 database side by side in the release run

1 participant