diff --git a/.github/workflows/test-mobile.yml b/.github/workflows/test-mobile.yml index 6ebdf91eb..242b4ad24 100644 --- a/.github/workflows/test-mobile.yml +++ b/.github/workflows/test-mobile.yml @@ -12,7 +12,7 @@ concurrency: cancel-in-progress: true jobs: - test-android: + test: runs-on: ${{ matrix.platform }} strategy: @@ -77,14 +77,30 @@ jobs: working-directory: ./examples/api run: yarn - - name: Init Android Studio Project + - name: init Android Studio project working-directory: ./examples/api run: ../../tooling/cli/target/debug/cargo-tauri android init env: NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - - name: Build apk + - name: build APK working-directory: ./examples/api run: ../../tooling/cli/target/debug/cargo-tauri android build env: NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} + + - name: setup iOS code signing certificate + if: matrix.platform == 'macos-latest' + run: ./tooling/cli/target/debug/cargo-tauri ios certificate setup + env: + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + + - name: init XCode project + if: matrix.platform == 'macos-latest' + working-directory: ./examples/api + run: ../../tooling/cli/target/debug/cargo-tauri ios init + + - name: build IPA + if: matrix.platform == 'macos-latest' + run: ../../tooling/cli/target/debug/cargo-tauri ios build diff --git a/tooling/bundler/src/bundle.rs b/tooling/bundler/src/bundle.rs index bfaf3f739..4217fa16f 100644 --- a/tooling/bundler/src/bundle.rs +++ b/tooling/bundler/src/bundle.rs @@ -16,6 +16,9 @@ mod updater_bundle; #[cfg(target_os = "windows")] mod windows; +#[cfg(target_os = "macos")] +pub use macos::sign as macos_sign; + pub use self::{ category::AppCategory, settings::{ diff --git a/tooling/bundler/src/bundle/macos/mod.rs b/tooling/bundler/src/bundle/macos/mod.rs index 303c582c8..ec85b60fa 100644 --- a/tooling/bundler/src/bundle/macos/mod.rs +++ b/tooling/bundler/src/bundle/macos/mod.rs @@ -7,4 +7,5 @@ pub mod app; pub mod dmg; pub mod icon; pub mod ios; +/// Code signing and notarization utilities. pub mod sign; diff --git a/tooling/bundler/src/bundle/macos/sign.rs b/tooling/bundler/src/bundle/macos/sign.rs index 5272d9244..103eadf74 100644 --- a/tooling/bundler/src/bundle/macos/sign.rs +++ b/tooling/bundler/src/bundle/macos/sign.rs @@ -14,12 +14,12 @@ use regex::Regex; const KEYCHAIN_ID: &str = "tauri-build.keychain"; const KEYCHAIN_PWD: &str = "tauri-build"; -// Import certificate from ENV variables. -// APPLE_CERTIFICATE is the p12 certificate base64 encoded. -// By example you can use; openssl base64 -in MyCertificate.p12 -out MyCertificate-base64.txt -// Then use the value of the base64 in APPLE_CERTIFICATE env variable. -// You need to set APPLE_CERTIFICATE_PASSWORD to the password you set when you exported your certificate. -// https://help.apple.com/xcode/mac/current/#/dev154b28f09 see: `Export a signing certificate` +/// Import certificate from ENV variables. +/// APPLE_CERTIFICATE is the p12 certificate base64 encoded. +/// By example you can use; openssl base64 -in MyCertificate.p12 -out MyCertificate-base64.txt +/// Then use the value of the base64 in APPLE_CERTIFICATE env variable. +/// You need to set APPLE_CERTIFICATE_PASSWORD to the password you set when you exported your certificate. +/// https://help.apple.com/xcode/mac/current/#/dev154b28f09 see: `Export a signing certificate` pub fn setup_keychain( certificate_encoded: OsString, certificate_password: OsString, @@ -130,6 +130,7 @@ pub fn setup_keychain( Ok(()) } +/// Deletes the keychain we setup from the environment variables. pub fn delete_keychain() { // delete keychain if needed and skip any error let _ = Command::new("security") @@ -138,6 +139,7 @@ pub fn delete_keychain() { .output_ok(); } +/// Sign the application. pub fn sign( path_to_sign: PathBuf, identity: &str, @@ -212,6 +214,7 @@ fn try_sign( Ok(()) } +/// Notarize the application. pub fn notarize( app_bundle_path: PathBuf, auth_args: Vec, @@ -373,6 +376,7 @@ fn get_notarization_status( } } +/// Authorization arguments for the notarization process. Read from environment variables. pub fn notarize_auth_args() -> crate::Result> { match ( std::env::var_os("APPLE_ID"), diff --git a/tooling/cli/src/mobile/ios.rs b/tooling/cli/src/mobile/ios.rs index 2edda014b..343abdb17 100644 --- a/tooling/cli/src/mobile/ios.rs +++ b/tooling/cli/src/mobile/ios.rs @@ -39,6 +39,7 @@ use std::{ }; mod build; +mod certificate; mod dev; mod open; pub(crate) mod project; @@ -78,6 +79,14 @@ enum Commands { Build(build::Options), #[clap(hide(true))] XcodeScript(xcode_script::Options), + #[clap(subcommand)] + Certificate(CertificateCommands), +} + +#[derive(Subcommand)] +enum CertificateCommands { + Setup, + Delete, } pub fn command(cli: Cli, verbosity: u8) -> Result<()> { @@ -88,6 +97,8 @@ pub fn command(cli: Cli, verbosity: u8) -> Result<()> { Commands::Dev(options) => dev::command(options, noise_level)?, Commands::Build(options) => build::command(options, noise_level)?, Commands::XcodeScript(options) => xcode_script::command(options)?, + Commands::Certificate(CertificateCommands::Setup) => certificate::setup()?, + Commands::Certificate(CertificateCommands::Delete) => certificate::delete(), } Ok(()) diff --git a/tooling/cli/src/mobile/ios/certificate.rs b/tooling/cli/src/mobile/ios/certificate.rs new file mode 100644 index 000000000..ad8e00b56 --- /dev/null +++ b/tooling/cli/src/mobile/ios/certificate.rs @@ -0,0 +1,22 @@ +use crate::Result; +use tauri_bundler::bundle::macos_sign::{delete_keychain, setup_keychain}; + +pub fn setup() -> Result<()> { + if let (Some(certificate_encoded), Some(certificate_password)) = ( + std::env::var_os("APPLE_CERTIFICATE"), + std::env::var_os("APPLE_CERTIFICATE_PASSWORD"), + ) { + // setup keychain allow you to import your certificate + // for CI build + setup_keychain(certificate_encoded, certificate_password)?; + Ok(()) + } else { + Err(anyhow::anyhow!( + "Missing APPLE_CERTIFICATE and APPLE_CERTIFICATE_PASSWORD environment variables" + )) + } +} + +pub fn delete() { + delete_keychain(); +}