feat(updater): add tauri-plugin-updater backend integration

Adds tauri-plugin-updater and tauri-plugin-process crates, the updater
config block in tauri.conf.json (with PLACEHOLDER_PUBLIC_KEY to be
replaced before release), capabilities for updater/process, and the
v2_is_auto_update_eligible command that returns true on macOS and
Linux AppImage installs only.

Cherry-picked from #305 by @afonsojramos.

cc
This commit is contained in:
vicrodh committed 2026-04-13 14:53:08 -06:00
1 parent 6c66961ca2
commit 96cfb93956
7 files changed
+221 -1

No files matched your search

+171
View File
@@ -166,6 +166,15 @@ version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arbitrary"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "arboard"
version = "3.6.1"
@@ -1379,6 +1388,17 @@ dependencies = [
"serde_core",
]
[[package]]
name = "derive_arbitrary"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "derive_more"
version = "0.99.20"
@@ -3416,6 +3436,12 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "minisign-verify"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22f9645cb765ea72b8111f36c522475d2daa0d22c957a9826437e97534bc4e9e"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
@@ -3923,6 +3949,18 @@ dependencies = [
"objc2-core-foundation",
]
[[package]]
name = "objc2-osa-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f112d1746737b0da274ef79a23aac283376f335f4095a083a267a082f21db0c0"
dependencies = [
"bitflags 2.11.0",
"objc2",
"objc2-app-kit",
"objc2-foundation",
]
[[package]]
name = "objc2-quartz-core"
version = "0.3.2"
@@ -4124,6 +4162,20 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "osakit"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b"
dependencies = [
"objc2",
"objc2-foundation",
"objc2-osa-kit",
"serde",
"serde_json",
"thiserror 2.0.18",
]
[[package]]
name = "pango"
version = "0.18.3"
@@ -4899,7 +4951,9 @@ dependencies = [
"tauri-plugin-dialog",
"tauri-plugin-opener",
"tauri-plugin-os",
"tauri-plugin-process",
"tauri-plugin-single-instance",
"tauri-plugin-updater",
"tempfile",
"thiserror 2.0.18",
"tokio",
@@ -5416,15 +5470,20 @@ dependencies = [
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-util",
"js-sys",
"log",
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier",
"serde",
"serde_json",
"sync_wrapper",
"tokio",
"tokio-rustls",
"tokio-util",
"tower",
"tower-http 0.6.8",
@@ -5665,6 +5724,33 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rustls-platform-verifier"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
"jni",
"log",
"once_cell",
"rustls",
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
"security-framework",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
]
[[package]]
name = "rustls-platform-verifier-android"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
version = "0.103.10"
@@ -6578,6 +6664,17 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "tar"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
@@ -6834,6 +6931,16 @@ dependencies = [
"thiserror 2.0.18",
]
[[package]]
name = "tauri-plugin-process"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d55511a7bf6cd70c8767b02c97bf8134fa434daf3926cfc1be0a0f94132d165a"
dependencies = [
"tauri",
"tauri-plugin",
]
[[package]]
name = "tauri-plugin-single-instance"
version = "2.4.0"
@@ -6850,6 +6957,39 @@ dependencies = [
"zbus 5.14.0",
]
[[package]]
name = "tauri-plugin-updater"
version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "806d9dac662c2e4594ff03c647a552f2c9bd544e7d0f683ec58f872f952ce4af"
dependencies = [
"base64 0.22.1",
"dirs",
"flate2",
"futures-util",
"http",
"infer",
"log",
"minisign-verify",
"osakit",
"percent-encoding",
"reqwest 0.13.2",
"rustls",
"semver",
"serde",
"serde_json",
"tar",
"tauri",
"tauri-plugin",
"tempfile",
"thiserror 2.0.18",
"time",
"tokio",
"url",
"windows-sys 0.60.2",
"zip",
]
[[package]]
name = "tauri-runtime"
version = "2.10.1"
@@ -8006,6 +8146,15 @@ dependencies = [
"system-deps",
]
[[package]]
name = "webpki-root-certs"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "webpki-roots"
version = "0.26.11"
@@ -8899,6 +9048,16 @@ dependencies = [
"time",
]
[[package]]
name = "xattr"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
dependencies = [
"libc",
"rustix 1.1.4",
]
[[package]]
name = "xdg-home"
version = "1.3.0"
@@ -9170,6 +9329,18 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "zip"
version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1"
dependencies = [
"arbitrary",
"crc32fast",
"indexmap 2.13.0",
"memchr",
]
[[package]]
name = "zmij"
version = "1.0.21"
+2
View File
@@ -39,6 +39,8 @@ tauri-plugin-opener = "2"
tauri-plugin-os = "2"
tauri-plugin-single-instance = { version = "2", features = ["deep-link"] }
tauri-plugin-deep-link = "2"
tauri-plugin-updater = "2"
tauri-plugin-process = "2"
# Serialization
serde = { version = "1", features = ["derive"] }
+3 -1
View File
@@ -36,6 +36,8 @@
"os:default",
"dialog:default",
"clipboard-manager:default",
"clipboard-manager:allow-write-text"
"clipboard-manager:allow-write-text",
"updater:default",
"process:allow-restart"
]
}
@@ -1202,6 +1202,11 @@ pub fn v2_is_running_in_flatpak() -> bool {
crate::flatpak::is_running_in_flatpak()
}
#[tauri::command]
pub fn v2_is_auto_update_eligible() -> bool {
crate::updates::is_auto_update_eligible()
}
#[tauri::command]
pub fn v2_is_running_in_snap() -> bool {
crate::snap::is_running_in_snap()
+3
View File
@@ -751,6 +751,8 @@ pub fn run() {
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_process::init())
.manage(AppState::with_device_and_settings(
saved_device,
audio_settings,
@@ -1490,6 +1492,7 @@ pub fn run() {
commands_v2::v2_has_whats_new_been_shown,
commands_v2::v2_mark_whats_new_shown,
commands_v2::v2_mark_flatpak_welcome_shown,
commands_v2::v2_is_auto_update_eligible,
commands_v2::v2_get_backend_logs,
commands_v2::v2_upload_logs_to_paste,
commands_v2::v2_get_download_settings,
+30
View File
@@ -14,6 +14,9 @@ use std::path::Path;
use std::sync::{Arc, Mutex};
use std::time::Duration;
#[cfg(target_os = "linux")]
use std::env;
const GITHUB_RELEASES_URL: &str = "https://api.github.com/repos/vicrodh/qbz/releases";
const UPDATE_MIN_AGE_HOURS: i64 = 12;
const NETWORK_TIMEOUT_SECONDS: u64 = 4;
@@ -650,3 +653,30 @@ pub async fn fetch_release_for_version(
}
Ok(to_release_info(release))
}
/// Determine if the current install method supports in-app auto-updating.
///
/// Auto-update is supported for:
/// - macOS (always — updater uses .app.tar.gz bundles)
/// - Linux AppImage (detected via APPIMAGE env var)
///
/// Not supported for Flatpak, Snap, DEB, RPM, AUR, Gentoo (they have their own update channels).
pub fn is_auto_update_eligible() -> bool {
#[cfg(target_os = "macos")]
{
return true;
}
#[cfg(target_os = "linux")]
{
if crate::flatpak::is_flatpak() || crate::snap::is_snap() {
return false;
}
return env::var("APPIMAGE").is_ok();
}
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
{
false
}
}
+7
View File
@@ -36,11 +36,18 @@
"desktop": {
"schemes": ["qobuzapp"]
}
},
"updater": {
"endpoints": [
"https://github.com/vicrodh/qbz/releases/latest/download/latest.json"
],
"pubkey": "PLACEHOLDER_PUBLIC_KEY"
}
},
"bundle": {
"active": true,
"targets": "all",
"createUpdaterArtifacts": true,
"icon": [
"icons/32x32.png",
"icons/128x128.png",