Skip to content

feat: in-app auto-update via tauri-plugin-updater + signing pipeline#2

Merged
hujiulin merged 5 commits into
mainfrom
feat/auto-update
Jun 7, 2026
Merged

feat: in-app auto-update via tauri-plugin-updater + signing pipeline#2
hujiulin merged 5 commits into
mainfrom
feat/auto-update

Conversation

@hujiulin

@hujiulin hujiulin commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

Add a full version-detection + auto-update flow so users get new releases without ever leaving the app.


What's in this PR

🔌 Client side

  • Plugins: tauri-plugin-updater + tauri-plugin-process (for relaunch) registered in main.rs; capabilities/default.json grants updater:* + process:allow-restart
  • tauri.conf.json: bundle.createUpdaterArtifacts: true + plugins.updater section pointing at the GitHub Releases latest.json endpoint (pubkey left blank for maintainers to fill — see README)
  • src/updater.ts: friendly wrapper around check / downloadAndInstall / relaunch. Silent-by-default so a startup auto-check stays quiet, but re-throws when called explicitly so the UI can surface errors
  • Store updater slice (store.ts): updateStatus (idle / checking / upToDate / available / downloading / installed / error), latestUpdate, updateProgress, updateError, lastUpdateCheck. Actions: checkForUpdate({silent}), installUpdate(), restartForUpdate(), dismissUpdate(). Auto-runs a silent check 3 s after init

🎨 UI

  • AboutPanel.tsx has a new <UpdaterCard> with five visual states:
    • idle / upToDate / checking — version + "Last checked X ago" + Check button
    • available — title + release notes (scrollable) + Install update / Not now
    • downloading — progress bar with KB/MB readout
    • installed — ✓ "Update installed" + Restart now
    • error — ⚠ message + Try again
  • Subtle green dot on Sidebar's Settings nav item + on Settings' About sub-tab whenever an update is available

🚀 CI / CD

  • .github/workflows/release.yml wires TAURI_SIGNING_PRIVATE_KEY + TAURI_SIGNING_PRIVATE_KEY_PASSWORD env so the bundler signs each updater artifact, and includeUpdaterJson: true emits the latest.json manifest alongside the installers

🧪 Tests (+23 / total 279 across 32 files)

  • tests/__mocks__/tauri-updater.ts — in-memory updater plugin with hooks for next update / next error / chunk sizes / download fail
  • tests/__mocks__/tauri-process.tsrelaunch spy
  • tests/updater.test.ts — wrapper silent vs non-silent, progress streaming, download errors
  • tests/store.updater.test.ts — every status transition + error paths + dismiss
  • tests/components/AboutPanel.test.tsx — identity + every updater UI state (idle / available / installed / error)

📝 Docs

  • Both READMEs gain a new Auto-update setup (maintainers) section walking through the 4-step signing onboarding (generate keypair → embed pubkey → add GH secrets → push tag)
  • Feature table picks up a 🔄 Auto-update row

Test plan

  • npm test green (279/279)
  • npm run vite:build passes
  • cargo build passes
  • CI workflow runs on this PR (see status checks above)
  • Manual smoke: npm run dev → Settings → About → click "Check for updates" (will show an error until latest.json exists, which is expected)
  • After maintainer adds TAURI_SIGNING_PRIVATE_KEY secret and tags a release: verify latest.json shows up in Releases and the in-app updater flow works end-to-end

How users will experience this

  1. Launch EchoWise → 3 s later a silent background check runs
  2. If a new version exists → a green dot appears next to Settings in the sidebar
  3. Open Settings → About → see "Update available — vX.Y.Z" with release notes
  4. Click Install update → progress bar → ✓ Installed
  5. Click Restart now → app relaunches into the new version

George Hu and others added 5 commits June 7, 2026 21:26
Add a full version-detection + auto-update flow so users get new releases
without ever leaving the app.

Client side
- tauri-plugin-updater + tauri-plugin-process registered in main.rs;
  capabilities/default.json grants updater + process:allow-restart
- tauri.conf.json: bundle.createUpdaterArtifacts=true and plugins.updater
  with GitHub Releases endpoint (pubkey left blank for maintainers to fill)
- src/updater.ts: friendly wrapper around check / downloadAndInstall /
  relaunch; silent-by-default so a startup auto-check stays quiet, but
  re-throws when called explicitly so the UI can show errors
- store.ts: new updater slice (status / latestUpdate / progress / error /
  lastUpdateCheck) + actions (checkForUpdate / installUpdate /
  restartForUpdate / dismissUpdate); auto-runs a silent check 3s after init
- AboutPanel: new UpdaterCard with five visual states — idle / checking,
  available (with release notes + Install / Not now), downloading (with
  KB/MB progress bar), installed (with Restart now), error (with retry)
- Sidebar and Settings sub-nav both show a green dot on Settings/About
  when an update is available

CI / CD
- release.yml: wires TAURI_SIGNING_PRIVATE_KEY +
  TAURI_SIGNING_PRIVATE_KEY_PASSWORD env so the bundler signs each
  updater artifact and includeUpdaterJson emits the latest.json manifest
  alongside installers

Tests (+23, total 279/32 files)
- tests/__mocks__/tauri-updater.ts: in-memory updater plugin with hooks
  for next-update / next-error / chunk-sizes / download-fail
- tests/__mocks__/tauri-process.ts: relaunch spy
- tests/updater.test.ts: wrapper silent vs non-silent, progress streaming
- tests/store.updater.test.ts: every status transition + error paths
- tests/components/AboutPanel.test.tsx: identity + all updater UI states

Docs
- README.md and README.zh.md: new "Auto-update setup (maintainers)" /
  "自动更新设置(维护者)" section with the 4-step signing onboarding;
  feature table picks up a 🔄 Auto-update row

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
…rives

Two UX glitches around the "EchoWise is thinking…" state:

1. Two thinking indicators were rendered at once — a line above the
   composer ("EchoWise is thinking…") and the composer ThinkingBar
   itself. Replace the message-stream copy with an iMessage-style
   TypingIndicator (avatar + three pulsing dots) that only shows while
   the AI hasn't replied yet (i.e. the last turn is still the user's).
   Removes the duplicate language and avoids the awkward "AI thinks
   again" pulse after the reply already appeared.

2. After the AI's text bubble shows up, the composer stayed stuck on
   "EchoWise is thinking…" for several seconds while TTS synthesized
   and saved audio. Run the TTS chain in the background (fire-and-
   forget) so setBusy(false) fires the moment the reply lands; audio
   still streams in once ready and the bubble's play button works.

ThinkingBar copy keeps the companion name ("EchoWise is thinking…") per
user preference; the leading three-dot icon was dropped to clean up the
pill visually.

Also remove Release flow / Roadmap / Contributing sections from both
READMEs per request to keep the public landing page focused.

Test updates:
- Replace the old "is thinking" text assertion with the new
  "EchoWise is thinking…" pill + aria-label="thinking" lookup.

279/279 tests pass.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
A 36-second GIF showing the core conversation loop (record / transcribe /
AI reply / scoring chip). Replaces the "Screenshots coming soon"
placeholder in both READMEs.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
The recording covers the full walk-through (talk + scoring + growth +
settings), not just the talking flow. `demo.gif` is the convention used
by most open-source projects (VS Code, Linear, shadcn-ui) and reads as
"the canonical visual" without an arbitrary numeric prefix.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
@hujiulin
hujiulin merged commit e42c506 into main Jun 7, 2026
1 check passed
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.

1 participant