Skip to content

feat(cli): Back up the database on upgrade and add cli upgrade undo - #1631

Merged
BYK merged 10 commits into
mainfrom
feat/cli-upgrade-undo
Oct 27, 2026
Merged

BYK merged 10 commits into
mainfrom
feat/cli-upgrade-undo

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1623. Builds on #1612 (merged), using its hook that runs after the new binary is downloaded and before it runs cli setup.

sentry cli upgrade now copies cli.db to backups/cli-<from>_to_<to>.db under the config directory before another version runs setup. The file name is the record: the newest backup is the last upgrade, so there is no separate manifest. sentry cli upgrade undo reinstalls <from> and puts its own database back. This is the backup-and-restore approach BYK suggested on #1612, so newer CLIs don't need to rewrite their schema for older ones.

Following BYK's answers on #1623:

  • Logins (merge when possible, warn at least): the restored database gets the current accounts rows, so logins and refreshed tokens made since the backup are kept. Accounts removed since then (logged out) stay removed. When the backup has no accounts table (before schema v18), or the rows can't be copied, the result warns that the user may need to sentry auth login. The result also warns that other changes since the backup, like defaults, are undone.
  • Retention (one per version): a version's backup replaces its earlier one. I also capped them at the five most recent, because nightly users would otherwise collect one per nightly. The backup an undo would restore is the newest, so it is never pruned.
  • Other install methods: undo only covers version changes made by sentry cli upgrade and says so. Downgrades through npm or Homebrew still rely on fix(cli): Keep the local database usable across CLI downgrades #1612's newer-database detection. On a Homebrew install, which can't install an earlier version, undo points to sentry cli upgrade undo --method curl.
  • Secrets: backups are 0600 in a 0700 directory, like cli.db.

How it works

  • The backup runs only after the download succeeds and before any CLI crashes with "ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint" after switching from nightly back to stable #1611 hand-off, so a failed download changes nothing and the backup keeps the logins. Reinstalling the same version doesn't back up, so it can't overwrite the record of the upgrade that led there.
  • Backups use VACUUM INTO, which takes a consistent copy while other CLI processes use the database. File operations use node:fs/promises.
  • Undo finds its backup by scanning backups/: the newest file by mtime is the last upgrade, and it only counts if <to> is the running version. _ isn't valid in semver, so it separates the two versions unambiguously.
  • Undo installs the earlier version on its own channel and doesn't save a channel change to the current database, because the restored database already has its own.
  • Undo also backs up the current database first, so an undo can be undone.
  • The restore checkpoints the WAL and closes cli.db, then swaps in the copy. For the rest of the run, the upgrading CLI uses a throwaway in-memory database (detachDatabase), so it can't migrate the restored file forward again. If the swap fails, the current database is left in place and the CLI crashes with "ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint" after switching from nightly back to stable #1611 hand-off runs as it would without undo.
  • Undo fails with a clear message when there is no backup, or the newest backup wasn't made upgrading to this version.

Limitation: a backup only exists once the version doing the upgrade includes this change, so undo can't return to 0.47.0 or other older releases.

Tests: test/lib/db/backup.test.ts covers backup naming and pruning, the undo checks, restoring with logins kept, older-format backups, and that the restored file isn't touched afterwards, with a full round trip on both the node:sqlite and WASM drivers. upgrade.test.ts derives its versions from CLI_VERSION with semver and covers the backup existing before setup runs, a full cli upgrade undo, undo refusing when the last upgrade went to another version, the Homebrew message, and the nothing-to-undo error.

via BYK.

--

View Junior Session [Sentry]

@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
sentry-local Skipped Skipped Oct 27, 2026 10:02pm UTC

Request Review

@github-actions github-actions Bot added the risk: medium PR risk score: medium label Oct 23, 2026

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread packages/cli/src/lib/db/backup.ts
Comment thread packages/cli/src/commands/cli/upgrade.ts
Comment thread packages/cli/test/commands/cli/upgrade.test.ts Outdated
Comment thread packages/cli/src/commands/cli/upgrade.ts Outdated
Comment thread packages/cli/src/commands/cli/upgrade.ts Outdated
Comment thread packages/cli/src/lib/db/backup.ts Outdated
Comment thread packages/cli/src/lib/db/backup.ts Outdated
@sentry-junior
sentry-junior Bot force-pushed the fix/cli-db-newer-schema-downgrade branch from 488037c to d814a7d Compare October 27, 2026 17:20
@sentry-junior
sentry-junior Bot force-pushed the feat/cli-upgrade-undo branch from a97653a to db9651d Compare October 27, 2026 17:34
Base automatically changed from fix/cli-db-newer-schema-downgrade to main October 27, 2026 17:37
sentry-junior Bot and others added 3 commits October 27, 2026 19:25
Before `sentry cli upgrade` hands the local database to another version,
it now copies `cli.db` to `backups/cli-<version>.db` under the config
directory and records which version it moved from.
`sentry cli upgrade undo` reinstalls that version and puts its own
database back, so newer CLIs don't need to rewrite their schema for
older ones.

