fix(migrate): skip staging when window is exactly the pending next migration#503
Merged
Conversation
When `[migrations].next` is set or `check-limit`/`build-limit` trims the chain, mops stages the active chain into `.migrations-<canister>/` and passes that directory to moc. Diagnostics for chain files therefore reference the staged path (e.g. `.migrations-backend/2025...AddEmail.mo`) rather than the original `migrations/...` path. Editor jump-to-error still works because the staged files are symlinks, but the path in raw error text was a recurring source of confusion. Document this in the mops.toml reference, the `mops migrate` page, and the mops-cli skill, and add a snapshot test that pins the current behavior so a future fix (e.g. rewriting paths in moc stderr) is an intentional snapshot update. Made-with: Cursor
Editor jump-to-error does not work on the printed path: the staged directory is removed in a `finally` block before the process exits, so by the time the user reads the error, the file is gone. Tell users to open the same filename under `chain` (or `next` for the pending migration) instead. Made-with: Cursor
…gration The staged migration directory only ever existed because moc takes a single `--enhanced-migration=<dir>` and we sometimes need to merge files from `chain/` and `next-migration/`. When the active window is exactly one file from `next-migration/` (the common dev-loop case `check-limit = 1` with a pending next, or no frozen chain yet), there is no merge to do — moc can be pointed at `next-migration/` directly. Errors then reference the real path the user is editing instead of a staged copy that gets `rm -rf`-ed before the user reads the message. Refactored `prepareMigrationArgs` to fold the previous early-return (no staging) and the new shortcut into a single `realDir` decision, removing duplicated arg-building. Same behavior for every other trimming/staging case. Updated docs and CHANGELOG; added a snapshot test that pins the real-path behavior. Made-with: Cursor
…rtcut Revert the structural refactor of `prepareMigrationArgs` from the previous commit; the only behavior change needed is a single early- return branch for "moc only needs the pending next migration". Net change in migrations.ts is now +10/-0 instead of churning the existing shape. Also align the three doc locations with the changelog (both `check-limit = 1 with pending next` and `no frozen chain yet` trigger the shortcut), and add a snapshot test for the empty-chain branch so that case is pinned, not just structurally implied. Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
Made-with: Cursor
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.
Problem
When
[canisters.<name>.migrations]triggers staging (a pendingnextmigration, orcheck-limit/build-limittrimming the chain), mops creates a temp.migrations-<canister>/directory of symlinks and points moc at it. Errors look like:The staged dir is
rm -rf-ed in afinallybefore the process exits, so by the time the user reads the error the path no longer resolves — editor jump-to-error fails, and CI logs contain a path that looks like an internal artifact.Why staging exists
moc --enhanced-migrationtakes a single directory. When the active window straddleschain/andnext-migration/, or when trimming hides files insidechain/, mops needs a synthesized directory holding exactly the files moc should see.Fix
When moc only needs the pending
nextmigration — empty chain, orcheck-limit = 1with a pending next — there's nothing to merge. Point moc atnext-migration/directly:Before:
After:
This covers the common dev-loop case (writing a new migration with
check-limit = 1) and the first-migration case (no frozen chain yet). Every other trimming / merge case still stages — diagnostics there continue to print the.migrations-backend/...path.Test plan
check-limit=1 with pending next reports real next-migration path on error— pins the trimmed-to-1 branchempty chain with pending next reports real next-migration path on error— pins the empty-chain brancherror inside a chain migration reports its file location— pins the staged-path behavior for the cases that still stagenpm test -- --testPathPatterns=migrate.test.ts— 19/19 passnpm run check— cleanbuild.test.tsfailures verified unrelated (stash + retest onmain)