mirror of
https://github.com/status-im/status-mobile.git
synced 2025-02-03 20:35:32 +00:00
fastlane: Create temporary Keychain for iOS signing
This is a new approach to signing the iOS app by using a temporary Keychain created only for that specific build and unlocked in advance. By doing it this way we can avoid issues with `errSecInternalComponent` appearing when there is no UI to open a Keychain password prompt when running build in CI. I've described this problem in details in: https://github.com/fastlane/fastlane/issues/15185 Thanks to `codesign:` partition ID being added to key partition list by Fastlane `match` when importing a Keychain this approach now works: https://github.com/fastlane/fastlane/pull/17456 Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
parent
d8eb33e330
commit
3b780f4ff2
@ -1,4 +1,4 @@
|
||||
library 'status-react-jenkins@v1.2.5'
|
||||
library 'status-react-jenkins@v1.2.6'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
@ -1,4 +1,4 @@
|
||||
library 'status-react-jenkins@v1.2.5'
|
||||
library 'status-react-jenkins@v1.2.6'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
@ -1,4 +1,4 @@
|
||||
library 'status-react-jenkins@v1.2.5'
|
||||
library 'status-react-jenkins@v1.2.6'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos-xcode-11.5' }
|
||||
|
@ -1,4 +1,4 @@
|
||||
library 'status-react-jenkins@v1.2.5'
|
||||
library 'status-react-jenkins@v1.2.6'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
|
@ -1,4 +1,4 @@
|
||||
library 'status-react-jenkins@v1.2.5'
|
||||
library 'status-react-jenkins@v1.2.6'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
@ -1,4 +1,4 @@
|
||||
library 'status-react-jenkins@v1.2.5'
|
||||
library 'status-react-jenkins@v1.2.6'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
@ -11,18 +11,6 @@
|
||||
# There are a few env variables defined in the .env file in
|
||||
# this directory (fastlane/.env)
|
||||
|
||||
# unlocks keychain if KEYCHAIN_PASSWORD variable is present
|
||||
# (to be used on CI machines)
|
||||
def unlock_keychain_if_needed
|
||||
return unless ENV['KEYCHAIN_PASSWORD']
|
||||
|
||||
unlock_keychain(
|
||||
path: 'login.keychain',
|
||||
password: ENV['KEYCHAIN_PASSWORD'],
|
||||
set_default: true
|
||||
)
|
||||
end
|
||||
|
||||
def curl_upload(url, file, auth, conn_timeout = 5, timeout = 60, retries = 3)
|
||||
rval = sh(
|
||||
'curl',
|
||||
@ -81,6 +69,38 @@ def upload_to_saucelabs(file)
|
||||
end
|
||||
end
|
||||
|
||||
# Helper which acts like a Python context manager
|
||||
def with(ctx)
|
||||
yield ctx.setup
|
||||
ensure
|
||||
ctx.teardown
|
||||
end
|
||||
|
||||
# Creates temporary keychain for build duration
|
||||
class Keychain
|
||||
attr_accessor :name, :path, :pass
|
||||
|
||||
def initialize(name)
|
||||
# We use epoch time to void clashes with CI builds
|
||||
@name = "#{name}_#{Time.now.to_f}.keychain-db"
|
||||
@path = "~/Library/Keychains/#{@name}"
|
||||
@pass = rand().to_s
|
||||
Fastlane::Actions::CreateKeychainAction.run(
|
||||
name: @name,
|
||||
password: @pass,
|
||||
unlock: true,
|
||||
# Lock it up after 25 minutes just in case we don't delete it.
|
||||
timeout: 1500,
|
||||
# To make Fastlane import WWDR certificate into it.
|
||||
default_keychain: true,
|
||||
)
|
||||
end
|
||||
|
||||
# for use in with()
|
||||
def setup; self end
|
||||
def teardown; Fastlane::Actions::DeleteKeychainAction.run(name: @name) end
|
||||
end
|
||||
|
||||
# builds an ios app with ad-hoc configuration and put it
|
||||
# to "status-ios" output folder
|
||||
# `readonly`:
|
||||
@ -95,30 +115,33 @@ def build_ios_adhoc(readonly: false, pr_build: false)
|
||||
scheme = pr_build ? 'StatusImPR' : 'StatusIm'
|
||||
app_id = pr_build ? 'im.status.ethereum.pr' : 'im.status.ethereum'
|
||||
|
||||
match(
|
||||
type: 'adhoc',
|
||||
force_for_new_devices: true,
|
||||
readonly: readonly,
|
||||
app_identifier: app_id,
|
||||
keychain_name: 'login.keychain'
|
||||
)
|
||||
with Keychain.new('adhoc') do |kc|
|
||||
match(
|
||||
type: 'adhoc',
|
||||
readonly: readonly,
|
||||
app_identifier: app_id,
|
||||
force_for_new_devices: true,
|
||||
keychain_name: kc.name,
|
||||
keychain_password: kc.pass
|
||||
)
|
||||
|
||||
build_ios_app(
|
||||
scheme: scheme,
|
||||
workspace: 'ios/StatusIm.xcworkspace',
|
||||
configuration: 'Release',
|
||||
clean: true,
|
||||
export_method: 'ad-hoc',
|
||||
output_name: 'StatusIm',
|
||||
output_directory: 'status-ios',
|
||||
export_options: {
|
||||
signingStyle: 'manual',
|
||||
provisioningProfiles: {
|
||||
"im.status.ethereum": "match AdHoc im.status.ethereum",
|
||||
"im.status.ethereum.pr": "match AdHoc im.status.ethereum.pr"
|
||||
build_ios_app(
|
||||
scheme: scheme,
|
||||
workspace: 'ios/StatusIm.xcworkspace',
|
||||
configuration: 'Release',
|
||||
clean: true,
|
||||
export_method: 'ad-hoc',
|
||||
output_name: 'StatusIm',
|
||||
output_directory: 'status-ios',
|
||||
export_options: {
|
||||
signingStyle: 'manual',
|
||||
provisioningProfiles: {
|
||||
"im.status.ethereum": "match AdHoc im.status.ethereum",
|
||||
"im.status.ethereum.pr": "match AdHoc im.status.ethereum.pr"
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# builds an ios app with e2e configuration and put it
|
||||
@ -128,34 +151,37 @@ def build_ios_e2e
|
||||
showsdks_output = sh('xcodebuild', '-showsdks')
|
||||
simulator_sdk = showsdks_output.scan(/iphonesimulator\d\d?\.\d\d?/).first
|
||||
|
||||
match(
|
||||
type: 'adhoc',
|
||||
force_for_new_devices: true,
|
||||
readonly: true,
|
||||
keychain_name: 'login.keychain'
|
||||
)
|
||||
with Keychain.new('adhoc') do |kc|
|
||||
match(
|
||||
type: 'adhoc',
|
||||
readonly: true,
|
||||
force_for_new_devices: true,
|
||||
keychain_name: kc.name,
|
||||
keychain_password: kc.pass
|
||||
)
|
||||
|
||||
build_ios_app(
|
||||
# Creating a build for the iOS Simulator
|
||||
# 1. https://medium.com/rocket-fuel/fastlane-to-the-simulator-87549b2601b9
|
||||
sdk: simulator_sdk,
|
||||
destination: 'generic/platform=iOS Simulator',
|
||||
# 2. fixing compilations issues as stated in https://stackoverflow.com/a/20505258
|
||||
# it looks like i386 isn't supported by React Native
|
||||
xcargs: 'ARCHS="x86_64" ONLY_ACTIVE_ARCH=NO',
|
||||
# 3. directory where to up StatusIm.app
|
||||
derived_data_path: 'status-ios',
|
||||
output_name: 'StatusIm.app',
|
||||
# -------------------------------------
|
||||
# Normal stuff
|
||||
scheme: 'StatusIm',
|
||||
workspace: 'ios/StatusIm.xcworkspace',
|
||||
configuration: 'Release',
|
||||
# Simulator apps can't be archived...
|
||||
skip_archive: true,
|
||||
# ...and we don't need an .ipa file for them, because we use .app directly
|
||||
skip_package_ipa: true
|
||||
)
|
||||
build_ios_app(
|
||||
# Creating a build for the iOS Simulator
|
||||
# 1. https://medium.com/rocket-fuel/fastlane-to-the-simulator-87549b2601b9
|
||||
sdk: simulator_sdk,
|
||||
destination: 'generic/platform=iOS Simulator',
|
||||
# 2. fixing compilations issues as stated in https://stackoverflow.com/a/20505258
|
||||
# it looks like i386 isn't supported by React Native
|
||||
xcargs: 'ARCHS="x86_64" ONLY_ACTIVE_ARCH=NO',
|
||||
# 3. directory where to up StatusIm.app
|
||||
derived_data_path: 'status-ios',
|
||||
output_name: 'StatusIm.app',
|
||||
# -------------------------------------
|
||||
# Normal stuff
|
||||
scheme: 'StatusIm',
|
||||
workspace: 'ios/StatusIm.xcworkspace',
|
||||
configuration: 'Release',
|
||||
# Simulator apps can't be archived...
|
||||
skip_archive: true,
|
||||
# ...and we don't need an .ipa file for them, because we use .app directly
|
||||
skip_package_ipa: true
|
||||
)
|
||||
end
|
||||
|
||||
zip(
|
||||
path: 'status-ios/Build/Products/Release-iphonesimulator/StatusIm.app',
|
||||
@ -181,7 +207,6 @@ platform :ios do
|
||||
desc 'It creates an .ipa that can be used by a list of devices, registeded in the App Store Connect.'
|
||||
desc 'This .ipa is ready to be distibuted through diawi.com'
|
||||
lane :adhoc do
|
||||
unlock_keychain_if_needed
|
||||
build_ios_adhoc(readonly: true)
|
||||
end
|
||||
|
||||
@ -189,47 +214,48 @@ platform :ios do
|
||||
desc 'This lane is used for SauceLabs end-to-end testing.'
|
||||
desc 'It creates an .app that can be used inside of a iPhone simulator.'
|
||||
lane :e2e do
|
||||
unlock_keychain_if_needed
|
||||
build_ios_e2e
|
||||
end
|
||||
|
||||
desc '`fastlane ios pr` - makes a new pr build'
|
||||
desc 'This lane builds a new adhoc build and leaves an .ipa that is ad-hoc signed (can be uploaded to diawi)'
|
||||
lane :pr do
|
||||
unlock_keychain_if_needed
|
||||
build_ios_adhoc(pr_build: true)
|
||||
end
|
||||
|
||||
desc '`fastlane ios nightly` - makes a new nightly'
|
||||
desc 'This lane builds a new nightly and leaves an .ipa that is ad-hoc signed (can be uploaded to diawi)'
|
||||
lane :nightly do
|
||||
unlock_keychain_if_needed
|
||||
build_ios_adhoc()
|
||||
end
|
||||
|
||||
desc '`fastlane ios release` builds a release & uploads it to TestFlight'
|
||||
lane :release do
|
||||
match(
|
||||
type: 'appstore',
|
||||
readonly: true,
|
||||
app_identifier: 'im.status.ethereum',
|
||||
keychain_name: 'login.keychain'
|
||||
)
|
||||
with Keychain.new('adhoc') do |kc|
|
||||
match(
|
||||
type: 'appstore',
|
||||
readonly: true,
|
||||
app_identifier: 'im.status.ethereum',
|
||||
keychain_name: kc.name,
|
||||
keychain_password: kc.pass
|
||||
)
|
||||
|
||||
build_ios_app(
|
||||
scheme: 'StatusIm',
|
||||
workspace: 'ios/StatusIm.xcworkspace',
|
||||
configuration: 'Release',
|
||||
clean: true,
|
||||
export_method: 'app-store',
|
||||
output_directory: 'status-ios',
|
||||
include_symbols: false,
|
||||
export_options: {
|
||||
"combileBitcode": true,
|
||||
"uploadBitcode": false,
|
||||
"ITSAppUsesNonExemptEncryption": false
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
build_ios_app(
|
||||
scheme: 'StatusIm',
|
||||
workspace: 'ios/StatusIm.xcworkspace',
|
||||
configuration: 'Release',
|
||||
clean: true,
|
||||
export_method: 'app-store',
|
||||
output_directory: 'status-ios',
|
||||
include_symbols: false,
|
||||
export_options: {
|
||||
"combileBitcode": true,
|
||||
"uploadBitcode": false,
|
||||
"ITSAppUsesNonExemptEncryption": false
|
||||
}
|
||||
)
|
||||
upload_to_testflight(
|
||||
ipa: 'status-ios/StatusIm.ipa',
|
||||
skip_waiting_for_build_processing: true
|
||||
|
Loading…
x
Reference in New Issue
Block a user