How to setup Fastlane and Match to release iOS apps automatically on CI/CD server
By: Douglas Iacovelli
Tags: Matches, Ci, Continuous Delivery, iOS, Fastlane

Let's get our hands dirty

1. Creating the team account

When using Match, the whole idea is having a single Apple account which will generate and own the certificates. This could be your user, for example, but if you leave the company, then this would have to be changed so other employees could keep updating the certificates.

The recommended and best approach for this is inviting/creating a new Apple developer account to be shared among the team. I'll reference it from now on as ios-devs@yourcompany.com .

In our case we used a group email but this could be an e-mail of your organisation as well. Also mind that this e-mail must exist because you'll need to confirm it. As for the phone I recommend using someone's phone who thinks of staying in the company for a long time, but it can be changed in the future if you ever need.

https://appstoreconnect.apple.com/access/users

2. Choosing and creating the storage for the certificates

This is the source of truth where your certificates will be stored, where you'll update them and where your teammates and the CD server will fetch them.

Here, at Revelo, we use S3 storage but you can also use Git or Google Cloud at the time this article was written. I'll explain how to do it with GitHub below:

Create a private git repository and a user for our CD server on GitHub.

I recommend using the same e-mail address you used before, such as ios-devs@yourcompany.com . It's not mandatory to use the same e-mail, but it makes things easier to maintain.

This user should be added to the repository and given permission to read it.

You could have used your own user, for example, but then what if you leave the company? This user used on the CD server should not be affected by that.

Later we'll have to generate an API token for this user so it can authenticate on the CD.

3. Install Fastlane

I won't cover this topic because it's already well covered on the docs and there are many articles and videos explaining how to do that, but just make sure it's setup, running and you are ready to write some lanes.

4. Setup Appfile

The Appfile is created within the fastlane folder and it's a configuration file. You should set at least these configurations below so fastlane can get the certificates/provisioning profiles and upload it to Appstore.

team_name and team_id

Both can be found on Apple Developer membership

itc_team_name

This can be the same as the team_name

itc_team_id

This is the trickiest to get. I recommend visiting this stackoverflow question and trying any of the answers. Personally I used this answer and it worked flawlessly.

5. Setup match

On the project folder run

fastlane match init

It will ask you which storage you want to use. If you're following the tutorial from the beginning, select Git repo. If you’re using another storage option, then I recommend you to look Fastlane Match docs on how to set it up.

Then you can enter the git project url (prefer the git@... one if your machine is already using SSH for authenticating with GitHub).

This will just make things easier for now, thinking that you will write the tokens with your own account. Later on if you ever leave the company, it's just a matter of another person with write access to the repo run generate the tokens and update them by using match.

This will create a Matchfile on fastlane folder that should look like this:

This Matchfile is another configuration file with parameters that Match will use, but you could also set them via env vars or pass them as parameters of the functions we will call shortly.

6. Setup your environment variables

Just before that, I recommend that you use Dotenv gem at least for local development so you can make it easier for new developers who join the team to setup the environment more easily. However if you want to set them manually on your ~/.profile , it will work the same.

Go to your Gemfile and add this line:

gem "dotenv"

and run on the command line

bundle install

Now create a file inside the fastlane folder called .env.default and another one .env.default.sample . The sample one you should leave it like the file below and it can be committed to git. The other one should be filled with the environment variables that should not be committed, otherwise you risk exposing your keys and secrets. 👀

Fastlane will automatically load the .env.default file so it should be good.

6.1 Fill the environment variables for Match

For local development

MATCH_GIT_BASIC_AUTHORIZATION

Here every developer on the team can use one's own account. So if one's authenticated with SSH on git, then there's no need to fill this one:

MATCH_PASSWORD

This password will be used to encrypt/decrypt the certificates, so don't loose it. Every developer on your team must have it to download the certificates.

MATCH_USERNAME

This variable should be set with the e-mail of the Apple shared account used on the first step ios-devs@yourcompany.com . Usually there's no need for every developer to know this and its password, because it's simpler if only a few people can generate new certificates. Otherwise, every time someone leaves your team, then you'd have to change the password for this user.

*The last keys starting with APP_STORE_CONNECT_API_ I will cover later.

For CD

MATCH_GIT_BASIC_AUTHORIZATION

On CD server you should generate a personal access token for the team user we mentioned on step 2. For GitHub, follow these instructions and run this on your command line to get the base64 string you will store on this env var.

echo -n your_github_username:your_personal_access_token | base64

MATCH_PASSWORD

This password will be used to encrypt/decrypt the certificates, so don’t loose it.

MATCH_USERNAME

There's no need to set this on CD, because it will only fetch instead of generating new certificates.

7. Create a fastlane lane to sync the certificates

If Fastlane has already created a Fastfile inside of fastlane folder, then edit it to add the lanes below. Otherwise, create a new Fastfile and copy this:

The first lane :certificates is the one that your CD server must run. This is also useful when you and new developers want to get the newest certificates available.

The second lane :generate_new_certificates will update the certificates if needed. This could happen if they expire, are revoked or if a new device id is added to the list of devices on apple developers portal.

Note: Make sure to add a sync_code_signing method call for each of the types of certificates needed. The available types are development, adhoc and appstore. Don't forget to change the app_identifiers according to your app as well.

After that it is a good practice to revoke and erase the current certificates on the Apple developers portal before generating new ones with Match. Do this by running the command:

fastlane match nuke

Now run the command below to create and store the new certificates:

fastlane generate_new_certificates

When you run this command, it might ask the password and a 2 factor authentication code of the user you've created on the first step so it can log into Apple.

8. Change in Xcode the signing option

I assume you previously used automatic signing by Xcode. So you can now disable this check on every build type and scheme you have and select the appropriate provisioning profile that match created. It should start with match ... com.company.example depending on the type of build you are selecting.

For example, for development or profile build types, you should select the one that start with match Development com.company.example and for the release you should use match AppStore com.company.example (Thanks Mark Moes for pointing that out on the comments).

If an error appears, usually restarting Xcode solves it.

Everyone in your team should do the same.

9. We're almost done, let's get the Appstore Connect API key so our CI can release our app automatically

The Apple account holder of your team must do this step:

Visit the page https://appstoreconnect.apple.com/access/api

Generate a new API Key (make sure it's set to App Manager access)

You must collect three things: issuer_id , key_id and key itself (.p8) file .

These values you’ve just got ideally should stay only on your CD server, but you could also fill it in your local environment for testing. So let's continue filling the .env.default file. I also recommend not to share this with your team because of the same reason I told before: If this person leaves, security-wise it would be better to change revoke and generate a new API Key.

APP_STORE_CONNECT_API_KEY_KEY_ID

Fill this with the key_id you've just got.

APP_STORE_CONNECT_API_KEY_ISSUER_ID

Fill this with the key_issuer_id you've just got.

APP_STORE_CONNECT_API_KEY_KEY

For this option, you must convert your .p8 key to base64 so you can store it as a secret string in your CD server. You can do that by running this command which will copy your key as base64 string into your clipboard. Finally assign that to this env var.

openssl base64 < path/to/key.p8 | tr -d '

' | pbcopy

10. Update the Fastfile script to build the app and upload it to Appstore Connect

Make sure to change the app_identifier as well and the scheme .

Also mind the call to setup_ci . This fastlane action configures the keychain on the CI and a few other options. Locally this is not needed and it's not run by default, because you have your own keychain set up.

This should be enough for you to upload your app locally without having to open Xcode again. So if you want to run it on your CD server, just make sure you install Fastlane, set all your secrets and let them available for the Fastlane script to use. And then just run the command: