MAINT: Production schema migration guard + add deliberate migration script for release#2028
Open
jsong468 wants to merge 5 commits into
Open
MAINT: Production schema migration guard + add deliberate migration script for release#2028jsong468 wants to merge 5 commits into
jsong468 wants to merge 5 commits into
Conversation
behnam-o
reviewed
Jun 22, 2026
| @@ -0,0 +1,317 @@ | |||
| # Copyright (c) Microsoft Corporation. | |||
Contributor
There was a problem hiding this comment.
I'm wondering if adding a 300 line script is a bit of overhead, with a lot of overlap with other migration code (i.e. the run_migrations functions there which upgrades a db given its engine.
I think this should be a thin wrapper that constructs an AzureSQLMemory with skip=true and the prod connection string, then calls its _run_schema_migration ... no?
Contributor
Author
There was a problem hiding this comment.
agreed, slimmed it down!
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.
PR: Production Schema Migration Guard
Description
PyRIT's
AzureSQLMemoryrunsalembic upgrade headautomatically on construction, meaning any user connecting to a shared Azure SQL database triggers a schema upgrade using whatever migration files are on their machine. This PR prevents accidental schema modifications to production and adds a deliberate release-time migration path.Runtime Guard (
AzureSQLMemory)AZURE_SQL_DB_CONNECTION_STRING_PROD, the constructor now runs check-only mode instead of full migrationskip_schema_migration=True), providing visibility without modificationAzureSQLMemorycatches bothAutogenerateDiffsDetectedandCommandError(the latter fires when the DB hasn't been upgraded at all)_check_schema_migrationonMemoryInterface_run_schema_migration— a clean primitive that callscheck_schema_migrationsand lets exceptions propagateAzureSQLMemory, not in the base class_run_schema_migration: upgrade + verify_check_schema_migration: verify only, raises on mismatchRelease Migration Script (
build_scripts/migrate_prod_memory_schema.py)AzureSQLMemory(skip_schema_migration=True)and calls_run_schema_migration()— no duplicated migration logicreleases/branch, clean working tree inpyrit/memory/, no.devversion suffixAZURE_SQL_DB_CONNECTION_STRING_PRODfrom~/.pyrit/.envautomatically (loaded withoverride=Falseso explicit env vars take precedence)upgrade headis the release revision--skip-environment-checkflag for CI pipelines where Git state may differmemory_migrations.py headSubcommandgenerateandchecksubcommandsDesign Decisions
main(with unreleased schema changes) connects to prod, the guard detects the mismatch but only logs a warning — it does not block startup. This preserves the primary goal (no accidental schema modification) while keeping prod usable for querying data. The previous iteration raisedAutogenerateDiffsDetected, which blocked developers from using prod at all after any schema PR merged tomain.skip_schema_migration=True. This provides visibility without modification. When migration runs, it fixes any mismatch anyway, so checking first would be redundant noise._check_schema_migrationis a clean primitive: The base class method just callscheck_schema_migrationsand lets exceptions propagate. The prod-specific "catch and warn" policy lives inAzureSQLMemory.__init__where the context (prod vs. non-prod) is known. This follows the principle that base classes provide primitives, subclasses implement policy.AzureSQLMemory: The migration script reuses the existing constructor and_run_schema_migration()rather than duplicating migration logic. This avoids code divergence and ensures the release path uses the exact same code path as normal startup.upgrade head(not explicit revision): Since the script requires running from a release branch (enforced by environment checks),headon that branch IS the release revision. An explicit--target-revisionargument was redundant with the branch check.Tests and Documentation
Unit Tests Added (9 tests)
5 tests in
test_azure_sql_memory.py(prod guard):skip_schema_migration=Truestill runs check, never migrates4 tests in
test_migration.py:_check_schema_migrationdelegates tocheck_schema_migrations_check_schema_migrationraisesAutogenerateDiffsDetectedon mismatch (primitive behavior)_check_schema_migrationraisesRuntimeErrorwhen engine is Nonememory_migrations.py headoutputs a valid hex revision IDE2E Verification (
test_migration_release.py— not committed, local only)Test 1: Full migration flow — fresh SQLite DB is migrated to head via
AzureSQLMemory(skip=True)+_run_schema_migration()Test 2: Idempotency — running migration twice succeeds (second is no-op)
Test 3: Prod guard after migration — connecting to a migrated prod DB passes schema check
Test 4: Prod guard on old schema — connecting to an outdated DB logs a mismatch warning but doesn't block
Test 5: Environment checks — script fails when not on a release branch
Test 6: Unit tests — all 72 migration/guard unit tests pass
Also tested with the dev DB, which was already up to date but messages printed as expected.
Documentation
doc/contributing/10_release_process.md