How to setup CI/CD for iOS with Github Actions and Fastlane

Based on the setup used by several teams in Axel Springer

Tim Dolenko
Axel Springer Tech
3 min readJul 14, 2022

--

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:

Pull Request / Feature Workflow Example

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 and bundle 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 the Gemfile 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! 🥳

--

--