cli: stage migrations next to chain dir so shared imports resolve#500
Merged
Conversation
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
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.
Why
Migration files often want to share state types from a sibling folder:
This fails as soon as a
next-migrationexists 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/Statebecomes.mops/types/State.moand errors.Fix
Stage into
<parent-of-chain>/.migrations-<canister>/instead. The staged files now sit at the same depth as the originals, so../types/Stateresolves to the same target either way.This requires
chainandnextto 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 ingit status.Breaking
Any
[canisters.<name>.migrations]whosechainandnexthad different parents is rejected. The default layout (chain = \"migrations\"+next = \"next-migration\") is unaffected.2.11.0introduced the migration feature one release ago, so adoption is small.Test plan
migrate.test.tstests pass, including two new tests that the sibling validation fires from bothmops checkandmops migrate new.with-nextfixture updated to use a sharedtypes/State.mo— exercises the imports-resolve-correctly behavior end-to-end.npm run checkandnpm run lintpass.