fix(cli): export method on Xcode < 15.4, closes #13818 (#14106)

see https://github.com/fastlane/fastlane/issues/22028 for additional context
This commit is contained in:
Lucas Fernandes Nogueira
2025-08-28 12:37:26 -03:00
committed by GitHub
parent 07e134f70e
commit 956b4fd6ff
4 changed files with 61 additions and 2 deletions

View File

@@ -0,0 +1,6 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Use the correct export method on Xcode < 15.4.

View File

@@ -175,6 +175,22 @@ fn is_xcode_command_line_tools_installed() -> bool {
.map(|o| o.status.success())
.unwrap_or(false)
}
#[cfg(target_os = "macos")]
pub fn xcode_version() -> Option<String> {
Command::new("xcodebuild")
.arg("-version")
.output()
.ok()
.map(|o| String::from_utf8_lossy(&o.stdout).into_owned())
.and_then(|s| {
s.split('\n')
.filter_map(|line| line.strip_prefix("Xcode "))
.next()
.map(ToString::to_string)
})
}
fn de_and_session() -> String {
#[cfg(any(
target_os = "linux",
@@ -319,5 +335,11 @@ pub fn items() -> Vec<SectionItem> {
}.into()
},
),
#[cfg(target_os = "macos")]
SectionItem::new().action(|| {
xcode_version().map(|v| (format!("Xcode: {v}"), Status::Success)).unwrap_or_else(|| {
(format!("Xcode: {}", "not installed!".red()), Status::Error)
}).into()
}),
]
}

View File

@@ -15,7 +15,7 @@ use std::fmt::{self, Display, Formatter};
mod app;
mod env_nodejs;
mod env_rust;
mod env_system;
pub mod env_system;
#[cfg(target_os = "macos")]
mod ios;
mod packages_nodejs;

View File

@@ -102,6 +102,17 @@ pub enum ExportMethod {
Debugging,
}
impl ExportMethod {
/// Xcode 15.4 deprecated these names (in this case we should use the Display impl).
pub fn pre_xcode_15_4_name(&self) -> String {
match self {
Self::AppStoreConnect => "app-store".to_string(),
Self::ReleaseTesting => "ad-hoc".to_string(),
Self::Debugging => "development".to_string(),
}
}
}
impl std::fmt::Display for ExportMethod {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
@@ -215,7 +226,27 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
let mut export_options_plist = plist::Dictionary::new();
if let Some(method) = options.export_method {
export_options_plist.insert("method".to_string(), method.to_string().into());
let xcode_version =
crate::info::env_system::xcode_version().context("failed to determine Xcode version")?;
let mut iter = xcode_version.split('.');
let major = iter.next().context(format!(
"failed to parse Xcode version `{xcode_version}` as semver"
))?;
let minor = iter.next().context(format!(
"failed to parse Xcode version `{xcode_version}` as semver"
))?;
let major = major.parse::<u64>().context(format!(
"failed to parse Xcode version `{xcode_version}` as semver: major is not a number"
))?;
let minor = minor.parse::<u64>().context(format!(
"failed to parse Xcode version `{xcode_version}` as semver: minor is not a number"
))?;
if major < 15 || (major == 15 && minor < 4) {
export_options_plist.insert("method".to_string(), method.pre_xcode_15_4_name().into());
} else {
export_options_plist.insert("method".to_string(), method.to_string().into());
}
}
let (keychain, provisioning_profile) = super::signing_from_env()?;