From 09e9dc1aab1b66aa6a3a009d5873db586abe76a0 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Fri, 23 Aug 2024 21:12:49 -0300 Subject: [PATCH] feat(cli): allow xcodebuild to manage iOS signing and provisioning (#10752) --- .changes/provisioning-signing-ios.md | 7 +++++ tooling/cli/Cargo.lock | 4 +-- tooling/cli/Cargo.toml | 2 +- tooling/cli/ENVIRONMENT_VARIABLES.md | 4 +-- tooling/cli/src/mobile/ios/build.rs | 39 +++++++++++++++++++++++++--- 5 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 .changes/provisioning-signing-ios.md diff --git a/.changes/provisioning-signing-ios.md b/.changes/provisioning-signing-ios.md new file mode 100644 index 000000000000..6a8d48ae268b --- /dev/null +++ b/.changes/provisioning-signing-ios.md @@ -0,0 +1,7 @@ +--- +'tauri-cli': 'patch:feat' +'@tauri-apps/cli': 'patch:feat' +--- + +Allow Xcode to manage iOS code sign and provisioning profiles by default. +On CI, the `APPLE_API_KEY`, `APPLE_API_ISSUER` and `APPLE_API_KEY_PATH` environment variables must be provided for authentication. diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index a17c239e10cb..c5e634e53da6 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -557,9 +557,9 @@ dependencies = [ [[package]] name = "cargo-mobile2" -version = "0.13.5" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bd9e694230d442d680f8e578b4f252c67adbfd74cc1dd1caa9e1f1767114dc" +checksum = "b37140c84631f1a416fff6a3f898db7bda1a2643335fdf14e3d5eb5af61bf2e3" dependencies = [ "colored", "core-foundation 0.10.0", diff --git a/tooling/cli/Cargo.toml b/tooling/cli/Cargo.toml index 0d3a32b00c28..a21daafe7efe 100644 --- a/tooling/cli/Cargo.toml +++ b/tooling/cli/Cargo.toml @@ -39,7 +39,7 @@ name = "cargo-tauri" path = "src/main.rs" [dependencies] -cargo-mobile2 = { version = "0.13.5", default-features = false } +cargo-mobile2 = { version = "0.14", default-features = false } jsonrpsee = { version = "0.24", features = [ "server" ] } jsonrpsee-core = "0.24" jsonrpsee-client-transport = { version = "0.24", features = [ "ws" ] } diff --git a/tooling/cli/ENVIRONMENT_VARIABLES.md b/tooling/cli/ENVIRONMENT_VARIABLES.md index b4e5bb4f7870..5ce3089eeecb 100644 --- a/tooling/cli/ENVIRONMENT_VARIABLES.md +++ b/tooling/cli/ENVIRONMENT_VARIABLES.md @@ -26,11 +26,11 @@ These environment variables are inputs to the CLI which may have an equivalent C - `APPLE_ID` — The Apple ID used to notarize the application. If this environment variable is provided, `APPLE_PASSWORD` and `APPLE_TEAM_ID` must also be set. Alternatively, `APPLE_API_KEY` and `APPLE_API_ISSUER` can be used to authenticate. - `APPLE_PASSWORD` — The Apple password used to authenticate for application notarization. Required if `APPLE_ID` is specified. An app-specific password can be used. Alternatively to entering the password in plaintext, it may also be specified using a '@keychain:' or '@env:' prefix followed by a keychain password item name or environment variable name. - `APPLE_TEAM_ID`: Developer team ID. To find your Team ID, go to the [Account](https://developer.apple.com/account) page on the Apple Developer website, and check your membership details. -- `APPLE_API_KEY` — Alternative to `APPLE_ID` and `APPLE_PASSWORD` for notarization authentication using JWT. +- `APPLE_API_KEY` — Alternative to `APPLE_ID` and `APPLE_PASSWORD` for notarization authentication using JWT. Also an option to allow automated iOS certificate and provisioning profile management. - See [creating API keys](https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api) for more information. - `API_PRIVATE_KEYS_DIR` — Specify the directory where your AuthKey file is located. See `APPLE_API_KEY`. - `APPLE_API_ISSUER` — Issuer ID. Required if `APPLE_API_KEY` is specified. -- `APPLE_API_KEY_PATH` - path to the API key `.p8` file. If not specified, the bundler searches the following directories in sequence for a private key file with the name of 'AuthKey\_.p8': './private_keys', '~/private_keys', '~/.private_keys', and '~/.appstoreconnect/private_keys'. +- `APPLE_API_KEY_PATH` - path to the API key `.p8` file. If not specified, for macOS apps the bundler searches the following directories in sequence for a private key file with the name of 'AuthKey\_.p8': './private_keys', '~/private_keys', '~/.private_keys', and '~/.appstoreconnect/private_keys'. **For iOS this variable is required**. - `APPLE_SIGNING_IDENTITY` — The identity used to code sign. Overwrites `tauri.conf.json > bundle > macOS > signingIdentity`. If neither are set, it is inferred from `APPLE_CERTIFICATE` when provided. - `APPLE_PROVIDER_SHORT_NAME` — If your Apple ID is connected to multiple teams, you have to specify the provider short name of the team you want to use to notarize your app. Overwrites `tauri.conf.json > bundle > macOS > providerShortName`. - `APPLE_DEVELOPMENT_TEAM` — The team ID used to code sign on iOS. Overwrites `tauri.conf.json > bundle > iOS > developmentTeam`. Can be found in https://developer.apple.com/account#MembershipDetailsCard. diff --git a/tooling/cli/src/mobile/ios/build.rs b/tooling/cli/src/mobile/ios/build.rs index 5da719a75704..ee1107719caf 100644 --- a/tooling/cli/src/mobile/ios/build.rs +++ b/tooling/cli/src/mobile/ios/build.rs @@ -22,13 +22,20 @@ use clap::{ArgAction, Parser, ValueEnum}; use anyhow::Context; use cargo_mobile2::{ - apple::{config::Config as AppleConfig, target::Target}, + apple::{ + config::Config as AppleConfig, + target::{ExportConfig, Target}, + }, env::Env, opts::{NoiseLevel, Profile}, target::{call_for_targets_with_fallback, TargetInvalid, TargetTrait}, }; -use std::{env::set_current_dir, fs}; +use std::{ + env::{set_current_dir, var, var_os}, + fs, + path::PathBuf, +}; #[derive(Debug, Clone, Parser)] #[clap( @@ -294,7 +301,13 @@ fn run_build( target.build(config, env, NoiseLevel::FranklyQuitePedantic, profile)?; target.archive(config, env, noise_level, profile, Some(app_version))?; - target.export(config, env, noise_level)?; + + let mut export_config = ExportConfig::new().allow_provisioning_updates(); + if let Some(credentials) = auth_credentials_from_env()? { + export_config = export_config.authentication_credentials(credentials); + } + + target.export(config, env, noise_level, export_config)?; if let Ok(ipa_path) = config.ipa_path() { let out_dir = config.export_dir().join(target.arch); @@ -313,3 +326,23 @@ fn run_build( Ok(handle) } + +fn auth_credentials_from_env() -> Result> { + match ( + var("APPLE_API_KEY"), + var("APPLE_API_ISSUER"), + var_os("APPLE_API_KEY_PATH").map(PathBuf::from), + ) { + (Ok(key_id), Ok(key_issuer_id), Some(key_path)) => { + Ok(Some(cargo_mobile2::apple::target::AuthCredentials { + key_path, + key_id, + key_issuer_id, + })) + } + (Err(_), Err(_), None) => Ok(None), + _ => anyhow::bail!( + "APPLE_API_KEY, APPLE_API_ISSUER and APPLE_API_KEY_PATH must be provided for code signing" + ), + } +}