You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(migrate): skip staging when window is exactly the pending next migration (#503)
## 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
- [x] `check-limit=1 with pending next reports real next-migration path
on error` — pins the trimmed-to-1 branch
- [x] `empty chain with pending next reports real next-migration path on
error` — pins the empty-chain branch
- [x] `error inside a chain migration reports its file location` — pins
the staged-path behavior for the cases that still stage
- [x] `npm test -- --testPathPatterns=migrate.test.ts` — 19/19 pass
- [x] `npm run check` — clean
- [x] Pre-existing `build.test.ts` failures verified unrelated (stash +
retest on `main`)
Copy file name to clipboardExpand all lines: .agents/skills/mops-cli/SKILL.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -146,6 +146,8 @@ When `[canisters.<name>.migrations]` is configured, `mops check`, `mops build`,
146
146
147
147
`chain` and `next` must live in the same parent directory. Migration files can import from sibling folders via relative paths (e.g. shared types in `src/backend/types/`); mops stages the active chain into `<parent-of-chain>/.migrations-<canister>/`, preserving depth so relative imports resolve identically. The staged dir self-stamps a `.gitignore`; `mops init` also adds `.migrations-*/` to the project `.gitignore`.
148
148
149
+
`moc` diagnostics may print paths under `.migrations-<canister>/` — a staging dir that mops removes when the command finishes. The real file has the same name under `chain/` or `next/`.
150
+
149
151
Typical workflow: make a breaking change → `mops check` fails with a hint → `mops migrate new Name` → edit migration → `mops check` passes → `mops build` → deploy → `mops migrate freeze`.
Copy file name to clipboardExpand all lines: cli/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,7 @@
1
1
# Mops CLI Changelog
2
2
3
3
## Next
4
+
-`mops check`/`build`/`check-stable` skip migration staging when only the pending `next` migration is needed, so `moc` diagnostics reference the real `next-migration/<file>` path.
4
5
5
6
## 2.12.0
6
7
- Migration staging directory moved from `.mops/.migrations/<canister>/` to `<parent-of-chain>/.migrations-<canister>/`, so migration files can import shared modules from sibling folders (e.g. a `types/` folder next to `migrations/`) — relative imports now resolve to the same target whether moc reads the original chain dir or the staged one. The staged dir self-stamps a `.gitignore` so it doesn't pollute `git status`; `mops init` now also adds `.migrations-*/` to the project `.gitignore`
Copy file name to clipboardExpand all lines: docs/docs/09-mops.toml.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -167,6 +167,8 @@ When `[migrations]` is configured, do not add `--enhanced-migration` to `[canist
167
167
168
168
:::note
169
169
When a `next` migration exists or chain trimming is active, mops stages the active chain into `<parent-of-chain>/.migrations-<canister>/` for compilation. This keeps the staged files at the same depth as the originals so relative imports (e.g. a shared `types/` folder next to `chain` and `next`) resolve identically. The staged dir self-stamps a `.gitignore`, and `mops init` adds `.migrations-*/` to the project `.gitignore`.
170
+
171
+
`moc` diagnostics may point to a staged path under `.migrations-<canister>/`, which mops removes when the command finishes.
Copy file name to clipboardExpand all lines: docs/docs/cli/4-dev/08-mops-migrate.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,6 +61,8 @@ build-limit = 100
61
61
62
62
`chain` and `next` must live in the same parent directory. Migration files can import from sibling folders (e.g. a shared `types/` folder) using relative paths — mops stages the active chain into `<parent-of-chain>/.migrations-<canister>/` for compilation, preserving the depth of the originals so relative imports resolve identically. The staged dir self-stamps a `.gitignore`, and `mops init` adds `.migrations-*/` to the project `.gitignore`.
63
63
64
+
`moc` diagnostics may point to a staged path under `.migrations-<canister>/`, which mops removes when the command finishes.
65
+
64
66
See [`mops.toml` reference](/mops.toml#canistersnamemigrations) for all fields.
0 commit comments