Skip to content

cli: stage migrations next to chain dir so shared imports resolve#500

Merged
Kamirus merged 3 commits into
mainfrom
cli/migration-staging-sibling-imports
Apr 20, 2026
Merged

cli: stage migrations next to chain dir so shared imports resolve#500
Kamirus merged 3 commits into
mainfrom
cli/migration-staging-sibling-imports

Conversation

@Kamirus
Copy link
Copy Markdown
Collaborator

@Kamirus Kamirus commented Apr 20, 2026

Why

Migration files often want to share state types from a sibling folder:

migrations/20250101_000000_Init.mo  ─ import State \"../types/State\"
types/State.mo                      ─ shared type definitions

This fails as soon as a next-migration exists or chain trimming kicks in. mops symlinks the chain into .mops/.migrations/<canister>/ and points moc at it, but moc resolves relative imports from the symlink's parent — so ../types/State becomes .mops/types/State.mo and errors.

Fix

Stage into <parent-of-chain>/.migrations-<canister>/ instead. The staged files now sit at the same depth as the originals, so ../types/State resolves to the same target either way.

This requires chain and next to share the same parent — enforced with a clear validation error at every entry point (check, build, migrate new/freeze, check-stable).

The staged dir self-stamps a .gitignore (*) so it doesn't show up in git status.

Breaking

Any [canisters.<name>.migrations] whose chain and next had different parents is rejected. The default layout (chain = \"migrations\" + next = \"next-migration\") is unaffected. 2.11.0 introduced the migration feature one release ago, so adoption is small.

Test plan

  • All 16 migrate.test.ts tests pass, including two new tests that the sibling validation fires from both mops check and mops migrate new.
  • with-next fixture updated to use a shared types/State.mo — exercises the imports-resolve-correctly behavior end-to-end.
  • npm run check and npm run lint pass.

Kamirus added 3 commits April 20, 2026 15:02
Migration files often want to import shared state types from a sibling
folder (e.g. types/State.mo next to migrations/). Today this fails as
soon as a next-migration exists or trimming kicks in: mops symlinks the
chain into .mops/.migrations/<canister>/, and moc resolves relative
imports from the symlink's parent — not the realpath — so ../types/State
points at .mops/types/State.mo and errors.

Stage into <parent-of-chain>/.migrations-<canister>/ instead. The staged
files now sit at the same depth as the originals, so the same relative
import resolves to the same file in both layouts.

Enforce that chain and next live in the same parent directory; without
that invariant a single staged dir cannot stand in for both.

Made-with: Cursor
…sages

- Stamp `.gitignore` (containing `*`) inside the staged dir so git
  ignores it without users needing to add `.migrations-*` to their own
  .gitignore. Self-cleaning even if a process is killed before
  cleanup() runs.
- Add a second sibling-validation test exercising `mops migrate new`
  (different entry point than `mops check` covered earlier) — locks in
  that the validator runs on every public command.
- Rewrite the validator's "fix it" example to mirror the canonical
  default layout (`migrations` + `next-migration`) instead of an
  artificial `migrations/chain` + `migrations/next` wrapper.
- Simplify the parent-directory computation to one helper instead of
  round-tripping through resolveConfigPath().
- Rephrase the CHANGELOG hint to cover all non-sibling layouts, not
  just the docs-example one.

Made-with: Cursor
Even with the staged dir self-stamping a `.gitignore` (`*`), the dir
itself still appears as untracked in `git status` until git is told
about it. Belt-and-suspenders the user experience:

- `mops init` now adds `.migrations-*/` to the project .gitignore
  alongside `.mops`. Idempotent — re-running init doesn't duplicate
  entries.
- Add `.migrations-*/` to this repo's own .gitignore so leaked staged
  dirs from a crashed test run don't pollute `git status`.
- Update docs and CHANGELOG to describe both layers (self-stamp +
  init).

Made-with: Cursor
@Kamirus Kamirus marked this pull request as ready for review April 20, 2026 13:29
@Kamirus Kamirus requested a review from a team as a code owner April 20, 2026 13:29
@Kamirus Kamirus merged commit 256e0c7 into main Apr 20, 2026
21 checks passed
@Kamirus Kamirus deleted the cli/migration-staging-sibling-imports branch April 20, 2026 13:32
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