Skip to content

feat(cli): confirm major-version jumps in mops self update - #697

Merged
Kamirus merged 2 commits into
v3from
kamil-v3/self-update-major-guard
Aug 10, 2026
Merged

feat(cli): confirm major-version jumps in mops self update#697
Kamirus merged 2 commits into
v3from
kamil-v3/self-update-major-guard

Conversation

@Kamirus

@Kamirus Kamirus commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Same guard as #696, on the v3 line: a major jump in mops self update prints the release-notes link and asks for confirmation; non-interactive environments skip the update with a notice and exit 0 (erroring would break scripted updates the day a major ships), naming mops self update --major; an unparseable /tags/latest body is an error instead of an npm install spec. Same-major updates are unchanged.

#696 is what partially protects the 2.x→3.0 jump (client-side check, so only users who update into it get it). This one covers 3.x→4.x permanently.

Decision table in helpers/self-update-kind.ts with unit tests for the prerelease edges — 2.20.0 → 3.0.0-beta.1 prompts, 3.0.0-beta.1 → 3.0.0 does not, which matters while previews ship from this branch. Full v3 suite passes (26 suites, 265 tests, 75 snapshots).

🤖 Generated with Claude Code

Port of the 2.x guard (kamil/self-update-major-guard) to the v3 line,
so the 3.x -> 4.x jump is covered permanently. A major jump prints the
release-notes link and asks; non-interactive environments refuse and
name the fix verbatim: mops self update --major. An unparseable
/tags/latest body errors instead of reaching npm as an install spec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Cursor AI review

👍 APPROVE — looks safe to merge

Category Assessment Details
Summary Adds a major-version confirmation gate to mops self update (--major escape hatch, non-TTY skip-with-success, reject unparseable /tags/latest), with docs, changelog, and classifier unit tests.
Code Quality Decision table isolated in classifySelfUpdate; confirmation UX reuses the existing prompts/onCancel pattern from owner.ts/maintainer.ts; no speculative helpers.
Consistency --major naming matches mops update --major in cli.ts; --help, docs/docs/cli/6-self/01-mops-self-update.md, and ## 3.0.0 changelog entry stay aligned with the new behavior.
Security Traced update()getLatestVersion() → npm/pnpm install of ${url}/versions/${latest}.tgz; invalid tags now process.exit(1) instead of being interpolated into the install URL; no auth/identity/integrity paths touched.
Tests cli/tests/self-update.test.ts covers the classifier decision table (same-major, major, prerelease edges, invalid tags); network/install wiring remains untested as before this PR. moduleNameMapper in jest.config.js only enables the .js import style used by the new test.
Maintainability Small pure helper with explicit SelfUpdateKind union; comments document the non-TTY success-exit contract that scripts rely on.

Verdict

Decision: APPROVE
Risk: Low
Reason: Contained CLI safety guard outside registry/install/auth paths; same-major updates unchanged, non-interactive scripts keep succeeding, and docs/changelog/--help match the intended behavior.


Generated for commit bb20004

@automation-sa-sre automation-sa-sre left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: the AI review verdict for df0a374 is APPROVE. See the "Cursor AI review" comment for details.

Same reasoning as on the 2.x line: a scripted mops self update must
keep succeeding after a new major ships, staying on its major, rather
than failing until someone edits the script. Notice + exit 0; --major
opts in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@automation-sa-sre automation-sa-sre left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval: the AI review verdict for bb20004 is APPROVE. See the "Cursor AI review" comment for details.

