How to setup CI/CD for iOS with Github Actions and Fastlane
Based on the setup used by several teams in Axel Springer
Our Goal
1. automatically run Unit Tests for each pull request
2. potentially deploy a new build to TestFlight whenever pull request is merged
If you prefer video, watch the one above ☝️
Here’s a quick diagram of how the process in the team might look like with this CI setup:
Let’s start!
Fork this repo and checkout to the start
branch.
It contains an empty SwiftUI app and 1 Unit Test.
Workflow
Now, let’s go to Visual Studio Code and create our first workflow yaml file:
Create .github/workflows/pullRequest.yml
file, with the following contents:
Each platform, in our case it’s Github Actions, has it’s own syntax, and it’s more important to understand the principles. Overall those config files are usually very easy to understand.
In the on
block we describe when we want to run the workflow, or what will trigger it. In out case it’s pull request against develop
branch.
workflow_dispatch
means that we want to be able to trigger the workflow manually on Github.
Each workflow consists of one or more jobs
. We have only one job called test
. Each job can also have one or many steps
in it.
Most of the actions names are self explanatory. Long story short, here’s what we do:
- Pull the repository code — we start with a clean state.
- Cancel previous runs — basically if we already running the same workflow from the same branch, we want to first cancel the old one, and only then start a new execution. We discard the result of the previous workflow.
- Install
XCode
- Install Ruby, Bundler and fastlane —
gem install bundler
andbundle install
are needed to install Bundler, that’s needed to manage ruby dependencies (kind of like SPM) and install all the gems (kind of like packages) that include fastlane. We will define theGemfile
later. But essentially all this installs fastlane. - Cache SPM Modules between workflow runs —to not fetch them over and over
Let’s now add .ruby-version
file to the root with the following line inside: 2.7.2
That’s it. Now we can push and see how it works, but the most important part is missing — the unit tests. To run them we will use fastlane
.
Fastlane
Let’s setup a simple fastlane project:
First of all we need to install fastlane locally, for it let’s create a Gemfile
(no extension) in the root folder:
Now please install ruby and Rubygems, there is a high chance that you already have them on your machine.
gem install bundler
in the Terminal. Now run bundle install
— it will read the Gemfile and install or update fastlane.
Okay let’s create the first fastlane file called Fastfile
inside Fastlane
folder:
Here we use scan — fastlane tool to run unit tests for iOS.
Now, obviously it’s not all it takes to run the test. We want to specify the project and the scheme among other things. Let’s create Fastlane/Scanfile
:
Please create .gitignore
to avoid committing build artefacts and test reports:
Okay, let’s test how the fastlane
works locally. In the terminal, from the root folder of the project, run:
fastlane unit_test
You’ll see the simulator running our tests! How exciting! Now we just have to do the same on the CI — Super easy!
Let’s go back to our workflow file pullRequest.yml
and finally add this at the end of the file:
We actually want to also use the cache, so change the lines above to:
Now let’s actually see if it works. Push the code!
And after a few minutes you’ll see beautiful green mark:
That’s it! 🥳