- The restored database keeps the current logins when the older
  version stores them in `accounts`; otherwise the command warns that
  the user may need to log in again.
- One backup per version, at most five, never pruning the one an undo
  would restore. Backups are 0600 in a 0700 directory, like `cli.db`.
- The upgrading process detaches from `cli.db` after restoring it, so
  it can't migrate the older version's database again.

Closes #1623.

Co-Authored-By: BYK <burak.kaya@sentry.io>
- Restoring a backup after logging out of every account brought the
  backup's logins back. The restored database now ends up with no
  accounts (or an empty pre-v18 `auth` row) in that case.
- `sentry cli upgrade undo` on a Homebrew install failed with the
  generic "Homebrew does not support installing a specific version"
  error. It now says undo can't go through Homebrew and points to
  `sentry cli upgrade undo --method curl`.
- Commit the regenerated skill reference for the docs fragment change.

Co-Authored-By: BYK <burak.kaya@sentry.io>
Each backup is now cli-<from>_to_<to>.db and the newest one is the last
upgrade, so undo reads the backup directory instead of a manifest.
Backup and restore use async fs calls, the undo argument constant is
MAGIC_VERSION_FOR_UNDO, and the upgrade tests derive their versions from
CLI_VERSION with semver.

Co-Authored-By: BYK <burak.kaya@sentry.io>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread packages/cli/src/commands/cli/upgrade.ts
The new binary installs itself during setup, so a failed setup leaves
this version installed. The backup made for that upgrade then hid the
earlier one from undo, and a failed undo left the older version's
database in place. Both are now reverted, and this process uses its
own database again.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread packages/cli/src/commands/cli/upgrade.ts
Comment thread packages/cli/src/commands/cli/upgrade.ts
A #1611 hand-off is redone after a failed setup, so reinstating this
version's database first had it wiped, and discarding the backup threw
away the only intact copy. A failed setup that needed the hand-off now
keeps the backup and leaves a restored database in place.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread packages/cli/src/commands/cli/upgrade.ts Outdated
…nd-off

A restore makes the #1611 hand-off unnecessary, so a failed undo to a
CLI below 0.48.0 can put this version's database back and skip the
hand-off like any other failed undo.

@BYK BYK left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What about that Warden issue raised?

Comment thread packages/cli/src/lib/db/backup.ts Outdated
Comment thread packages/cli/src/lib/db/backup.ts Outdated
Warden: a failed curl downgrade to a pre-0.48 CLI kept the handed-off
database, with its logins deleted, while this version stayed installed.
The backup is now moved back into place and the hand-off isn't redone.
Without a backup, the hand-off is still redone as before.

listBackups also scans the directory with opendir, per review.
@sentry-junior

sentry-junior Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor Author

@BYK On the Warden finding (a failed curl downgrade to a pre-0.48 CLI kept the handed-off cli.db, with its logins deleted, while this version stayed installed): fixed in 07cb5e6. When a --install setup fails, the backup taken just before it is moved back into place, and the hand-off isn't redone. The #1612 redo after a failed setup still runs when there is no backup to put back.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 07cb5e6. Configure here.

Comment thread packages/cli/src/lib/db/backup.ts Outdated
Some filesystems (NFS, some FUSE and bind mounts) don't report a type on
directory entries, so Dirent.isFile() skipped real backups. Match the
name first, then use the stat result to check the type.
Comment thread packages/cli/src/commands/cli/upgrade.ts
Comment thread packages/cli/src/commands/cli/upgrade.ts
Comment thread packages/cli/src/lib/db/backup.ts
Comment thread packages/cli/src/lib/db/backup.ts Outdated
…his database

Undo passed the target's artifact channel to setup, which records it and
overwrote the release channel stored in the restored database. Setup now
gets no --channel for an undo.

An undo that installs the binary through setup now stops when this
version's database can't be backed up: a failed setup could otherwise not
put it back, leaving this version with the restored database.
@BYK
BYK enabled auto-merge (squash) October 27, 2026 22:03
@BYK
BYK merged commit 0315e47 into main Oct 27, 2026
22 checks passed
@BYK
BYK deleted the feat/cli-upgrade-undo branch October 27, 2026 22:14

This branch was previously deployed

1 inactive deployment
Preview — e4586e58 Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: medium PR risk score: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI: back up cli.db on upgrade and add a command to undo an upgrade

1 participant