fix(deploy): script pending migrations from the first unapplied one - #113
Merged
Merged
Conversation
The migration-script artifact -- the thing a reviewer reads before approving the production environment gate -- picked its starting point with `[.[] | select(.applied == true)] | last`, which assumes applied migrations form a prefix of the id-ordered list. They do not. A PR that branches early can merge after a sibling, leaving a pending migration with a LOWER id than migrations already in the database. #106 merged after #107/#108 and did exactly that: 20260827_AddProjectDateOverrides sat unapplied below three applied 20260829 migrations, so "last applied" resolved to the newest id, and scripting forward from there produced an empty file. The efbundle applies all pending migrations regardless of ordering, so the deploy itself was correct -- but the approval gate showed nothing while two columns were about to be added. Script from the migration *before the first unapplied one* instead. --idempotent already guards every statement, so already-applied migrations caught in that range are no-ops. Two edge cases the old query got wrong are now handled explicitly: nothing pending writes a comment rather than an empty artifact, and a database with no migrations applied yields EF's "0" marker instead of failing the step. The hard error is now scoped to what it was meant to catch -- an unreadable migration list, i.e. the connection failing behind `|| true`.
ChristopherHoffman
deleted the
fix/deploy-migration-script-out-of-order
branch
September 4, 2026 01:14
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.
The bug
The
migration-scriptartifact — what a reviewer reads before approving theproductionenvironment gate — chose its starting point with:That assumes applied migrations form a prefix of the id-ordered list. They don't. A PR that branches early can merge after a sibling, leaving a pending migration with a lower id than migrations already in the database.
#106 merged after #107/#108 and did exactly that:
"Last applied" resolved to
AddDeviceTokens, and scripting forward from there produced an empty file.The deploy itself was correct.
efbundleapplies all pending migrations regardless of ordering, soAddProjectDateOverrideswas applied. What was lost is review: the approval gate showed an empty script for a run that was about to add two columns.The fix
Script from the migration before the first unapplied one.
--idempotentalready guards every statement, so already-applied migrations caught in that range are no-ops.20260829110351→ empty script20260826034417→ includes bothAddColumnsnone→-- No pending migrations.0→ full scriptThe last two were previously wrong as well: an empty artifact is indistinguishable from this bug, and the hard error fired on an empty result rather than on what it was meant to catch — an unreadable migration list, i.e. the connection failing behind
|| true. That guard now keys off the list itself.Verification
The step's selection logic was exercised against the four shapes in the table above. It has not run in CI yet —
deploy.ymlonly triggers on av*tag, so the first real proof is the next release'smigration-scriptartifact. Worth a closer read than usual for that reason.Not addressed
20260827122935_AddProjectDateOverrides.Designer.cscarries a pre-push-notification snapshot (noDeviceToken), which is inherent to the out-of-order merge. It's harmless — EF scaffolds new migrations fromPrintLogContextModelSnapshot.cs, which is correct, which is also why CI'shas-pending-model-changesstayed green. It would only matter to amigrations removereaching back past it.