Files
TREK/client/fastlane/Fastfile
T

100 lines
3.9 KiB
Ruby

# iOS release signing and TestFlight upload, driven by .github/workflows/native-release.yml.
#
# Automatic signing cannot work on a CI runner with no registered devices: it signs
# the archive for development and then needs a development provisioning profile, which
# requires a device. So this signs manually for distribution instead. The distribution
# certificate and the App Store provisioning profile are created (or reused) through the
# App Store Connect API key, which means no certificate or profile has to be stored as a
# secret: the key the workflow already holds is enough.
#
# The lane expects these in the environment (the workflow sets them):
# ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_PATH — the App Store Connect API key
# APPLE_TEAM_ID — the developer team
# MARKETING_VERSION, CURRENT_PROJECT_VERSION — the version and build number
# RUNNER_TEMP — a writable scratch directory
default_platform(:ios)
APP_IDENTIFIER = "com.liketrek.trek"
PROJECT = "ios/App/App.xcodeproj"
platform :ios do
desc "Build the signed Release app and upload it to TestFlight (internal testing)."
lane :beta do
key = app_store_connect_api_key(
key_id: ENV.fetch("ASC_KEY_ID"),
issuer_id: ENV.fetch("ASC_ISSUER_ID"),
key_filepath: ENV.fetch("ASC_KEY_PATH"),
in_house: false,
)
# A throwaway keychain with a known password, so fastlane can unlock the imported
# private key for code signing (without the password it cannot set the key's access
# list and the certificate is never usable).
keychain_name = "trek_ci.keychain"
keychain_password = "trek-ci-#{ENV.fetch('GITHUB_RUN_ID', 'local')}"
create_keychain(
name: keychain_name,
password: keychain_password,
default_keychain: true,
unlock: true,
timeout: 3600,
lock_when_sleeps: false,
)
keychain_path = File.expand_path("~/Library/Keychains/#{keychain_name}-db")
# Import the one distribution certificate from its stored .p12, rather than
# minting a new one each run — Apple caps distribution certificates at two, so
# a fresh one per build would quickly hit the limit. The matching App Store
# profile is created (or reused) through the API key.
import_certificate(
certificate_path: ENV.fetch("CERT_P12_PATH"),
certificate_password: ENV.fetch("CERT_P12_PASSWORD"),
keychain_name: keychain_name,
keychain_path: keychain_path,
keychain_password: keychain_password,
)
get_provisioning_profile(
api_key: key,
app_identifier: APP_IDENTIFIER,
development: false,
)
# Pin the project to that profile for this build; automatic signing stays the default
# a developer sees when they open the project in Xcode.
update_code_signing_settings(
path: PROJECT,
use_automatic_signing: false,
team_id: ENV.fetch("APPLE_TEAM_ID"),
code_sign_identity: "Apple Distribution",
bundle_identifier: APP_IDENTIFIER,
profile_name: lane_context[SharedValues::SIGH_NAME],
targets: ["App"],
)
build_app(
project: PROJECT,
scheme: "App",
configuration: "Release",
export_method: "app-store",
output_directory: File.join(ENV.fetch("RUNNER_TEMP"), "export"),
xcargs: [
"MARKETING_VERSION=#{ENV.fetch('MARKETING_VERSION')}",
"CURRENT_PROJECT_VERSION=#{ENV.fetch('CURRENT_PROJECT_VERSION')}",
].join(" "),
export_options: {
signingStyle: "manual",
provisioningProfiles: { APP_IDENTIFIER => lane_context[SharedValues::SIGH_NAME] },
},
)
# Upload to App Store Connect; it shows up in TestFlight after Apple finishes processing.
# Internal testing needs no App Review, so nothing here submits the app for review.
upload_to_testflight(
api_key: key,
skip_waiting_for_build_processing: true,
skip_submission: true,
)
end
end