Repository navigation
fix(cli): Keep the local database usable across CLI downgrades - #1612
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit dd06635. Configure here.
BYK
left a comment
There was a problem hiding this comment.
A cheaper alternative rather than trying to revert the db from code can be backing up the db along with the version the user is coming from and introducing a sentry cli revert or sentry cli upgrade undo or something like that which restores the previous db and database. This can be tracked in a separate issue while we do the resilience patches in this PR.
Switching from nightly back to stable left cli.db at a newer schema. The older CLI only migrates forward, so its org_regions upsert failed against the newer composite key and its login lookup found an empty auth table. - Before `cli upgrade` installs an older version, drop cache tables, copy the active account into the legacy auth/user_info tables, and set the schema version to 16 so the newer CLI re-migrates when it comes back. - Make the v18 accounts migration refresh an existing account instead of adding a duplicate when it re-runs. - When a newer CLI wrote the database, rebuild cache tables and record this version, or report it in `cli fix` when auto-repair is disabled. - Compare every table's primary key during repair, not only composite keys, and never drop a table whose data cannot be rebuilt. Fixes #1611
Another invocation of the newer CLI during the download re-migrates the database and undoes the hand-off, so `cli upgrade` now runs it again after installing. It skips a database already at schema 16, which keeps any login the older CLI wrote. When the older CLI logged out, `auth` comes back empty. The v18 migration now drops the handed-down active account instead of logging back in.
The post-install pass treated any version above 16 as a re-migration by the newer CLI, so it also undid forward migrations the older CLI's own `cli setup` ran. Only this CLI migrates to its own version, so skip everything below it.
Per review: rather than keep the pre-v18 `auth`/`user_info` schema in newer CLIs just for downgrades, the hand-off now clears stored accounts and the user logs in again in the older CLI. Coming back up, the v18 migration folds any login made there into `accounts` as before, so the token-matching and logout handling it gained in this PR are reverted. The hand-off only runs when the target predates 0.48.0, the first release that adapts a newer CLI's database itself.
Running the downgrade hand-off before the download meant a failed download left the current CLI logged out. It now runs right before the older binary's `cli setup`, and again in a `finally` after it, so a setup failure still redoes it if another invocation re-migrated the database in the meantime.
Tables now count as caches unless they set persistent: true, so only logins, settings, and other data the CLI cannot fetch again need a flag. A test lists the cache tables so adding a table is a deliberate choice.
488037c to
d814a7d
Compare
…#1631) 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](#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 #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 #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 #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. <!-- junior-request-attribution:start --> via **BYK**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC010884QHLG%3A1792748852.474329 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC010884QHLG%3A1792748852.474329) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC010884QHLG%3A1792748852.474329/?project=4510944073809921) <!-- junior-session-footer:end --> --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: BYK <burak.kaya@sentry.io>

Fixes #1611.
Running nightly migrates
cli.dbto schema 19. Going back to stable 0.47.0 (schema 16) then breaks in two ways, because older CLIs only migrate forward:org_regionskeeps the v17 composite key, so 0.47'sON CONFLICT(org_slug)upsert fails with "ON CONFLICT clause does not match…". Its auto-repair only checks composite keys, so it never fixes this.authintoaccounts. 0.47 recreates an emptyauthtable on startup, so the user is logged out without being told.0.47.0 has already shipped, so the fix has to come from the newer CLI, which is the one running
sentry cli upgrade stable:cli upgradetargets a release below0.48.0, the first release that adapts a newer database by itself, it hands the database to the older CLI. It drops the cache tables (the older CLI recreates them in its own shape), deletes the stored accounts, and sets the schema version to 16. The older CLI can't readaccounts, so the user runssentry auth loginthere. This is simpler than keeping the old login format alive in newer CLIs.cli setup. A failed download leaves the database and login untouched. It runs again after setup, even if setup fails, in case another invocation of the newer CLI re-migrated the database meanwhile. That second run does nothing unless the version is the running CLI's own, so it can't undo migrations the older CLI ran itself.accounts.SENTRY_CLI_NO_AUTO_REPAIR=1,sentry cli fixreports the mismatch instead (CLI crashes with "ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint" after switching from nightly back to stable #1611 noted it used to print the binary's version and "No issues found").pragma_table_info, not just composite keys. Tables are markedrebuildablewhen they only hold derived data. Only those get dropped and recreated; a wrong key on any other table is reported and left alone.Every migration after v16 now has to be safe to re-run. This is documented on
prepareDatabaseForDowngrade.The
0.48.0threshold assumes this PR lands before 0.48.0 is released.Backing up
cli.dbon upgrade and adding an undo command, which would keep the login across a downgrade, is tracked in #1623.via BYK.
--
View Junior Session [Sentry]