From 13365872e132ac8fe5531fa1698466109d5bee97 Mon Sep 17 00:00:00 2001 From: jLynx Date: Thu, 31 Oct 2024 09:31:21 +1300 Subject: [PATCH 1/8] Added deb to build --- .../src/bundle/updater_bundle.rs | 113 ++++++++++++++---- 1 file changed, 89 insertions(+), 24 deletions(-) diff --git a/crates/tauri-bundler/src/bundle/updater_bundle.rs b/crates/tauri-bundler/src/bundle/updater_bundle.rs index 77749afca21e..d08ccdb7876f 100644 --- a/crates/tauri-bundler/src/bundle/updater_bundle.rs +++ b/crates/tauri-bundler/src/bundle/updater_bundle.rs @@ -25,6 +25,7 @@ use std::{ use anyhow::Context; use zip::write::SimpleFileOptions; +use std::process::Command; // Build update pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result> { @@ -42,7 +43,7 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result< #[cfg(target_os = "macos")] return bundle_update_macos(bundles); #[cfg(target_os = "linux")] - return bundle_update_linux(bundles); + return bundle_update_linux(settings, bundles); #[cfg(not(any(target_os = "macos", target_os = "linux")))] { @@ -90,34 +91,98 @@ fn bundle_update_macos(bundles: &[Bundle]) -> crate::Result> { // Right now in linux we hot replace the bin and request a restart // No assets are replaced #[cfg(target_os = "linux")] -fn bundle_update_linux(bundles: &[Bundle]) -> crate::Result> { - use std::ffi::OsStr; +fn bundle_update_linux(settings: &Settings, bundles: &[Bundle]) -> crate::Result> { + use std::ffi::OsStr; - // build our app actually we support only appimage on linux - if let Some(source_path) = bundles - .iter() - .filter(|bundle| bundle.package_type == crate::PackageType::AppImage) - .find_map(|bundle| { - bundle - .bundle_paths + let mut update_artifacts = Vec::new(); + + // Handle AppImage updates + if let Some(source_path) = bundles .iter() - .find(|path| path.extension() == Some(OsStr::new("AppImage"))) - }) - { - // add .tar.gz to our path - let appimage_archived = format!("{}.tar.gz", source_path.display()); - let appimage_archived_path = PathBuf::from(&appimage_archived); + .filter(|bundle| bundle.package_type == crate::PackageType::AppImage) + .find_map(|bundle| { + bundle + .bundle_paths + .iter() + .find(|path| path.extension() == Some(OsStr::new("AppImage"))) + }) + { + // add .tar.gz to our path + let appimage_archived = format!("{}.tar.gz", source_path.display()); + let appimage_archived_path = PathBuf::from(&appimage_archived); + + // Create our gzip file + create_tar(source_path, &appimage_archived_path) + .with_context(|| "Failed to tar.gz update directory")?; + + log::info!(action = "Bundling"; "{} ({})", appimage_archived, display_path(&appimage_archived_path)); + + update_artifacts.push(appimage_archived_path); + } - // Create our gzip file - create_tar(source_path, &appimage_archived_path) - .with_context(|| "Failed to tar.gz update directory")?; + // Handle Deb package updates + if let Some(source_path) = bundles + .iter() + .filter(|bundle| bundle.package_type == crate::PackageType::Deb) + .find_map(|bundle| { + bundle + .bundle_paths + .iter() + .find(|path| path.extension() == Some(OsStr::new("deb"))) + }) + { + // For .deb packages, we don't need to archive them as they're already packaged + // We just need to sign them for the updater + + // Generate signature for the .deb package + let signature_path = sign_debian_package(source_path, settings) + .with_context(|| "Failed to sign Debian package")?; + + log::info!(action = "Signing"; "{} ({})", source_path.display(), display_path(&signature_path)); + + update_artifacts.push(source_path.to_path_buf()); + update_artifacts.push(signature_path); + } - log::info!(action = "Bundling"; "{} ({})", appimage_archived, display_path(&appimage_archived_path)); + if update_artifacts.is_empty() { + Err(crate::Error::UnableToFindProject) + } else { + Ok(update_artifacts) + } +} - Ok(vec![appimage_archived_path]) - } else { - Err(crate::Error::UnableToFindProject) - } +#[cfg(target_os = "linux")] +fn sign_debian_package(package_path: &Path, settings: &Settings) -> crate::Result { + use base64::{engine::general_purpose::STANDARD, Engine}; + use std::io::Read; + + // Read the package file + let mut package_contents = Vec::new(); + File::open(package_path)?.read_to_end(&mut package_contents)?; + + // Get the private key from settings + let private_key = settings + .private_key() + .ok_or_else(|| anyhow::anyhow!("Private key not found in settings"))?; + + // Create signature using minisign + let secret_key = minisign::SecretKey::from_base64(private_key) + .map_err(|e| anyhow::anyhow!("Invalid private key: {}", e))?; + + let signature = minisign::sign( + &secret_key, + &package_contents, + None, + None, + false, + ).map_err(|e| anyhow::anyhow!("Failed to create signature: {}", e))?; + + // Create signature file + let signature_path = package_path.with_extension("sig"); + let mut signature_file = File::create(&signature_path)?; + signature_file.write_all(STANDARD.encode(signature.to_string()).as_bytes())?; + + Ok(signature_path) } // Create simple update-win_.zip From 0aee430c4a42e4ab05b72b295864b511e973842f Mon Sep 17 00:00:00 2001 From: jLynx Date: Fri, 1 Nov 2024 11:20:58 +1300 Subject: [PATCH 2/8] Builds a deb updater too --- .../src/bundle/updater_bundle.rs | 73 +++++-------------- crates/tauri-cli/config.schema.json | 4 +- .../schemas/capability.schema.json | 4 +- .../schemas/config.schema.json | 4 +- 4 files changed, 25 insertions(+), 60 deletions(-) diff --git a/crates/tauri-bundler/src/bundle/updater_bundle.rs b/crates/tauri-bundler/src/bundle/updater_bundle.rs index d08ccdb7876f..96ae0809ea2e 100644 --- a/crates/tauri-bundler/src/bundle/updater_bundle.rs +++ b/crates/tauri-bundler/src/bundle/updater_bundle.rs @@ -25,7 +25,6 @@ use std::{ use anyhow::Context; use zip::write::SimpleFileOptions; -use std::process::Command; // Build update pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result> { @@ -43,7 +42,7 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result< #[cfg(target_os = "macos")] return bundle_update_macos(bundles); #[cfg(target_os = "linux")] - return bundle_update_linux(settings, bundles); + return bundle_update_linux(bundles); #[cfg(not(any(target_os = "macos", target_os = "linux")))] { @@ -91,12 +90,12 @@ fn bundle_update_macos(bundles: &[Bundle]) -> crate::Result> { // Right now in linux we hot replace the bin and request a restart // No assets are replaced #[cfg(target_os = "linux")] -fn bundle_update_linux(settings: &Settings, bundles: &[Bundle]) -> crate::Result> { +fn bundle_update_linux(bundles: &[Bundle]) -> crate::Result> { use std::ffi::OsStr; - let mut update_artifacts = Vec::new(); + let mut archived_paths = Vec::new(); - // Handle AppImage updates + // Handle AppImage bundles if let Some(source_path) = bundles .iter() .filter(|bundle| bundle.package_type == crate::PackageType::AppImage) @@ -111,16 +110,16 @@ fn bundle_update_linux(settings: &Settings, bundles: &[Bundle]) -> crate::Result let appimage_archived = format!("{}.tar.gz", source_path.display()); let appimage_archived_path = PathBuf::from(&appimage_archived); - // Create our gzip file + // Create our gzip file for AppImage create_tar(source_path, &appimage_archived_path) - .with_context(|| "Failed to tar.gz update directory")?; + .with_context(|| "Failed to tar.gz AppImage update directory")?; log::info!(action = "Bundling"; "{} ({})", appimage_archived, display_path(&appimage_archived_path)); - update_artifacts.push(appimage_archived_path); + archived_paths.push(appimage_archived_path); } - // Handle Deb package updates + // Handle Debian packages if let Some(source_path) = bundles .iter() .filter(|bundle| bundle.package_type == crate::PackageType::Deb) @@ -131,60 +130,26 @@ fn bundle_update_linux(settings: &Settings, bundles: &[Bundle]) -> crate::Result .find(|path| path.extension() == Some(OsStr::new("deb"))) }) { - // For .deb packages, we don't need to archive them as they're already packaged - // We just need to sign them for the updater - - // Generate signature for the .deb package - let signature_path = sign_debian_package(source_path, settings) - .with_context(|| "Failed to sign Debian package")?; + // add .tar.gz to our path + let deb_archived = format!("{}.tar.gz", source_path.display()); + let deb_archived_path = PathBuf::from(&deb_archived); + + // Create our gzip file for Deb + create_tar(source_path, &deb_archived_path) + .with_context(|| "Failed to tar.gz Debian package update directory")?; - log::info!(action = "Signing"; "{} ({})", source_path.display(), display_path(&signature_path)); + log::info!(action = "Bundling"; "{} ({})", deb_archived, display_path(&deb_archived_path)); - update_artifacts.push(source_path.to_path_buf()); - update_artifacts.push(signature_path); + archived_paths.push(deb_archived_path); } - if update_artifacts.is_empty() { + if archived_paths.is_empty() { Err(crate::Error::UnableToFindProject) } else { - Ok(update_artifacts) + Ok(archived_paths) } } -#[cfg(target_os = "linux")] -fn sign_debian_package(package_path: &Path, settings: &Settings) -> crate::Result { - use base64::{engine::general_purpose::STANDARD, Engine}; - use std::io::Read; - - // Read the package file - let mut package_contents = Vec::new(); - File::open(package_path)?.read_to_end(&mut package_contents)?; - - // Get the private key from settings - let private_key = settings - .private_key() - .ok_or_else(|| anyhow::anyhow!("Private key not found in settings"))?; - - // Create signature using minisign - let secret_key = minisign::SecretKey::from_base64(private_key) - .map_err(|e| anyhow::anyhow!("Invalid private key: {}", e))?; - - let signature = minisign::sign( - &secret_key, - &package_contents, - None, - None, - false, - ).map_err(|e| anyhow::anyhow!("Failed to create signature: {}", e))?; - - // Create signature file - let signature_path = package_path.with_extension("sig"); - let mut signature_file = File::create(&signature_path)?; - signature_file.write_all(STANDARD.encode(signature.to_string()).as_bytes())?; - - Ok(signature_path) -} - // Create simple update-win_.zip // Including the binary as root // Right now in windows we hot replace the bin and request a restart diff --git a/crates/tauri-cli/config.schema.json b/crates/tauri-cli/config.schema.json index a05ba79935ed..047c4a7393e0 100644 --- a/crates/tauri-cli/config.schema.json +++ b/crates/tauri-cli/config.schema.json @@ -1104,7 +1104,7 @@ ] }, "Capability": { - "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", @@ -1151,7 +1151,7 @@ } }, "permissions": { - "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", + "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" diff --git a/crates/tauri-schema-generator/schemas/capability.schema.json b/crates/tauri-schema-generator/schemas/capability.schema.json index 80df9a6893f8..0c9462c500aa 100644 --- a/crates/tauri-schema-generator/schemas/capability.schema.json +++ b/crates/tauri-schema-generator/schemas/capability.schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Capability", - "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", @@ -48,7 +48,7 @@ } }, "permissions": { - "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", + "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" diff --git a/crates/tauri-schema-generator/schemas/config.schema.json b/crates/tauri-schema-generator/schemas/config.schema.json index a05ba79935ed..047c4a7393e0 100644 --- a/crates/tauri-schema-generator/schemas/config.schema.json +++ b/crates/tauri-schema-generator/schemas/config.schema.json @@ -1104,7 +1104,7 @@ ] }, "Capability": { - "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```", "type": "object", "required": [ "identifier", @@ -1151,7 +1151,7 @@ } }, "permissions": { - "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ```", + "description": "List of permissions attached to this capability.\n\n Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.\n For commands directly implemented in the application itself only `${permission-name}`\n is required.\n\n ## Example\n\n ```json\n [\n \"core:default\",\n \"shell:allow-open\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n }\n ]\n ```", "type": "array", "items": { "$ref": "#/definitions/PermissionEntry" From 8bb40047a1a4df05522f4a15c8d1122e411a27d5 Mon Sep 17 00:00:00 2001 From: jLynx Date: Fri, 1 Nov 2024 12:23:28 +1300 Subject: [PATCH 3/8] generates deb as update --- crates/tauri-bundler/src/bundle.rs | 3 ++- crates/tauri-cli/src/bundle.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/tauri-bundler/src/bundle.rs b/crates/tauri-bundler/src/bundle.rs index 17100cb9cdfd..2f470c0c38d9 100644 --- a/crates/tauri-bundler/src/bundle.rs +++ b/crates/tauri-bundler/src/bundle.rs @@ -151,6 +151,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result> { | PackageType::MacOsBundle | PackageType::Nsis | PackageType::WindowsMsi + | PackageType::Deb ) } else { matches!(package_type, PackageType::MacOsBundle) @@ -166,7 +167,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result> { // Self contained updater, no need to zip matches!( package_type, - PackageType::AppImage | PackageType::Nsis | PackageType::WindowsMsi + PackageType::AppImage | PackageType::Nsis | PackageType::WindowsMsi | PackageType::Deb ) }) { diff --git a/crates/tauri-cli/src/bundle.rs b/crates/tauri-cli/src/bundle.rs index eded4aa2b477..476be86a988b 100644 --- a/crates/tauri-cli/src/bundle.rs +++ b/crates/tauri-cli/src/bundle.rs @@ -226,7 +226,7 @@ fn sign_updaters( .filter(|bundle| { matches!( bundle.package_type, - PackageType::Updater | PackageType::Nsis | PackageType::WindowsMsi | PackageType::AppImage + PackageType::Updater | PackageType::Nsis | PackageType::WindowsMsi | PackageType::AppImage | PackageType::Deb ) }) .collect(); From acd16d228940aaa0cf7331af36099199dcdba4b8 Mon Sep 17 00:00:00 2001 From: jLynx Date: Fri, 1 Nov 2024 15:58:02 +1300 Subject: [PATCH 4/8] Fixed linting --- .../src/bundle/updater_bundle.rs | 102 +++++++++--------- crates/tauri-cli/src/bundle.rs | 6 +- 2 files changed, 56 insertions(+), 52 deletions(-) diff --git a/crates/tauri-bundler/src/bundle/updater_bundle.rs b/crates/tauri-bundler/src/bundle/updater_bundle.rs index 96ae0809ea2e..fdab4e15523d 100644 --- a/crates/tauri-bundler/src/bundle/updater_bundle.rs +++ b/crates/tauri-bundler/src/bundle/updater_bundle.rs @@ -91,63 +91,63 @@ fn bundle_update_macos(bundles: &[Bundle]) -> crate::Result> { // No assets are replaced #[cfg(target_os = "linux")] fn bundle_update_linux(bundles: &[Bundle]) -> crate::Result> { - use std::ffi::OsStr; + use std::ffi::OsStr; - let mut archived_paths = Vec::new(); + let mut archived_paths = Vec::new(); - // Handle AppImage bundles - if let Some(source_path) = bundles + // Handle AppImage bundles + if let Some(source_path) = bundles + .iter() + .filter(|bundle| bundle.package_type == crate::PackageType::AppImage) + .find_map(|bundle| { + bundle + .bundle_paths .iter() - .filter(|bundle| bundle.package_type == crate::PackageType::AppImage) - .find_map(|bundle| { - bundle - .bundle_paths - .iter() - .find(|path| path.extension() == Some(OsStr::new("AppImage"))) - }) - { - // add .tar.gz to our path - let appimage_archived = format!("{}.tar.gz", source_path.display()); - let appimage_archived_path = PathBuf::from(&appimage_archived); - - // Create our gzip file for AppImage - create_tar(source_path, &appimage_archived_path) - .with_context(|| "Failed to tar.gz AppImage update directory")?; - - log::info!(action = "Bundling"; "{} ({})", appimage_archived, display_path(&appimage_archived_path)); - - archived_paths.push(appimage_archived_path); - } + .find(|path| path.extension() == Some(OsStr::new("AppImage"))) + }) + { + // add .tar.gz to our path + let appimage_archived = format!("{}.tar.gz", source_path.display()); + let appimage_archived_path = PathBuf::from(&appimage_archived); + + // Create our gzip file for AppImage + create_tar(source_path, &appimage_archived_path) + .with_context(|| "Failed to tar.gz AppImage update directory")?; + + log::info!(action = "Bundling"; "{} ({})", appimage_archived, display_path(&appimage_archived_path)); - // Handle Debian packages - if let Some(source_path) = bundles + archived_paths.push(appimage_archived_path); + } + + // Handle Debian packages + if let Some(source_path) = bundles + .iter() + .filter(|bundle| bundle.package_type == crate::PackageType::Deb) + .find_map(|bundle| { + bundle + .bundle_paths .iter() - .filter(|bundle| bundle.package_type == crate::PackageType::Deb) - .find_map(|bundle| { - bundle - .bundle_paths - .iter() - .find(|path| path.extension() == Some(OsStr::new("deb"))) - }) - { - // add .tar.gz to our path - let deb_archived = format!("{}.tar.gz", source_path.display()); - let deb_archived_path = PathBuf::from(&deb_archived); - - // Create our gzip file for Deb - create_tar(source_path, &deb_archived_path) - .with_context(|| "Failed to tar.gz Debian package update directory")?; - - log::info!(action = "Bundling"; "{} ({})", deb_archived, display_path(&deb_archived_path)); - - archived_paths.push(deb_archived_path); - } + .find(|path| path.extension() == Some(OsStr::new("deb"))) + }) + { + // add .tar.gz to our path + let deb_archived = format!("{}.tar.gz", source_path.display()); + let deb_archived_path = PathBuf::from(&deb_archived); - if archived_paths.is_empty() { - Err(crate::Error::UnableToFindProject) - } else { - Ok(archived_paths) - } + // Create our gzip file for Deb + create_tar(source_path, &deb_archived_path) + .with_context(|| "Failed to tar.gz Debian package update directory")?; + + log::info!(action = "Bundling"; "{} ({})", deb_archived, display_path(&deb_archived_path)); + + archived_paths.push(deb_archived_path); + } + + if archived_paths.is_empty() { + Err(crate::Error::UnableToFindProject) + } else { + Ok(archived_paths) + } } // Create simple update-win_.zip diff --git a/crates/tauri-cli/src/bundle.rs b/crates/tauri-cli/src/bundle.rs index 476be86a988b..5473c4b4690c 100644 --- a/crates/tauri-cli/src/bundle.rs +++ b/crates/tauri-cli/src/bundle.rs @@ -226,7 +226,11 @@ fn sign_updaters( .filter(|bundle| { matches!( bundle.package_type, - PackageType::Updater | PackageType::Nsis | PackageType::WindowsMsi | PackageType::AppImage | PackageType::Deb + PackageType::Updater + | PackageType::Nsis + | PackageType::WindowsMsi + | PackageType::AppImage + | PackageType::Deb ) }) .collect(); From 619ae702463efcf67f10696ddb129cdf70acbd00 Mon Sep 17 00:00:00 2001 From: jLynx Date: Mon, 4 Nov 2024 10:14:03 +1300 Subject: [PATCH 5/8] Revert deb gz --- .../src/bundle/updater_bundle.rs | 40 +++---------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/crates/tauri-bundler/src/bundle/updater_bundle.rs b/crates/tauri-bundler/src/bundle/updater_bundle.rs index fdab4e15523d..77749afca21e 100644 --- a/crates/tauri-bundler/src/bundle/updater_bundle.rs +++ b/crates/tauri-bundler/src/bundle/updater_bundle.rs @@ -93,9 +93,7 @@ fn bundle_update_macos(bundles: &[Bundle]) -> crate::Result> { fn bundle_update_linux(bundles: &[Bundle]) -> crate::Result> { use std::ffi::OsStr; - let mut archived_paths = Vec::new(); - - // Handle AppImage bundles + // build our app actually we support only appimage on linux if let Some(source_path) = bundles .iter() .filter(|bundle| bundle.package_type == crate::PackageType::AppImage) @@ -110,43 +108,15 @@ fn bundle_update_linux(bundles: &[Bundle]) -> crate::Result> { let appimage_archived = format!("{}.tar.gz", source_path.display()); let appimage_archived_path = PathBuf::from(&appimage_archived); - // Create our gzip file for AppImage + // Create our gzip file create_tar(source_path, &appimage_archived_path) - .with_context(|| "Failed to tar.gz AppImage update directory")?; + .with_context(|| "Failed to tar.gz update directory")?; log::info!(action = "Bundling"; "{} ({})", appimage_archived, display_path(&appimage_archived_path)); - archived_paths.push(appimage_archived_path); - } - - // Handle Debian packages - if let Some(source_path) = bundles - .iter() - .filter(|bundle| bundle.package_type == crate::PackageType::Deb) - .find_map(|bundle| { - bundle - .bundle_paths - .iter() - .find(|path| path.extension() == Some(OsStr::new("deb"))) - }) - { - // add .tar.gz to our path - let deb_archived = format!("{}.tar.gz", source_path.display()); - let deb_archived_path = PathBuf::from(&deb_archived); - - // Create our gzip file for Deb - create_tar(source_path, &deb_archived_path) - .with_context(|| "Failed to tar.gz Debian package update directory")?; - - log::info!(action = "Bundling"; "{} ({})", deb_archived, display_path(&deb_archived_path)); - - archived_paths.push(deb_archived_path); - } - - if archived_paths.is_empty() { - Err(crate::Error::UnableToFindProject) + Ok(vec![appimage_archived_path]) } else { - Ok(archived_paths) + Err(crate::Error::UnableToFindProject) } } From 4f2209e61bdba421060f78a13d4daab300ce3da9 Mon Sep 17 00:00:00 2001 From: jLynx Date: Wed, 13 Nov 2024 12:11:59 +1300 Subject: [PATCH 6/8] Added changes file --- .changes/deb-updater-support.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/deb-updater-support.md diff --git a/.changes/deb-updater-support.md b/.changes/deb-updater-support.md new file mode 100644 index 000000000000..5f9962a027b1 --- /dev/null +++ b/.changes/deb-updater-support.md @@ -0,0 +1,6 @@ +--- +'@tauri-apps/cli': minor:feat +'@tauri-apps/bundler': minor:feat +--- + +Add support for Debian (`.deb`) packages in the updater bundle system, enabling self-contained updater functionality for Debian packages alongside existing formats like AppImage, NSIS, and Windows MSI. From c7452c38c3912a31861d5ba60a62e0bbdd7bd3a6 Mon Sep 17 00:00:00 2001 From: jLynx Date: Wed, 13 Nov 2024 13:23:39 +1300 Subject: [PATCH 7/8] Update .changes/deb-updater-support.md Co-authored-by: Amr Bashir --- .changes/deb-updater-support.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.changes/deb-updater-support.md b/.changes/deb-updater-support.md index 5f9962a027b1..f3751bd500dd 100644 --- a/.changes/deb-updater-support.md +++ b/.changes/deb-updater-support.md @@ -1,6 +1,7 @@ --- +'tauri-bundler': minor:feat +'tauri-cli': minor:feat '@tauri-apps/cli': minor:feat -'@tauri-apps/bundler': minor:feat --- Add support for Debian (`.deb`) packages in the updater bundle system, enabling self-contained updater functionality for Debian packages alongside existing formats like AppImage, NSIS, and Windows MSI. From f528070ab30463267b195b6e1e23573e95638b2d Mon Sep 17 00:00:00 2001 From: jLynx Date: Wed, 13 Nov 2024 13:23:46 +1300 Subject: [PATCH 8/8] Update .changes/deb-updater-support.md Co-authored-by: Amr Bashir --- .changes/deb-updater-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/deb-updater-support.md b/.changes/deb-updater-support.md index f3751bd500dd..001a5b1dccd7 100644 --- a/.changes/deb-updater-support.md +++ b/.changes/deb-updater-support.md @@ -4,4 +4,4 @@ '@tauri-apps/cli': minor:feat --- -Add support for Debian (`.deb`) packages in the updater bundle system, enabling self-contained updater functionality for Debian packages alongside existing formats like AppImage, NSIS, and Windows MSI. +Generate signature for `.deb` packages when `createUpdaterArtifacts` option is enabled.