Continuous Integration at Scale for iOS

Gilles Grousset
inside|app
Published in
5 min readJan 14, 2020

[Version updated in 2023]

If you’re a professional iOS (or macOS) app developer, you probably use a continuous integration tool to automate testing, signing, and delivering your applications. However, those who have dealt with setting up and maintaining such a pipeline will tell you that continuous integration in the Apple world is not straightforward.

Continuous Integration

Continuous integration is like the conductor orchestrating the automation of repetitive technical tasks to save time and enhance the delivery process.

How It Works

A continuous integration platform generally follows a consistent structure:

The master server centralizes the parameters and triggers processes on appropriate runners.

Runners provide the environment required to execute requested processes. They consist of an OS and various additional tools for compiling, testing, analyzing, or deploying applications.

Each runner has a limited number of slots (the number of jobs it can process in parallel), determined based on its hardware capabilities (CPU, RAM, disk space).

To increase the processing capacity of continuous integration, you need to either upgrade the hardware or add more runners.

Types of Jobs

Continuous integration platforms typically operate at three levels during the development process:

  • Continuous compilation, which involves recompiling and retesting (including replaying unit tests) the entire application every time the codebase changes. This helps detect errors and regressions early.
  • Analysis, which involves periodic compilation, running all tests, and using various analysis tools to generate metrics related to the application’s quality (code, performance, security, etc.).
  • Delivery, which can be automated (publishing changes to a source code repository branch) or manual. It involves signing the application (a mandatory step for iOS app deployment, even for testing purposes) and publishing it on an app store or distribution platform for testers or end-users to access.

Continuous Integration for iOS

The steps described above are combined to create a typical continuous integration process for iOS, as illustrated below:

In addition to outlining the stages of continuous integration for iOS, this diagram details the tools typically used to perform the necessary processes. It’s apparent that Apple provides the bare minimum to build a continuous integration pipeline.

While other platforms (such as Android and web) offer build management/task runner tools to facilitate automation at each stage, iOS developers need to juggle several command-line tools (with some created by the community to fill the gaps) to achieve the same results.

Thus, setting up a complete and reliable continuous integration process for iOS is not simple, and it has direct implications for the choice of the continuous integration solution and its maintenance (updates, capacity increases).

Apple’s Solution: Xcode Cloud

Since 2022, Apple has offered its own integrated continuous integration solution within Xcode: Xcode Cloud.

This solution simplifies handling continuous integration tasks for Apple devices without leaving the Xcode environment.

Its advantages include being maintenance-free, requiring no DevOps skills, and having more competitive pricing than Bitrise.

However, it is less flexible than traditional continuous integration solutions and only caters to Apple devices, necessitating another CI system to handle other platforms.

Other Market Solutions

The number of continuous integration solutions continues to grow. These solutions can be categorized into three groups based on their iOS support capabilities:

Full Saas Solutions

These solutions allow you to outsource your entire Apple continuous integration pipeline (both the master and runners) to the cloud, eliminating hardware constraints and maintenance.

Examples: Bitrise, CircleCI.

On-Premises Solutions:

These are classic solutions where the entire pipeline is installed locally (both the master and runners). They provide full control but require heavier maintenance and the purchase of Macs to build your runners.

Examples: Jenkins, TeamCity.

Hybrid Solutions

Hybrid solutions are a mix of the previous two categories. They are SaaS offerings that don’t support Apple environments, requiring you to connect your Macs to access Apple support (the master and possibly Linux runners are offered as SaaS, but you can add specific runners as needed).

Example: GitLab CI (gitlab.com).

Choosing the Right Solution

Each solution has its advantages and disadvantages. Below is a summary table to help you make a more informed choice:

If you already have a continuous integration platform for other technologies like web (front-end or back-end), consider its ability to support mobile platforms, which can simplify maintenance and operation.

Multiple Runner Management

If you require multiple runners for continuous integration, you should consider using virtualization to streamline their management.

Complex Maintenance

When you have only one runner, it remains relatively simple. However, it’s highly likely that a single runner won’t suffice to handle all the requests promptly, especially last-minute delivery demands.

Beyond managing a single runner for iOS, maintenance time significantly increases because you’ll need to synchronize your scripts and tools on two different machines. This becomes a laborious and repetitive manual task, which can lead to disparities between your runners at the slightest deviation, resulting in unpredictable behavior in your continuous integration pipeline.

Automating Runner Management

To simplify, expedite, and enhance this maintenance process, most runners are structured as Docker containers. This format facilitates scripting the creation of environments, building them, and deploying them.

Unfortunately, Docker cannot containerize macOS…

The closest solution is therefore automatic provisioning of virtual machines using Vagrant and VirtualBox (or VMWare). Vagrant is a tool for scripting the creation of a virtual machine, meaning the installation of a base image including the operating system and additional tools.

VirtualBox and VMWare, on the other hand, are two virtualization solutions (capable of running virtual machines) available on macOS.

Certainly, this solution is heavier than Docker (with longer machine creation times, increased disk space usage, and reduced performance due to virtualization). Nevertheless, it retains the main benefit of ensuring the reliability and automation of machine/runner creation.

For your convenience, I’m providing a Vagrant script here that allows you to create a runner for GitLab CI with a single command. You’re free to enhance or modify it to suit your specific needs.

In Conclusion

Continuous integration is a crucial tool for mobile app development in a professional environment. It’s important to consider the available solutions to build a platform that meets your requirements and constraints. Maintenance efforts for your continuous integration platform should not be underestimated, as it requires continuous updates to incorporate new features and support the latest compilation tools.

Setting up continuous integration for iOS can be relatively complex depending on your environment. Moreover, it requires Mac machines to function. If your continuous integration needs lead to setting up multiple iOS runners, consider using virtualization to simplify their management.

Note that I have intentionally focused on iOS continuous integration in this article.

--

--