Skip to content

fix(migrate): skip staging when window is exactly the pending next migration#503

Merged
Kamirus merged 8 commits into
mainfrom
docs/migration-staged-error-paths
Apr 21, 2026
Merged

fix(migrate): skip staging when window is exactly the pending next migration#503
Kamirus merged 8 commits into
mainfrom
docs/migration-staged-error-paths

Conversation

@Kamirus
Copy link
Copy Markdown
Collaborator

@Kamirus Kamirus commented Apr 21, 2026

Problem

When [canisters.<name>.migrations] triggers staging (a pending next migration, or check-limit/build-limit trimming the chain), mops creates a temp .migrations-<canister>/ directory of symlinks and points moc at it. Errors look like:

.migrations-backend/20250401_000000_RenameId.mo:4.12-4.19: type error [M0050] ...

The staged dir is rm -rf-ed in a finally before 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-migration takes a single directory. When the active window straddles chain/ and next-migration/, or when trimming hides files inside chain/, mops needs a synthesized directory holding exactly the files moc should see.

Fix

When moc only needs the pending next migration — empty chain, or check-limit = 1 with a pending next — there's nothing to merge. Point moc at next-migration/ directly:

Before:

.migrations-backend/20250401_000000_RenameId.mo:4.12-4.19: type error [M0050] ...

After:

next-migration/20250401_000000_RenameId.mo:4.12-4.19: type error [M0050] ...

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 branch
  • empty chain with pending next reports real next-migration path on error — pins the empty-chain branch
  • error inside a chain migration reports its file location — pins the staged-path behavior for the cases that still stage
  • npm test -- --testPathPatterns=migrate.test.ts — 19/19 pass
  • npm run check — clean
  • Pre-existing build.test.ts failures verified unrelated (stash + retest on main)

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
@Kamirus Kamirus requested a review from a team as a code owner April 21, 2026 09:22
Kamirus added 2 commits April 21, 2026 11:49
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
@Kamirus Kamirus changed the title docs(migrate): note that moc reports staged paths in chain diagnostics fix(migrate): skip staging when window is exactly the pending next migration Apr 21, 2026
Kamirus added 5 commits April 21, 2026 14:17
…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
@Kamirus Kamirus merged commit 82d400d into main Apr 21, 2026
27 checks passed
@Kamirus Kamirus deleted the docs/migration-staged-error-paths branch April 21, 2026 13:02
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.

1 participant