@Kamirus
Kamirus merged commit 78405ad into v3 Aug 10, 2026
25 checks passed
@Kamirus
Kamirus deleted the kamil-v3/self-update-major-guard branch August 10, 2026 12:23
Kamirus added a commit that referenced this pull request Aug 10, 2026
…ncher pin) (#702)

Brings v3 level with main. Three changes flow in, one needing a by-hand
carry:

- **[#699](#699) — decompress
removal.** The call site moved on v3 (`cli/vessel.ts` →
`cli/commands/install/install-from-github.ts`), so the extractor swap
was carried by hand: main's `extractGithubZip` with v3's import depths.
Verified on v3 by installing a real GitHub dep
(`dfinity/motoko-base#moc-0.14.14`) — extracted at the right paths, lock
integrity passes. `npm audit` clean on the merged tree.
- **[#696](#696) — self-update
guard.** Already on v3 via
[#697](#697); the merge
resolves to one `prompts` import and otherwise identical code.
- **[#700](#700) —
network-launcher pin.** `icp.yaml` merged clean; AGENTS.md's icp-cli
bullet takes main's reworded version on top of v3's dfx bullets.

**Changelog resolution**: v3's `## Next` gains the decompress entry (the
release workflow rolls `Next` into the version heading at release time,
so it lands in 3.0.0 automatically) and keeps the 2.x-only moc-wrapper
note; main's self-update entry is dropped from `Next` because #697
already placed it in the `3.0.0 (unreleased)` section. The 3.0.0 section
itself is untouched, so this does not conflict with
[#701](#701).

`cli/package-lock.json` regenerated from the merged `package.json`
rather than resolved textually — the ~500-line shrink is `decompress`'s
transitive tree leaving.

Full merged suite: 269/269, 75 snapshots. (Two initial failures were a
stale local `dist/` predating the merge, green after rebuild — same
artifact-staleness mode as in #699's development, not a code issue.)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Kamirus added a commit that referenced this pull request Aug 13, 2026
Brings `v3` up to `origin/main`. Three of main's fifteen commits carry
anything new: the 2.22.0 release and its `cli-releases` artifacts, and
the changelog-rollup fix in `prepare-cli-release.yml`. The other twelve
were already ported to `v3` in adapted form — the lock `graph`, hash
carry-over and cache resilience via
[#717](#717), `--check-deploy`
via [#703](#703), the
`decompress` removal and launcher pin via
[#702](#702), the self-update
major guard via [#697](#697),
the 2.21.0 release via
[#707](#707).

So every source conflict resolves to v3's version, and the net diff is
ten files.

## Why 28 files conflicted for a 15-commit sync

Every previous sync (`24793648`, `9d086b9b`, `eb5c1232`) was
squash-merged, which discards the ancestry link. Git's merge base is
consequently still `0e91af70` (#550), so each sync re-resolves
everything both branches have touched since — not what actually changed
since the last sync.

**Merging this with a merge commit rather than a squash would stop
that.** The next sync would then only have to resolve real divergence.

## Conflicts that needed a decision

Each main-only hunk was checked against v3 rather than blanket-resolved:

- `sync-local-cache.ts` — main's "restore a package missing from the
global cache" fix is already at `sync-local-cache.ts:55`.
- `build.test.ts` — main's `--check-deploy` / `--check-wasm` tests moved
to `build-check-deploy.test.ts` and `build-check-wasm.test.ts` when
[#731](#731) split the file.
- `build.ts` — main gained a guard requiring an explicit `[toolchain]
pocket-ic` pin plus a dfinity-client compatibility assert. Neither
applies here: v3 dropped the legacy client and defaults `pocket-ic` to
14.0.0.
- `10-mops.lock.md` — main's two new `graph` paragraphs exist on v3,
adapted to a model with no `--lock update`.
- `CHANGELOG.md` — main's `2.22.0` section is spliced in above `2.21.0`;
v3's `Next` and `3.0.0 (unreleased)` blocks already document the same
work and are untouched.
- Auto-merge quietly added two obsolete `check-deploy` snapshots to
`build.test.ts.snap`, where v3 no longer runs those tests. Reverted.

`vessel.ts` stays deleted, and `moc-wrapper`, `dhall-to-json-cli`,
`pic-ic`, the dfx fallback and `--lock <mode>` stay gone.

## One behavior-adjacent change

`docs/docusaurus.config.js` claimed the docs canister is shared and
"whichever branch deployed most recently decides the layout".
[#709](#709) stopped `main`
deploying docs, so `v3` is now the sole deployer:

```js
// This branch is the only one that deploys the docs canister, so
// this config decides what docs.mops.one serves. `main` keeps a
// matching copy, but there it only shapes local previews.
```

The `release.yml` docs-deploy step is kept on this branch for the same
reason — main's replacement comment explaining its absence does not
apply here.

## What is unchanged

No CLI behavior changes. The version bump to 2.22.0 is not asserted
anywhere in the tests, and `cli-releases` artifacts are 2.x release
history: `releases.json`, `tags/latest`, and `2.tgz` / `latest.tgz` all
agree with `2.22.0.tgz` and its recorded sha256.

`npm run check` is clean and the CLI suite passes 494 tests across 59
suites. `npm run lint` fails at the repo root only because
`cli-releases/frontend` has no `node_modules` in a fresh worktree, so
eslint cannot resolve `eslint-plugin-svelte` — pre-existing and
unrelated; `npx eslint cli` is clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Michael Morandi <michael.morandi@caffeine.ai>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: caffeine-ci-bot[bot] <249119985+caffeine-ci-bot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

2 participants