feat(updater): auto-update via tauri-plugin-updater (based on #225) - #235
Conversation
Add an [updates] section to the user config (enabled by default). When an update is found, automatically download, install, and restart when enabled; otherwise fall back to the existing confirm dialog. Progress is logged in 10% buckets and a desktop notification is shown while updating. Also adds the updater:default capability required for handle.updater().
Add updater_ui.rs: a custom-protocol-served progress window (aw-update://) so IPC works during download (data: URLs break Origin checks). Wire it into the update-check flow in lib.rs with config-driven auto_download, a restart_app/close_update_progress command pair, and an AW_DISABLE_AUTO_UPDATE env var escape hatch mirroring gptme's pattern. Add the update-progress capability window and scoped permissions file, new assets/update-progress.html, and the tokio/log deps the progress window and env-gating need.
- Remove createUpdaterArtifacts from baseline config; CI adds it dynamically only when TAURI_SIGNING_PRIVATE_KEY is set (fail-open until Erik provisions the signing keypair) - Add conditional 'Configure updater artifacts' step to release.yml, matching build.yml; also make includeUpdaterJson conditional - Clear test pubkey (empty string placeholder until official key generated) - Fix updater endpoint from 0xbrayo fork to ActivityWatch/activitywatch - Add .envrc to .gitignore (local signing key helper, not for repo)
Greptile SummaryThe PR adds signed automatic updates and addresses the previously reported issues.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Sequence DiagramsequenceDiagram
participant App as ActivityWatch
participant Endpoint as Update endpoint
participant Window as Update progress window
participant User
App->>Endpoint: Check for update
Endpoint-->>App: Signed update metadata
App->>Window: Show download progress
App->>Endpoint: Download update
Endpoint-->>App: Update artifact
App->>App: Verify and install
App->>Window: Enable restart
User->>Window: Restart Now
Window->>App: restart_app
Reviews (2): Last reviewed commit: "fix(updater): address review findings" | Re-trigger Greptile |
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | ||
| with: |
There was a problem hiding this comment.
| @@ -913,7 +1177,12 @@ pub fn run() { | |||
| }; | |||
| }) | |||
There was a problem hiding this comment.
When the user dismisses the updater window, close_update_progress emits CloseRequested, but this unconditional handler prevents the close and hides the window instead, leaving the transient window allocated in Tauri's registry for the remainder of the process.
| .on_window_event(|window, event| { | |
| if window.label() == "main" { | |
| if let tauri::WindowEvent::CloseRequested { api, .. } = &event { | |
| api.prevent_close(); | |
| window.hide().expect("Failed to hide main window"); | |
| } | |
| } | |
| }) |
| "windows": [ | ||
| "main", | ||
| "module-alert" | ||
| "module-alert", | ||
| "update-progress" | ||
| ], | ||
| "permissions": [ | ||
| "core:default", | ||
| "shell:allow-open", | ||
| "dialog:default", | ||
| "opener:default" | ||
| "opener:default", | ||
| "updater:default", | ||
| "allow-restart-app", | ||
| "allow-close-update-progress", | ||
| "allow-open-external", | ||
| "allow-greet" |
There was a problem hiding this comment.
Updater privileges are overly broad
This shared capability grants updater, restart, shell, dialog, and opener operations to the localhost dashboard and module-alert windows even though the update-progress window is the only UI that needs restart access, unnecessarily increasing the impact of script execution in the dashboard.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
@greptileai review |
|
CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click. This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted. |
Summary
This PR builds directly on the excellent implementation in #225 by @0xbrayo. It adds
the auto-update feature using
tauri-plugin-updaterwith a proper fail-open CI gatingstrategy, cleaned of testing artifacts.
Greenlit in #68 by @ErikBjare. The companion CI PR for the
activitywatchrepo (which generateslatest.jsonon tag releases) isActivityWatch/activitywatch#1372.
What #225 contributes (kept as-is)
tauri-plugin-updaterintegration and Rust implementationupdater_ui.rs— progress window with download bar and restart buttonmanager.rs— config error surface (show dialog instead of restart loop)build.ymlandrelease.ymlWhat this PR adds on top
createUpdaterArtifactsfrom baseline config —build.ymladdsit dynamically only when
TAURI_SIGNING_PRIVATE_KEYis set, so CI doesn'tfail on unsigned builds (fail-open until Erik provisions the keypair)
release.yml— mirrorsbuild.ymlgating;
includeUpdaterJsonis also made conditional0xbrayo/activitywatchfork;now
ActivityWatch/activitywatch(matches whatactivitywatch#1372publishes)""until official key generated.envrcto.gitignore— local signing key helper, shouldn't be committedWhat's needed before updates work end-to-end
tauri signer generate -w ~/.tauri/aw-tauri.keyTAURI_SIGNING_PRIVATE_KEY(and optionallyTAURI_SIGNING_PRIVATE_KEY_PASSWORD)in the ActivityWatch GitHub org settings
pubkeyinsrc-tauri/tauri.conf.jsonwith thegenerated public key — at that point CI can be switched to fail-closed
Test plan
TAURI_SIGNING_PRIVATE_KEYset generate.sigfileslatest.jsonis published byactivitywatch#1372on tag releaseupdater_ui.rs