From 83f492d10d3732bc09c4496048c698ccf3b917ee Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 5 May 2026 00:29:29 +0100 Subject: [PATCH] Fix macos signing/notarization (0.7 backport) (#5528) * Staple notarization to .app not .zip * Fix default value for hardened_runtime macos bundle setting --- packages/cli/src/bundler/macos.rs | 14 +++++++------- packages/cli/src/config/bundle.rs | 22 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/bundler/macos.rs b/packages/cli/src/bundler/macos.rs index f9805be3a..cb4691cb3 100644 --- a/packages/cli/src/bundler/macos.rs +++ b/packages/cli/src/bundler/macos.rs @@ -221,7 +221,7 @@ impl BundleContext<'_> { bail!("ditto failed to create zip for notarization"); } - match notarize(&zip_path).await { + match notarize(&zip_path, &app_dir).await { Ok(()) => { let _ = fs::remove_file(&zip_path); } @@ -356,7 +356,7 @@ impl BundleContext<'_> { std::env::var("APPLE_ID").is_ok() || std::env::var("APPLE_API_KEY").is_ok(); if should_notarize { - notarize(&dmg_path).await?; + notarize(&dmg_path, &dmg_path).await?; } } @@ -853,7 +853,7 @@ async fn sign_path( } /// Notarize a .app or .dmg with Apple's notary service. -async fn notarize(app_path: &Path) -> Result<()> { +async fn notarize(notarize_path: &Path, staple_path: &Path) -> Result<()> { let apple_id = std::env::var("APPLE_ID").ok(); let apple_password = std::env::var("APPLE_PASSWORD").ok(); let apple_team_id = std::env::var("APPLE_TEAM_ID").ok(); @@ -863,7 +863,7 @@ async fn notarize(app_path: &Path) -> Result<()> { let mut cmd = Command::new("xcrun"); cmd.args(["notarytool", "submit"]); - cmd.arg(app_path); + cmd.arg(notarize_path); if let (Some(key), Some(issuer), Some(key_path)) = (&api_key, &api_issuer, &api_key_path) { cmd.args(["--key", key_path]); @@ -883,15 +883,15 @@ async fn notarize(app_path: &Path) -> Result<()> { cmd.arg("--wait"); - tracing::info!("Submitting {} for notarization...", app_path.display()); + tracing::info!("Submitting {} for notarization...", notarize_path.display()); run_command(&mut cmd, "xcrun notarytool submit").await?; tracing::info!("Stapling notarization ticket..."); let mut staple_cmd = Command::new("xcrun"); - staple_cmd.args(["stapler", "staple"]).arg(app_path); + staple_cmd.args(["stapler", "staple"]).arg(staple_path); run_command(&mut staple_cmd, "xcrun stapler staple").await?; - tracing::info!("Notarization complete for {}", app_path.display()); + tracing::info!("Notarization complete for {}", staple_path.display()); Ok(()) } diff --git a/packages/cli/src/config/bundle.rs b/packages/cli/src/config/bundle.rs index f58f279e4..cbdd771fd 100644 --- a/packages/cli/src/config/bundle.rs +++ b/packages/cli/src/config/bundle.rs @@ -149,7 +149,7 @@ pub(crate) struct WixSettings { pub upgrade_code: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)] +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub(crate) struct MacOsSettings { #[serde(default)] pub(crate) bundle_version: Option, @@ -197,6 +197,26 @@ fn default_hardened_runtime() -> bool { true } +// Custom default impl so that we can default hardened_runtime to true +impl Default for MacOsSettings { + fn default() -> Self { + Self { + bundle_version: None, + frameworks: None, + minimum_system_version: None, + license: None, + exception_domain: None, + signing_identity: None, + provider_short_name: None, + entitlements: None, + info_plist_path: None, + bundle_name: None, + files: HashMap::new(), + hardened_runtime: true, + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)] pub(crate) struct WindowsSettings { #[serde(default)]