diff --git a/.changes/updater-zip9.md b/.changes/updater-zip9.md new file mode 100644 index 0000000000..d199a8150a --- /dev/null +++ b/.changes/updater-zip9.md @@ -0,0 +1,5 @@ +--- +"updater": patch +--- + +Use patched ZIP extraction for Windows update archives. The plugin now requires Rust 1.88 to match the ZIP dependency. Keep update signature verification and the public updater API unchanged. diff --git a/.github/workflows/enrichlayer-updater-validation.yml b/.github/workflows/enrichlayer-updater-validation.yml new file mode 100644 index 0000000000..2a2fda0a54 --- /dev/null +++ b/.github/workflows/enrichlayer-updater-validation.yml @@ -0,0 +1,21 @@ +name: Enrich Layer updater compatibility +on: + push: + branches: [codex/DEV-13167-updater-zip9] + workflow_dispatch: +permissions: + contents: read +jobs: + updater: + strategy: + fail-fast: false + matrix: + os: [windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + timeout-minutes: 35 + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@1.95.0 + - uses: Swatinem/rust-cache@v2 + - run: cargo test -p tauri-plugin-updater --lib + - run: cargo tree -p tauri-plugin-updater diff --git a/plugins/updater/Cargo.toml b/plugins/updater/Cargo.toml index 3324825082..324243ee2c 100644 --- a/plugins/updater/Cargo.toml +++ b/plugins/updater/Cargo.toml @@ -5,7 +5,7 @@ description = "In-app updates for Tauri applications." edition = { workspace = true } authors = { workspace = true } license = { workspace = true } -rust-version = { workspace = true } +rust-version = "1.88" repository = { workspace = true } links = "tauri-plugin-updater" @@ -49,7 +49,7 @@ infer = "0.19" percent-encoding = "2.3" [target."cfg(target_os = \"windows\")".dependencies] -zip = { version = "4", default-features = false, optional = true } +zip = { version = "9.0.4", default-features = false, optional = true } windows-sys = { version = "0.60.0", features = [ "Win32_Foundation", "Win32_UI_WindowsAndMessaging", diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index 1425228744..2938189edc 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -1559,6 +1559,56 @@ fn escape_msi_property_arg(arg: impl AsRef) -> String { #[cfg(test)] mod tests { + #[test] + #[cfg(all(windows, feature = "zip"))] + fn zip_update_extracts_installer_with_patched_archive_reader() { + use super::*; + use std::io::Write; + + let update = Update { + run_on_main_thread: Arc::new(Box::new(|_| Ok(()))), + config: serde_json::from_value(serde_json::json!({ "pubkey": "test" })).unwrap(), + on_before_exit: None, + body: None, + current_version: "1.0.0".into(), + version: "1.0.1".into(), + date: None, + target: "windows-x86_64".into(), + download_url: Url::parse("https://example.invalid/update.zip").unwrap(), + signature: String::new(), + raw_json: serde_json::Value::Null, + timeout: None, + proxy: None, + no_proxy: true, + headers: HeaderMap::new(), + extract_path: PathBuf::new(), + app_name: "zip-compatibility-test".into(), + installer_args: Vec::new(), + current_exe_args: Vec::new(), + configure_client: None, + }; + let mut archive = zip::ZipWriter::new(Cursor::new(Vec::new())); + archive + .start_file( + "setup.exe", + zip::write::SimpleFileOptions::default() + .compression_method(zip::CompressionMethod::Stored), + ) + .unwrap(); + archive + .write_all(b"installer fixture; never executed") + .unwrap(); + let bytes = archive.finish().unwrap().into_inner(); + let installer = update.extract(&bytes).unwrap(); + let WindowsUpdaterType::Nsis { path, .. } = installer else { + panic!("expected the ZIP's NSIS installer"); + }; + assert_eq!( + std::fs::read(&path).unwrap(), + b"installer fixture; never executed" + ); + std::fs::remove_dir_all(path.parent().unwrap()).unwrap(); + } #[test] #[cfg(windows)]