Files
VoiceStudio/docs/update-channels.md
T
16294fed44 feat(updates): data-safe updates — pre-migration DB backups, guarded venv heal, release notes + changelog reader (#909)
Backend:
- core/db_backup.py: WAL-safe SQLite snapshot to omnivoice.db.backup-<version>-<n>
  before pending alembic migrations run; keep newest 3, prune older; skip >500MB
  with a log line. Restore is never automatic.
- core/db.py: _run_alembic_upgrade now plans the run (up_to_date / pending /
  unknown_revision), snapshots first when migrations will execute, and raises
  MigrationError on a mid-flight failure — startup stops with the backup path
  named instead of continuing on a half-migrated DB. The #552/#547
  unknown-revision class stays non-fatal (warn + additive reconcile).
- core/changelog.py + GET /api/settings/changelog: parse the shipped
  CHANGELOG.md (single-line and wrapped bullet styles) into structured releases.
- GET /api/settings/db-backup: newest pre-migration backup for the panel.

Rust (bootstrap.rs):
- #314 heal guard: an exit-signature match alone can no longer delete the venv —
  venv_rebuild_justified requires a structural problem or a failed direct
  interpreter probe; a venv that probes healthy is kept and the real error
  surfaced. Drift/repair remains in-place `uv sync` (non-destructive).
- CHANGELOG.md now ships as a bundle resource and is copied/refreshed into the
  project dir so the changelog endpoint works in packaged installs.

Frontend (Settings → Updates):
- Available update shows its actual release notes (updater metadata body)
  through a safe markdown-lite renderer (text nodes only, refs stay plain).
- "Your data is backed up before every update" line with the latest backup
  timestamp from the new endpoint.
- "What's new" changelog reader (accordion, newest expanded) over the shipped
  CHANGELOG.md; GitHub releases list reuses the same renderer.
- One-time, non-blocking "What's new" footer pill after an update
  (persisted last-seen version; fresh installs baseline silently).
- All strings via t() with en keys (other locales fall back to English).

Tests: db backup/rotation/failure-path units, migration-safety units, changelog
parser (both bullet styles + real CHANGELOG.md), endpoint tests, route
inventory regenerated, Rust decision-logic + probe tests, vitest suites for
renderer/viewer/panel/pill logic.

Co-authored-by: mergetest <test@local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:52:17 +05:30

3.9 KiB

Update channels (Stable / Preview)

OmniVoice Studio auto-updates itself in the background. You choose which builds it offers you with the update channel in Settings → Updates → Update channel.

Channel What you get Who it's for
Stable (default) The latest tagged vX.Y.Z release. Everyone. This is the default on every install and every launch.
Preview The latest main build (a rolling preview prerelease). Newer features, less testing. Falls back to a stable release if one is ahead. Users who want to try fixes/features before they're tagged, and report issues.

Switching is instant — the next update check (on launch, or via Check for updates) uses your chosen channel. Your projects, voices, settings, and any in-flight job are untouched; an in-progress dub blocks the install until it finishes, and your data lives outside the app bundle, so an update never touches it.

There are no accounts, no telemetry, and no extra network calls — both channels just point the existing signed updater at a different GitHub Releases manifest:

  • Stable → releases/latest/download/latest.json
  • Preview → releases/download/preview/latest.json

Both manifests are signed with the same minisign key, so a tampered build is rejected regardless of channel.

Your data during updates

Your voices, projects, history, and settings live in a SQLite database (omnivoice.db) outside the app bundle, so replacing the app never touches them. On the first launch of an updated build, if the new version needs a database schema upgrade, OmniVoice:

  1. Backs up the database first — a consistent snapshot is written next to it as omnivoice.db.backup-<version>-<n> before any migration runs. The newest 3 backups are kept; older ones are pruned automatically. (Databases over 500 MB skip the snapshot, with a log line saying so.)
  2. Stops instead of guessing — if a migration fails midway, the app does not start on a half-migrated database and does not silently restore anything. It shows an error naming the backup path so you (or a support thread) decide: retry, report the issue, or roll back by replacing omnivoice.db with the backup.

Settings → Updates shows the timestamp of the latest backup, the release notes of any available update, and a What's new reader for the shipped changelog — all local, no extra network calls.

The Python environment (.venv) is also updated non-destructively: dependency drift after an app update is reconciled in place with uv sync, and a failed sync keeps the previous environment working. The venv is only ever rebuilt when its interpreter is confirmed broken (structural check + a direct probe) or when you explicitly use Clean & Retry.

For maintainers — how previews are built

Preview builds come from main, two ways:

  • Nightly (automatic). A scheduled job (07:00 UTC) rebuilds the rolling preview prerelease from main — but only when main actually moved in the last day, so idle days cost nothing. Preview is never more than ~24h behind main.
  • On demand. Actions → Desktop Release → Run workflow, pick a branch (usually main), set publish_preview = true. Useful to cut a preview off a feature branch, or to refresh immediately without waiting for the nightly.

Either way it builds the matrix and publishes/updates a single rolling preview prerelease — always flagged prerelease, and carrying the same platform set as stable (both verified in CI after each preview publish) — with its own signed latest.json. The tagged latest stable release is never affected. Preview users get the new build on their next check; stable users see nothing.

To stop offering previews, delete the preview release/tag on GitHub — the Preview channel then falls back to stable.