Continuous Delivery for iOS using Fastlane and GitHub Actions
Prerequisites
Before continuing with the tutorial…
- Make sure you have Fastlane installed on your development machine.
- iOS developer program membership.
- Desire to read 😆…
Important about the price
https://github.com/features/actions
The service is ‘free’ up to the limit, depending on the chosen machine.
We are going to use a macOS machine, you can see in the screenshot its price and limits (prices as of the creation of the tutorial, they could undergo changes in the future)
🔴 Once warned of requirements and prices, if you like, we continue…
📣 In the post we assume that we have the app created in iTunes connect, we do have the certificates of the Apple ecosystem, everything will be copied by Fastlane!
Let’s go to the mess 🧑🏽💻
Steps to follow in the post
- Using App Store Connect API with Fastlane Match
- Requirements
- Creating an App Store Connect API Key
- Using an App Store Connect API Key
- Copy Fastline files
- Configure Fastlane matchs
- Configure Fastlane matchs
1. Using App Store Connect API with Fastlane Match
Starting February 2021, two-factor authentication or two-step verification is required for all users to sign in to App Store Connect. This extra layer of security for your Apple ID helps ensure that you’re the only person who can access your account.
From Apple Support
Getting started with match requires you to revoke your existing certificates. But no worry, you will have the new one directly.
Requirements
To be able to use App Store Connect API, Fastlane needs three things.
- Issuer ID.
- Key ID.
- Key file or Key content.
Creating an App Store Connect API Key
To generate keys, you must have Admin permission in App Store Connect. If you don’t have that permission, you can direct the relevant person to this article and follow the following instructions.
1 — Log in to App Store Connect.
2 — Select Users and Access.
3 — Select the API Keys tab.
4 — Click Generate API Key or the Add (+) button.
5 — Enter a name for the key. The name is for your reference only and is not part of the key itself.
6 — Under Access, select the role for the key. The roles that apply to keys are the same roles that apply to users on your team. See role permissions.
7 — Click Generate.
An API key’s access cannot be limited to specific apps.
The new key’s name, key ID, a download link, and other information appear on the page.
You can grab all three necessary information here.
<1> Issue ID.
<2> Key ID.
<3> Click “Download API Key” to download your API private key. The download link appears only if the private key has not yet been downloaded. Apple does not keep a copy of the private key. So, you can download it only once.
🔴 Store your private key in a safe place. You should never share your keys, store keys in a code repository, or include keys in client-side code.
Using an App Store Connect API Key
The API Key file (p8 file that you download), the key ID, and the issuer ID are needed to create the JWT token for authorization. There are multiple ways that these pieces of information can be input into Fastlane using Fastlane’s new action, app_store_connect_api_key
. You can learn other ways in Fastlane documentation. I show this method because I think it is the easiest way to work with most CI out there, where you can set environment variables.
Now we can manage Fastlane with the App Store Connect API key, great!
2. Copy Fastline files
Fastlane is a Ruby library created to automate common mobile development tasks. Using Fastlane, you can configure custom “lanes” which bundle a series of “actions” that perform tasks that you’d normally perform using Android studio. You can do a lot with Fastlane, but for the purposes of this tutorial, we’ll be using only a handful of core actions.
Create a Fastlane folder at the root of your project and copy the following files: Fastfile
Appfile
Configure Fastlane match
Fastlane match is a new approach to iOS’s code signing. Fastlane match makes it easy for teams to manage the required certificates and provisioning profiles for your iOS apps.
Create a new private repository named certificates
, for example on your GitHub personal account or organization.
Initialize Fastlane match for your iOS app.
Then select option #1 (Git Storage).
Assign the URL of the newly created repository.
Now you have inside Fastlane folder a file named Matchfile and
_git_url_
should be set to the HTTPS URL of the certificates repository. Optionally, you can also use SSH, but it requires a different step to run.
Next, we go to generate the certificates and enter your credentials when asked with Fastlane Match.
You will be prompted to enter a passphrase. Remember it correctly because it will be used later by GitHub Actions to decrypt your certificates repository.
If all went well, you should see something like that:
If you experienced any problem with GitHub and the necessary permissions, maybe this post will help you to generate authentication tokens for git.
Generated certificates and provisioning profiles are uploaded to the certificates repository resources
Lastly, open your project
in Xcode, and update the provisioning profile for the release configuration of your app.
Few things to note 💡
MATCH
For the CI/CD to import the certificates and provisioning profiles, it needs to have access to the certificates repository. You can do this by generating a personal access token (should be used before) that has the scope to access or read private repositories.
In GitHub, go to Settings → Developer Settings → Personal access tokens → click Generate New Token
→ tick the repo
scope → then click Generate token
.
Have a copy of the personal access token generated. You will use it later for the environment variable GIT_TOKEN
.
Then replace your match file generated in Fastlane folder by Matchfile
This will be used by GitHub Actions to import the certificates and provisioning profiles. And var will be set in GitHub Secrets, instead of hard-coding them in the file.
Build Processing
In GitHub Actions, you are billed based on the minutes you have used for running your CI/CD workflow. From experience, it takes about 10–15 minutes before a build can be processed in App Store Connect.
For private projects, the estimated cost per build can go up to $0.08/min x 15 mins = $1.2, or more, depending on the configuration or dependencies of your project.
If you share the same concerns for the pricing as I do for private projects, you can keep the skip_waiting_for_build_processing
to true
.
What’s the catch? You have to manually update the compliance of your app in App Store Connect after the build has been processed, for you to distribute the build to your users.
This is just an optional parameter to update if you want to save on the build minutes for private projects. For free projects, this shouldn’t be a problem at all. See pricing.
3. Setup GitHub Actions
Configure GitHub secrets
Ever wonder where the values of the ENV
are coming from? Well, it’s not a secret anymore – it’s from your project’s secret. 🤦
1. APP_STORE_CONNECT_TEAM_ID
- the ID of your App Store Connect team in you’re in multiple teams.
2. DEVELOPER_APP_ID
- in App Store Connect, go to the app → App Information → Scroll down to the General Information
section of your app and look for Apple ID
.
3. DEVELOPER_APP_IDENTIFIER
- your app’s bundle identifier.
4. DEVELOPER_PORTAL_TEAM_ID
- the ID of your Developer Portal team if you’re in multiple teams.
5. FASTLANE_APPLE_ID
- the Apple ID or developer email you use to manage the app.
6. GIT_USERNAME
& GIT_TOKEN
- Your git username and your personal access token.
7. MATCH_PASSWORD
- the passphrase that you assigned when initializing match, will be used for decrypting the certificates and provisioning profiles.
8. PROVISIONING_PROFILE_SPECIFIER
- match AppStore <YOUR_APP_BUNDLE_IDENTIFIER>
, eg. match AppStore com.domain.blabla.demo
.
9. TEMP_KEYCHAIN_USER
& TEMP_KEYCHAIN_PASSWORD
- assign a temp keychain user and password for your workflow.
10. APPLE_KEY_ID
— App Store Connect API Key 🔺Key ID.
11. APPLE_ISSUER_ID
— App Store Connect API Key 🔺Issuer ID.
12. APPLE_KEY_CONTENT
— App Store Connect API Key 🔺 Key file or Key content of .p8, check it
13. CERTIFICATE_STORE_URL
— The repo url of your Match keys (ex: https://github.com/***/fastlane_match.git)
4. Configure GitHub workflow file
Create a GitHub workflow directory.
Inside the workflow
folder, create a file named build-upload-ios.yml
and add the following.
This workflow should be triggered after each GitHub tag, if you need to automatize tag please, refer to Automatic build and release with GitHub actions first.
Then this workflow will pull your NodeJS deps, install them and build your JavaScript app.
Each time you send a new commit, a release will be built in TestFlight.
Your App doesn’t need to use Ionic, only Capacitor base is mandatory., it can have old Cordova module, but Capacitor JS plugin should be preferred.
5. Trigger workflow
Create a Commit
Make a commit, you should see the active workflow in the repository.
Trigger the workflow
Push the new commits to the branch main
or developement
to trigger the workflow.
After a few minutes, the build should be available in your App Store Connect dashboard.
Can deploy from local machine?
Yes, you can, and it is effortless.
Imagine that you have a private repository, and you have used up the minutes of the free plan and you do not want to pay for new releases, or maybe you prefer to submit the application manually.
Let’s go for it
Ok, first we need to create in my_project_path/fastlane path a file called .env, just in the same path as Fastfile, to be able to create the same secret properties found in our _GitHub, a_s below:
.env file for deploy from local machine
Now, you can go to the terminal and launch the Fastlane from your machine:
❌ Essential about the .env file, as we would rather not expose this data, we must add it in our .gitignore, something like that: ❌
It should work the same as it happens from GitHub Actions on the remote machine but in our local machine. 🍻
Terminal execution: $ Fastlane closed_beta
If you have come this far, my congratulations, now you have a fully automated process for your iOS apps with Fastlane and GitHub Actions.
Each time you send a new commit, a release will be built in Google Play console, beta channel. I will improve this blog with your feedbacks, if you have any question or suggestion, please let me know by email martin@capgo.app
Build on your device
If you still need to build on your device, you need to add them manually to the provisionning.
Connect your device to your mac and open the device menu
Then copy your identifier
And then start the command:
fastlane register_new_device
it will ask you to set a device name and the identifier:
if you got issues
If you have issue with dev device not able to test etc that usually fix it.
There a magic command who can save you:
Then : Clean the project by holding Shift(⇧)+Command(⌘)+K or selecting Product > Clean (it might be labelled “Clean Build Folder”)
Then try to run again the app on your device.
Thanks
This blog is based on the following articles: