CLI v3.0.0
·
14 commits
to main
since this release
Migrating from 2.x
Everything that requires action, in one list. Details in the themed sections below.
- Pin a compiler:
mops toolchain use moc <version>, commitmops.toml. Every command that compiles now requires the pin — there is no dfx fallback. - If you deploy with dfx: delete the
export DFX_MOC_PATH=moc-wrapperline from your shell config (dfx buildfails outright while it points at the removed binary), then read dfx support is removed — your dfx builds no longer use the pinned compiler. - Drop
--replica dfx/--replica pocket-icfrommops test/mops bench— the flag is gone, PocketIC is always used. Re-record benchmark baselines withmops bench --save. - Pin
pocket-icif you run replica tests, benches, or--check-deploy:mops toolchain use pocket-ic 15.0.0. There is no silent default. [toolchain] pocket-icbelow9.0.0: runmops toolchain use pocket-ic 15.0.0.- If you use
[optimize]: pin Binaryen withmops toolchain use wasm-opt <version>and commit it. Builds no longer pin one for you, and awasm-optfailure now fails the build. check-stablebaselines: point[canisters.<name>.check-stable].pathat a.mostfile — a.mosource is rejected.mops buildwrites one per canister.- CI pipelines: replace
--lock checkand theCIenv-var behavior with an explicit--lockedflag; it is accepted bymops installand every command that installs implicitly. - Replace
mops set-network <net>with theMOPS_NETWORKenvironment variable. mops watch: drop-g/-d(removed); no flags now means error + warning + format,--testis opt-in.- Scripts parsing
mops info <pkg> --versions: take the first line for the latest version, not the last. - Node.js >= 20 is required.
- Commit
mops.lock— libraries too; remove it from.gitignoreif the old advice put it there. - Publishing: delete the
dfx = "..."line from[package]if you still have one. - Vessel users:
mops initno longer migratesvessel.dhall— copy dependencies intomops.tomlby hand. - CI gates on
mops outdated: it now exits1when updates are available (it always exited0before), and2when the check itself fails. - Programmatic users of the
ic-mopspackage:downloadFileanddownloadPackageFilesreturnUint8Arrayinstead ofArray<number>.
dfx support is removed
- The
dfxanddfx-pocket-icreplicas are gone, and with them the--replicaflag onmops testandmops bench(deprecated since 2.14). PocketIC is always used. - The dfx-bundled
mocfallback is gone.mops build,check,check-stable,test,bench,docs,generate,syncandmops watchresolve the compiler only from[toolchain] mocand error naming the fix when it is unset.mops toolchain bin --fallbackis removed (the flag, not the command). mops toolchain initandmops toolchain resetare gone, along with themoc-wrapperbinary. Their job was exportingDFX_MOC_PATH=moc-wrappersodfx buildcompiled with the pinnedmoc. If you deploy with dfx, this is the entry to read:mops sourcesstill works as adfx.jsonpacktool, so dfx keeps resolving your mops dependencies — butdfx buildnow uses its own bundled compiler whilemops check/build/testuse your pinned one, and a program that passesmops checkcan build differently, or not at all, under dfx. In GitHub Actions the same applies silently:mops install/mops sourcesno longer writeDFX_MOC_PATHinto$GITHUB_ENV, so such a workflow stays green while compiling with a differentmoc. The supported path isicp, whose Motoko recipe builds by invokingmops build, so the pin propagates. If you stay on dfx, setDFX_MOC_PATHyourself and keep it in step with[toolchain] moc.mops watch --deployandmops watch --generateare removed, not replaced: mops is not a deployment tool, anddfx generateemits JS/TS bindings mops has never produced. Flag bundles fail loudly —mops watch -tgderrors withunknown option '-gd'; usemops watch -t. To deploy or regenerate declarations on change, runicp deploy/icp-bindgen(or the dfx equivalents) in a second terminal.mops initno longer contacts the registry for a dfx-versioned "default package set" (a freshmops.tomlhas no[dependencies]—mops add coreyourself) and no longer writesdefaults.build.packtoolinto adfx.jsonit finds. It touches nothing outside your project's own files.mops benchno longer readsprofilefromdfx.json; benchmark canisters are always compiled--release. Projects with"profile": "Debug"were silently benchmarking debug builds.- Benchmark baselines drift: PocketIC and the dfx replica report different instruction and heap counts, so the first
mops bench --compareafter upgrading shows a large diff wherever a dfx replica was implicitly in use. Change of measuring instrument, not a regression — re-record withmops bench --save. - The
dfxfield in[package]is rejected at publish with an error naming the field (documentation-deprecated since 2.7, but no runtime warning ever shipped). Delete the line. mops sourcesis unchanged, byte-for-byte, including its stdout. It prints--packageflags and has no opinion about who consumes them.
PocketIC and toolchain
- Breaking: replica tests,
mops bench,--check-deploy, andmops toolchain bin pocket-icrequire an explicit[toolchain] pocket-icpin. An unpinned project errors namingmops toolchain use pocket-ic 15.0.0— that version is a hint, not a runtime fallback, so it can move without changing anyone's replica. Attaching to an already-running server viaMOPS_POCKET_IC_URL(added in 2.24.0) still works without a pin. - Breaking: the legacy
pic-icPocketIC client is gone, and with it[toolchain] pocket-icpins below9.0.0(deprecated in 2.20). Migration:mops toolchain use pocket-ic 15.0.0. There is no upper bound — mops keeps no list of blessedpocket-icversions, same as formoc,wasmtimeandlintoko. @icp-sdk/coreupgraded from4.0.2to5.4.0(#652). Only affectsMOPS_NETWORK=local/MOPS_REGISTRY_HOST: update calls now use the IC HTTP APIv3endpoint, so the replica you point mops at must serve it —icpand recentdfxdo. Nothing changes for the defaulticnetwork orstaging.dist/vendor/pic.mjsno longer inlines a second copy and shrinks from 1.15 MB to 600 KB.- Removed legacy
mocvdetection:mops docsno longer resolvesmo-docfrom a mocv-managedDFX_MOC_PATH. Usemops toolchain use moc <version>. - Breaking:
[optimize]requires a[toolchain] wasm-optpin. Build commands now fail before compiling and name the fix (mops toolchain use wasm-opt <version>). Previously a project with[optimize]and no pin had itsmops.tomlrewritten by the nextmops buildormops bench, with the version chosen by a "latest release" lookup — so the same commit built different artifacts either side of a Binaryen release. This closes the last runtime "latest" lookup on the build path. - Breaking: a
wasm-optfailure fails the build instead of warning and keeping the unoptimized module, which left nothing downstream — anything that hashes, certifies or deploys the artifact — able to tell.--no-optimizestill skips the pass deliberately, and--verbosestill prints fullwasm-optoutput.
Checks and builds
- Breaking: the
check-stablebaseline must be a.mostfile.[canisters.<name>.check-stable].pathand themops check-stable <baseline>argument no longer accept a.mosource, inmops checkandmops check-stablealike; a.mopath is rejected up front. A.mobaseline described whatever that source said at the time of the run rather than what the canister actually holds, so it drifted silently and the check passed against the wrong state. Migration: pointpathat a.most—mops buildalready writes one per canister, and how it gets committed depends on who runs the deploy; seemops deployed. - On moc 1.12.0+,
mops checkandmops check-stablecheck upgrade compatibility faster and report it better for canisters with[migrations]: compatibility errors now point at your source (src/main.mo:3.1-11.2) instead of(unknown location), and a field the initial actor requires that no migration produces now fails as anM0267error rather than only warning (M0254) — a forgotten migration that previously slipped through as a warning will now fail the check. Older moc pins and canisters without[migrations]are unaffected.
Lockfile and integrity
- Breaking:
--lockedreplaces--lock <check|update|ignore>, which is removed frommops add,remove,install,syncandupdate(#516). Two modes, one flag: plain commands are the dev flow,--lockedis the CI flow.--lock check→--locked. Strictly stronger: it also refuses to write the lockfile, so a CI run can never mutate it. Fails whenmops.lockis missing, unparseable, not the current format version, does not pin whatmops.tomldeclares, or records a file hash the registry disagrees with. Accepted bymops installand every implicitly-installing command (build,check,check-candid,check-stable,test,bench,generate candid), so a pipeline can runmops test --lockedwith no install step.mops sourcesdeliberately has no--locked(machine-parsed mid-build) — putmops install --lockedearlier in the pipeline.--lock update→ plainmops install, now self-healing: a missing, unparseable, legacy-format ormops.toml-inconsistent lockfile is regenerated instead of erroring, as is one carrying absolute localpathentries from a pre-2.19.2 CLI.--lock ignore→ no successor; the lockfile is always maintained (cargo model).- Note when moving off
--lock check:--lockedrequires the current format (v3), while--lock checkaccepted v1/v2. A committed v1/v2 lock fails--lockedwith a message saying to runmops installonce and commit the upgrade. 3.0.0-beta.4and3.0.0-beta.5accepted--lock <mode>as a hidden, value-ignoring shim so v2 call sites would keep parsing during the rollout. It is gone;--lockis an unknown option again.
- Breaking: the
CIenvironment variable no longer switchesmops installto check mode (deprecated in 2.18). Pass--lockedexplicitly. (#516) - Breaking: integrity is verified at download time instead of by re-hashing
.mops/on every install (#517). Files are hashed as they arrive and compared against the registry before the package is committed to the cache, so a corrupted download never reaches your project.- Guarantee change: editing a file under
.mops/no longer fails your next install/build/test — installs are not a tamper gate for files already on disk. If a pipeline relied on that, runmops verify, which re-hashes every file the lockfile records and checks the lock againstmops.tomland the registry. It also audits packages cached by an earlier CLI, which were never download-verified;mops cache cleanforces a verified re-download. Neither--lockednormops verifyre-walks the graph, so a transitive change reached through a localpathdependency is not detected. - The removed re-hash was paid on every install, proportional to the whole tree (~136 ms for an 842-file tree on a warm SSD, worse on cold caches or networked filesystems).
- Guarantee change: editing a file under
- Breaking:
mops build,check,check-candid,check-stable,test,benchandgenerate candidno longer silently ignoremops.lockwhen installing implicitly — they follow the same lock flow asmops install, and a download that fails its integrity check aborts them with exit code 1 (previously they carried on against a partially-populated.mops/). mops installalso self-heals what it previously ignored: a structurally-wrong lock (missing/non-objectdepsorhashes) is regenerated instead of throwing aTypeError; adepsentry that disagrees withmops.toml(previously installed as-is — the wrong version, silently) and ahashessection inconsistent withdepsare both detected offline and repaired.- Known limitation, by design: hand-edited file hash values in
mops.lockare not repaired bymops install— detecting them costs a ~1.2 s registry call that would outweigh the re-hash this release removes. They are consumed only by--lockedandmops verify(never by the build), and both report the mismatch with the recovery that works: restoremops.lockfrom version control, or delete and reinstall. - Breaking (guidance): commit
mops.lock, for libraries as well as applications. A library's lock has no effect on consumers (they resolve their own graph) and makes the library's own CI reproducible. The old gitignore advice is gone from themops.lock created.message and the docs. - Fixes for incomplete global-cache state: a cache entry counts as cached only if it is complete (empty leftover directories from interrupted runs are deleted and re-downloaded instead of being treated as hits), packages missing from the global cache are re-downloaded when syncing
.mops, and the advisorymoc/lintokorequirements check falls back to the global cache instead of crashing on a manifest missing from.mops/. mops.lockis now written with all keys sorted — dependencies, packages, per-file hashes, graph entries and GitHub entries — so unrelated installs no longer produce diff churn or spurious merge conflicts. The lockfile format is unchanged: an existing lockfile with unsorted keys stays valid, still passesmops install --locked, and is reordered only the next time something legitimately updates it.mops.lockis now a trust anchor on the install path. When the lockfile already covers a package being downloaded, its bytes are verified against the hashes recorded there — a local, committed record — so no registry call is needed at all. A clean clone with a committed lock and a cold cache therefore makes no consensus call, where previously it made one per package (~1.2–2.5 s each, each blocking the next). This is the model cargo uses withCargo.lock.- When the lockfile cannot answer — no lock, a stale one, a package new to the lock, or a version that lost a conflict — the registry's consensus reply is used, as before, and always before the bytes are staged into the cache. Verification is therefore always against either a committed local record or a subnet-agreed one, at the moment of admission, regardless of which command is installing.
- Registry file hashes are fetched at most once per process, so a package downloaded during an install costs nothing further when the lockfile is written.
- A hash mismatch now names its source. If the expectation came from
mops.lock, the message says so and points at restoring or regenerating the lockfile, rather than suggesting a retry that cannot succeed. - GitHub dependencies are now covered by the lockfile.
mops.lockrecords the resolved commit and a content hash for everyrepo = "..."dependency, and an install verifies the fetched archive against them before it enters the cache. A ref carrying no commit — a bare#main, or a tag — is resolved once and pinned and then fetched by commit, so a moved tag or a force-push can no longer silently change what you build.mops verifyaudits them on disk too. Migration: for a project with GitHub dependencies, a lockfile written by an older CLI counts as stale —mops installregenerates it, and--lockedfails until the result is committed. They are often transitive, so this can apply to a project whose ownmops.tomldeclares none. - Behaviour change: plain
mops installnow fails when it has to download a package whose hashes disagree with the committed lockfile. It remains true that files already on disk under.mops/are not re-hashed by an install —mops verifyis still the command that audits those.
Dependency resolution
- Version comparison uses a real semver comparator instead of
parseInton dot-split parts. Semantics are unchanged — bare1.2.3is still exact, conflicts still resolve to the root version or the highest — but GitHub refs now compare correctly: prereleases no longer tie with their release or with each other (rc.2vsrc.10was a coin flip),0.16no longer equals0.16.1, and#release-v1.2.0no longer parses as0.2.0. Registry versions are validatedx.y.zat publish, so nothing changes for them. - Breaking: cross-major dependency conflicts are reported by default on every resolving command (
mops install,build,test,sources, …), on stderr somops sourcesstdout stays machine-parseable. It is a warning — resolution still succeeds. The report names every dependent, which version won, and that pinning in your rootmops.tomlis how you choose otherwise. Minor/patch skew stays silent, and only registry dependencies take part. Since a validmops.lockskips the graph walk, the report appears on the run that produces or updates the lock. (mops watchcannot surface it yet: its redraw clears the terminal.) mops sources --conflicts ignoresilences the report for the whole command — pass it where your build tool invokesmops sourcesafter you have reviewed a conflict and decided to keep it.--conflicts errorstill exits non-zero. Other commands have no opt-out.
Install engine
- Parallel package installs. Packages download through a bounded pool instead of one at a time, and branches of the graph requesting the same package share one download. A cold install of 8 root packages plus transitives measured 19.7 s → 13.2 s. New
mops install --concurrency <n>andMOPS_CONCURRENCYcap simultaneous registry requests; the default derives from the CPU count and the file-descriptor soft limit (2 × cores, clamped to 4–16), so a many-core machine with a lowulimit -ncannot exhaust its own descriptors. The undocumented heuristic that capped download threads wheneverGITHUB_ENVwas set is removed — it detected a brand, not a constraint. - Installs self-heal on transient network failures. A
fetch failed,ECONNRESETorEMFILEretries up to twice with the request concurrency halved, so an environment that cannot sustain the default parallelism degrades to a slower install instead of a broken one. Packages that already downloaded come from the cache; only the failures are re-fetched. Registry answers such as "Package not found" are never retried. - Roughly 1.5 s of fixed cost removed from every install, independent of how many packages a project has: registry file-hash lookups are batched into one request that starts before the downloads so the consensus round overlaps them, dependency resolution runs once per command instead of three to five times, the API compatibility check runs alongside the install rather than before it, install telemetry no longer waits for a certified reply, and the agent no longer synchronises time against a ledger canister it never otherwise talks to.
mops updateis single-pass. Outdated dependencies download in parallel through the same poolmops installuses,mops.tomlis rewritten once after the installs instead of once per package, and the registry is notified in one batched call. Failure handling is unchanged: a dependency that fails to update is reported, keeps its oldmops.tomlentry and exits2without blocking the others. Each applied update printsUpdated <pkg> <old> -> <new>.mops outdatedandmops updateno longer make a registry call when a project has no registry dependencies to check.- Breaking for programmatic consumers of the
ic-mopspackage:downloadFileanddownloadPackageFilesreturnUint8Arrayinstead ofArray<number>.
Defaults and CLI strictness
- Breaking: unknown flags before
--are rejected with an error instead of silently swallowed as arguments (a mistypedmops check --nopeused to be treated as an ordinary argument). Applies tobuild,check,check-stable,test,bench,generate candidandlint. The-- <tool flags>passthrough is unaffected:mops check -- -Werror,mops lint -- --severity warningkeep working. - Breaking:
mops watchwithout flags runs the safe informative set — error check, warning check, formatting — instead of "almost everything";--testis opt-in. Passing any flag still selects only the named tasks. - Breaking:
mops testdefaults to theverbosereporter for any number of files. Pass--reporter filesfor the old multi-file output. - Breaking:
mops info <pkg> --versionslists newest-first, matchingmops toolchain info --versions. Scripts that took the last line (| tail -1) should take the first (| head -1). mops checkgets--no-lintto skip the automatic lint step for one run whenlintokois pinned. Projects without a pin are unaffected.- Fix
mops lint -- <lintoko flags>failing withtoo many arguments(Commander 13 regression).mops lint <filter> -- <lintoko flags>works too. mops update --helpand its doc page now state that the command rewritesmops.toml— it iscargo upgradesemantics, notcargo update— and list its exit codes.
Errors and exit codes
- Error messages now go to stderr. Failures used to be printed with
console.log, somops <cmd> > out.txtswallowed them; every error now reaches the terminal even when stdout is redirected or machine-parsed. Exit codes are unchanged. Cleanup that used to be skipped on failure — build and--fixlock release, temp dirs — now runs reliably. mops updatenow exits2when re-pinning a GitHub dependency fails, and carries on to the remaining dependencies. A failed branch lookup previously exited0— an incomplete update looked like success — and a failed download killed the whole update with exit1.- Commands run outside a mops project now exit
1after printing the missing-mops.tomlerror.mops bump,mops sync,mops owner *andmops maintainer *used to print it and exit0. A registry lookup error inmops add— including theaddcallsmops syncmakes — also exits1now instead of0. mops updatenow exits2for an unknown package or a missingmops.toml, matchingmops outdated. It previously exited0after printingPackage "<name>" is not installed!, so a typo in a scripted update looked like success.
Removals
- Breaking:
mops set-networkandmops get-networkare removed. Use theMOPS_NETWORKenvironment variable —MOPS_NETWORK=local mops install(orstaging); unset meansic. The removed commands stored the choice in a file inside the installed CLI directory: frequently not writable (CI, Docker, root-owned globals), shared across every project on the machine, and wiped by the nextnpm i -g ic-mops.MOPS_NETWORKhas been the documented mechanism since 2.5.1.mops get-networkhas no replacement — read$MOPS_NETWORK. - Remove vessel/dhall support (deprecated since 2.14).
mops initno longer migratesvessel.dhall— copy dependencies intomops.tomland deletevessel.dhall/package-set.dhall. GitHub dependencies (repo = "...") are unaffected, but transitives they declare via vessel files are no longer resolved — add what you need to your ownmops.toml..vesseldirectories are no longer excluded frommops test/watchscans, and thedhall-to-json-clidependency is gone.
Runtime
- Breaking: Node.js >= 20 is required (
enginesbump from >= 18); installs on Node 18 fail with an engines error. (#288)
Fixed
- A local
pathdependency's ownmops.tomlno longer goes unnoticed. Adding or bumping a dependency inside a local package leftmops.lockjudged fresh, somops installexited 0, installed nothing, and never passed the new dependency to the compiler — the package then failed to build against a dependency mops had reported as installed.mops.locknow records a hash of the[dependencies]of every path dependency it reaches, transitively, so editing any of them makes the lockfile stale. - Changing
MOPS_ENVno longer leavesmops.lockpinned to the previous environment.{MOPS_ENV}paths are stored expanded in the lockfile, but the freshness check compared the unexpanded string, so a fullmops installunder a new environment exited 0 and kept building against the old environment's directories.mops installnow re-resolves,mops sourcesreports the current environment, andmops install --lockedfails rather than silently using the wrong paths. Note that a committed lockfile now only satisfies--lockedfor theMOPS_ENVit was generated under. - Breaking: only the winning versions and their own dependencies are installed — the closure of the winners, as cargo and pnpm do it. Previously a package declared only by a version that lost a conflict was still downloaded and passed to
mocas--package. A project that was compiling against such a package without declaring it now fails with an unresolved import — add the dependency tomops.toml. Dependency edges for losing versions stay in the lockfile, so regenerating a lock does not need those versions back on disk. mops outdatedis now usable as a CI gate. It exited0whether or not anything was outdated. It now exits1when updates are available and2when the check itself could not be completed (nomops.toml, unknown package, registry or GitHub lookup error), so a partial report can never be mistaken for a clean bill of health.1for "found something" matchesnpm outdatedandpnpm outdated.mops outdatedandmops updateno longer disagree.outdatedskipped GitHub dependencies whilemops updateupdates them, so it could print "All dependencies are up to date!" for a project wheremops updatewould rewrite a GitHub pin. GitHub dependencies whose branch has moved past the pinned commit are now reported, using the same rulemops updateapplies.mops updateno longer declares a package twice when it is declared in both sections. Givencorein[dependencies]and"core@1"in[dev-dependencies], the update was written under the[dependencies]key but into[dev-dependencies], leaving the intended entry stale and the package declared twice. The key and the section now come from the single declaration that matched.- A pinned alias no longer claims versions outside its own segment.
"map@1"matched10.xand"map@8"matched80.x— a version prefix was compared without a segment boundary — somops updateandmops outdatedcould report an update against the wrong declared version and write it under the wrong key. mops add <pkg> --devnow moves an existing[dependencies]entry into[dev-dependencies]instead of declaring the package twice; a plainmops add <pkg>moves it back.mops remove <pkg>now finds the package in whichever section declares it, so removing a dev-only dependency no longer requires--dev. When both sections declare it, both entries go;--devstill removes only the dev entry.mops add org/repois accepted as a GitHub shorthand instead of crashing with an unhandledERR_INVALID_URL. An argument that is neither a package name, a GitHub repo nor a local path now fails with a message naming the accepted forms, and a failed repo lookup prints an error rather than a stack trace.mops add <pkg>@<version>no longer collapses an existing pinned alias such as"map@8.1.0" = "8.1.0"into the bare package key. Replacing a declared version is now reported, along with the pinned alias to add if both versions should be kept.mops addandmops removenow name the affected section in their output.mops syncno longer destroys a pinned alias dependency. Givenmap = "9.0.1"and"map@8.1.0" = "8.1.0", sync compared imports (map@8.1.0) against alias-stripped manifest keys (map), so it reported the alias as both missing and unused — adding it overwrotemapwith8.1.0, and a single run could remove the dependency entirely. Aliases are now matched verbatim and added under their own key.mops syncadds packages imported only fromtest,tests,benchorbenchmarkdirectories to[dev-dependencies]rather than[dependencies]. Already-declared packages are never moved between sections.mops syncremoves an unused package from both sections when it is declared in both; previously it was only removed from[dependencies], leaving a dangling entry that the next run reported again.mops syncis roughly twice as fast — it runsmoc --print-depsonce per file instead of twice.mops remove --dry-runis now side-effect free. It no longer deletes local cache directories or rewrites a stalemops.lock, and it printsWould remove package …instead of reporting the removal as done.mops cache cleanworks on Windows and on non-icnetworks. Its safety guard compared apath.joinresult against a forward-slash suffix, so it failed with "Invalid cache directory" on every Windows run and for every network-scoped cache directory. The replacement is separator-agnostic and strictly narrower: it also requires the directory to be inside the global cache root, rejecting a traversingMOPS_NETWORK.mops cache cleanno longer deletes./.mopswhen run outside a project, where an empty root directory made it target the current working directory.mops updateandmops outdatednow share one rule for deciding when arepo = "..."dependency is out of date, so the two commands cannot disagree about it.mops installno longer crashes with a rawRangeError: Maximum call stack size exceededwhen two localpathdependencies require each other, or when one requires itself. The install walk now skips a local package it has already visited in the same run, naming neither a cycle nor an error — the packages install normally.- Fixed
mops remove <pkg>crashing withInvalid dependency value ""when the dependency is a local path dep. mops removenow echoes the dependency value it removed for GitHub and local path deps, instead of an empty version.
Added
mops outdated [pkg]accepts a package name, matchingmops update [pkg].mops update --verbose, matchingmops add,mops removeandmops install.mops sync --dry-runprints what would be added and removed without touchingmops.toml, the local cache ormops.lock.mops cache clean --globalcleans only the global cache and keeps the project's.mopsdirectory.mops.lockgains an optionallocalDepsHashfield, written only for projects that declare a localpathdependency. Those projects have their lockfile regenerated once on the nextmops install, andmops install --lockedfails until the regenerated lockfile is committed. Projects without path dependencies are unaffected — the field is omitted entirely and existing lockfiles stay valid.
SHA256: 79320180f705ecb98cba81994ddcb76f6fbe6e752c10f5c745ce2053f146a7a1
Verify build:
cd cli
docker build . --build-arg COMMIT_HASH=89154ce076a48fae0c76d60506b1a0e3f44294fb --build-arg MOPS_VERSION=3.0.0 -t mops
docker run --rm --env SHASUM=79320180f705ecb98cba81994ddcb76f6fbe6e752c10f5c745ce2053f146a7a1 mops