Code Signing for iOS Projects#
This guide describes how to set up code signing in CI/CD for your iOS project on Semaphore using Fastlane Match.
If you'd like Semaphore to push new builds for distribution to HockeyApp, Fabric Beta, or TestFlight, then CI must have access to the code signing certificate and provisioning profiles that are required to build the app for such distribution.
Follow the steps below to set it up.
Basic configuration of iOS projects#
For this setup, we assume you have a working iOS project configured to run on Semaphore. If you're new to Semaphore or not sure how to configure your iOS project, see the open source demo project and associated tutorial.
In addition, we assume that you have installed and configured Fastlane. If not, please visit the Fastlane setup guide to learn how to configure Fastlane for your project.
If you are new to code signing, we recommend you to visit the Code Signing Guide and read it.
The Match tool has extensive documentation on its use and configuration, which you can find at Fastlane Docs.
What you need for this tutorial is shown below:
- Your iOS project must be configured with Fastlane and Match.
- You need to have a separate private Git repositories that store code signing certificates and provisioning profiles.
- Your CI/CD project on Semaphore must be connected to these two repositories.
Setting up Fastlane Match#
Before setting up provisioning profiles and distributing builds, you need an App ID for your app and an App Store Connect application. If you don't have them yet, you can either create them manually in the Apple developer account and App Store Connect website, or you can use Fastlane's produce
action to create both from the command line.
Once you have your App ID and App Store Connect Application, you can proceed to configuring code signing for your project.
To set up match
, you'll need a private Git repository.
Follow the documentation and run the init
command from the root
directory of your iOS project, and then follow the prompts:
$ bundle exec fastlane match init
This will configure match
with your private Git URL and password locally on your computer. You are now ready to create provisioning profiles for your app.
The following will generate a 'development' provisioning profile so that you can run your app on a device connected to Xcode:
$ bundle exec fastlane match development
You can generate an 'adhoc' provisioning profile so that other people can run your app on their devices via a non-App Store distribution like HockeyApp or Fabric Beta with the command shown below:
$ bundle exec fastlane match adhoc
You can generate an 'appstore' provisioning profile so that your app can be distributed through TestFlight and the App Store with the command shown below:
$ bundle exec fastlane match appstore
Preparing your Xcode project for use with Fastlane Match#
By default, the Xcode employs "automatic" code signing that uses Xcode's preferences to manage the signing of certificates and provisioning of profiles. While this works on your local computer, it won't work in the CI environment. That's why the project should be switched to "manual" code signing.
To do this, in the "General" tab of your app target in Xcode, uncheck "Automatically manage signing" and select the provisioning profiles generated by match for each "Provisioning Profile" dropdown menu and for each configuration (Sections "Signing (Debug)" and "Signing (Release)").
Adding the Semaphore Plugin to Fastlane#
In order to configure Fastlane for the CI/CD environment, please install the Semaphore plugin with the command shown below:
$ bundle exec fastlane add_plugin semaphore
The plugin provides the setup_semaphore
action that configures a temporary Keychain and switches match
to 'readonly' mode.
Adding Match to a Fastlane Lane#
As mentioned earlier, CI doesn't have access to your developer account unless you provide the credentials in the configuration for match
. To make this work, we need to add a match
action to the lanes that will publish your app for distribution.
# fastlane/Fastfile
default_platform(:ios)
platform :ios do
before_all do
setup_semaphore
end
desc "Build and run tests"
lane :test do
scan
end
desc "Ad-hoc build"
lane :adhoc do
match(type: "adhoc")
gym(export_method: "ad-hoc")
end
desc "TestFlight build"
lane :build do
match(type: "appstore")
gym(export_method: "app-store")
end
end
Adding a deploy key to the Semaphore project#
Now that we have configured our tools to use the appropriate configuration, we must also provide a way for Semaphore to access your Git certificates repo and the Apple Developer portal.
To allow Semaphore to download certificates from your private certificates repository, you need to create a deploy key and add it to Semaphore secrets. Adding a deploy key is described in the Using private dependencies documentation.
If you have not installed the sem
command line tool, this is a good time to install it. See the sem reference documentation.
To store the deploy key as a secret file in the Semaphore environment, enter the command shown below:
$ sem create secret ios-cert-repo -f id_rsa_semaphore:/Users/semaphore/.keys/ios-cert-repo
Mounting the ios-cert-repo
secret in your pipeline configuration will create the deploy key file in the ~/.keys
directory when your CI/CD jobs run on Semaphore.
For an introduction to secrets on Semaphore, see the guided tour on secrets.
Adding a Match passphrase to a secret#
Next, add the URL for the certificates repository and the encryption password as environment variables that will be accessible in CI. We also recommend adding the App Store developer account's credentials to the same secret:
$ sem create secret fastlane-env \
-e MATCH_GIT_URL="<your ssh git url>" \
-e MATCH_PASSWORD="<password for decryption>" \
-e FASTLANE_USER="<App Store developer's Apple ID>" \
-e FASTLANE_PASSWORD="<App Store developer's password>"
⚠️ As a security note, it is highly advisable to create a separate App Store "developer" account that will only be used in the CI/CD environment. The same approach is advisable for accessing your private Git certificates repository.
In a similar fashion, you can also add API keys for any other distribution platform that you use, such as HockeyApp or Fabric Beta. Consult with the respective platform's documentation to see which environment variables and secrets you need to include.
With your secrets and configuration in place, Semaphore will be able to access code signing certificates and provisioning profiles in order to build and distribute your app in your CI/CD workflow.
Sample configuration files#
After you have configured Match, Fastlane, and environment variables, you are ready to build your app on Semaphore. The following are examples of the 'Fastfile' and semaphore.yml
configuration files that will run, test, and build on every code push.
For Fastlane:
# fastlane/Fastfile
default_platform(:ios)
platform :ios do
before_all do
# install the semaphore plugin with `fastlane add_plugin semaphore`
setup_semaphore
end
desc "Run Tests"
lane :test do
scan
end
desc "Build"
lane :build do
match(type: "appstore")
gym(export_method: "app-store")
end
desc "Ad-hoc build"
lane :adhoc do
match(type: "adhoc")
gym(export_method: "ad-hoc")
end
end
For Semaphore:
# .semaphore/semaphore.yml
version: v1.0
name: Semaphore iOS example
agent:
machine:
type: a1-standard-4
os_image: macos-xcode14
blocks:
- name: Run tests
task:
env_vars:
- name: LANG
value: en_US.UTF-8
prologue:
commands:
- checkout
- cache restore
- bundle install --path vendor/bundle
- cache store
jobs:
- name: Fastlane test
commands:
- bundle exec fastlane ios test
secrets:
- name: fastlane-env
- name: Build app
task:
env_vars:
- name: LANG
value: en_US.UTF-8
prologue:
commands:
- checkout
- cache restore
- bundle install --path vendor/bundle
jobs:
- name: Fastlane build
commands:
- chmod 0600 ~/.keys/*
- ssh-add ~/.keys/*
- bundle exec fastlane build
secrets:
- name: fastlane-env
- name: ios-cert-repo
Example application on GitHub#
To see how an iOS project can be configured on Semaphore, see the semaphore-demo-ios-swift-xcode
GitHub repository.