How to set up GitLab Continuous Integration for iOS projects without a hassle

Viktor Peschenkov
6 min readMar 19, 2018

How to make Gitlab-CI/CD & Fastlane integration when you have never worked with it?

We recently faced this challenge at Lodoss Team. In this beginner guide, I’ll share our step-by-step process, initial expectation, and the final result. So you will be able to configure GitLab-CI/CD & Fastlane by yourself with ease.

Why do we want Continuous Integration?

Everything should be done with purpose. We considered these necessary points for automation:

  • Auto running of Swiftlint
  • Improving the quality of a code
  • Decreasing amount of manual work
  • Auto running of UI & Unit-tests jobs

It’s not the full list of what we needed, however, it was a good point to start. In our work, we typically use the following GitFlow, and we used it to automate our CI/CD processes as well.

Here are sequence diagrams describing some successful cases of what we wanted to obtain:

Sequence for master branch using Gitlab-CI/CD
Sequence for develop, feature & release branches using Gitlab-CI/CD

Moreover, all those sequences are possible by using tags if we have a situation when it will be necessary (e.g. make an urgent build from a feature branch to show a new functional to a manager).

Why GitLab-CI?

We had GitLab and we couldn’t find any reason for using something else. So, we decided to use it, why not 😎? As for me, the GitLab-CI/CD is more developer-oriented than Jenkins. At least because it is aimed at the pipelines, tags, and branches, unlike Jenkins with jobs. And we have to use those things to get the necessary job instead of configuration without code. GitLab-CI/CD seems like a tool for running scripts on a remote machine; no more, but enough.

Some time later, we realized what it doesn’t matter what to use if we use Fastlane. Because it was able to do all what we needed. As the result, we got freedom from other tools. So I can strongly recommend using Fastlane instead of manual scripts or other approaches.

Why Fastlane?

Fastlane is the easiest way to automate beta deployments and releases for your iOS and Android apps. 🚀 It handles all tedious tasks, like generating screenshots, dealing with code signing, and releasing your application.

We decided to use Fastlane because it:

  • makes life better
  • reduces time to automate
  • has the clear documentation

Mentioned reasons also mean that it will be easy to learn for other developers in a team. And of course, simple processes are better than the complicated ones.

Setting Up GitLab-CI & Fastlane

Setting Up your Xcode project

  1. Create a new project in Xcode.
  2. Give a name to the project.
  3. Go to the projects schemes and turn the shared flag on like on the image below:

4. Push it into your GitLab repository.

So, the first stage is passed and we can go further.

Installing & Registering GitLab Runner

GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with GitLab CI, the open-source continuous integration service included with GitLab that coordinates the jobs.

GitLab has good documentation and you can easily investigate everything by yourself. Just follow these steps:

  1. Create a new user (Cocoapods cannot be run as a root user, you should start a runner as a specified one).
  2. Install a runner according to the installation instruction.
  3. Register the runner according to the instruction.
  4. Set working_directory in the/Users/gitlab-runner/.gitlab-runner/config.toml file as the root path to the runner user like this/Users/gitlab-runner.
  5. Stop & start the runner again.

Or by following the instruction for osx below:

  1. Download the binary for your system:
sudo curl --output /usr/local/bin/gitlab-runner

2. Give it permissions to execute:

sudo chmod +x /usr/local/bin/gitlab-runner

3. Register it by the following instruction there. And chose the executor as shell and add ios tag to it (the tags are optional, however, the code in the article uses ios tag for determination which runners will be chosen for performing a job but you can skip it).

4. Install the runner as a service and start it:

gitlab-runner install
gitlab-runner start

Example of config.toml file:

concurrent = 2[[runners]]
name = "The runner name"
url = "Your gitlab url"
token = "The runner token"
executor = "shell"
working_directory = "Path to user home directory"

If the actions were correct, the runner should look at GitLab page like on the image below:

Installing & Setting Up Fastlane

You can follow the official instruction to investigate the process by yourself (because true engineers prefer to find the right way by themselves 😂). Here I just share the source code of fastlane configuration file for a merge commit on the develop branch:

The script above uses swiftlint. So, please, don’t forget to install it to all machines with runner.

And by the way, you can use Gemfile file to install some awesome tools, e.g. cocoapods and others. We use the following:

source ""gem "fastlane"gem "cocoapods"

That approach allows you not to be worried about the absence of necessary applications on used machines.

Adding .gitlab-ci.yml

You can follow the official instruction to investigate the process by yourself (you know why, don’t you? 😉). Here I just share the source code of fastlane configuration file for a merge commit on develop branch:

Let’s come over descriptions of those jobs:

  • lint runs swiftling according to the rules in fastlane configuration file by push commit on any branch
  • tests run test according to the rules in fastlane configuration file by push commit on any branch
  • develop runs build according to the rules in fastlane configuration file by push commit/merge/tag only on develop branch

And before testing all of these, we should solve the next problem about Code Signing… I would recommend you to read the next article about that problem here and decide which way will be better for you. However, for the first time you can use the manual way of code signing, and after the number of runners will be more than one, it will be better to choose another way.

Also, if you wish to get notifications of fastlane jobs into your Slack, you can add SLACK_URL and FL_SLACK_CHANNEL to CI/CD Pipelines variables. So, at this point, our work is done and you can check the result of it by push commit on develop branch.


We built the great solution for automation of our needs. And, to sum up, it was the good choice to use Fastlane as a main tool. So, we got:

  • Better quality of a code
  • Auto running of Swiftlint checks
  • Auto running of UI & Unit-tests jobs
  • Decreasing amount of manual work
  • Auto builds delivering to QA Team & Client Team

Thank you for reading. I hope the article will be useful for you. Please, feel free to ask me if you have any questions :-)




Viktor Peschenkov

Passionate iOS developer, open source contributor, and gamer. Always looking for new challenges and ways to grow and improve |