It's almost the end of 2019 - exactly 3 years after the U.S. presidential election and maybe America isn't made great again but we all need to admit that it was a pretty good electoral slogan. A company that I am working in used what made Ronald Reagan’s and Donald Trump’s campaigns successful and made its own motto: - "Appunite - Make software great again". What if you ask me what makes us create such high quality software? I would answer that it’s mostly people, but still "mostly" and not "only" because apart from hard work, there are always tools that help to achieve it. One of such tools is Continuous Integration system that we are using at Appunite to test and deploy our software every day, hour and minute. Today I would like to tell you a little story about CI infrastructure that I've been working on, which is used for building iOS applications.
When you think about CI, you probably imagine some magical system that schedules to run build on some physical computers. At Appunite, we use Gitlab CI, which is a natural way of continuous integration when using Gitlab as a source control tool. To make it clear, let me show you the simplest possible Gitlab CI setup:
As you can see, there are 3 components required:
Back in 2017, when I joined the company, the CI setup looked more or less like this:
Our CI fleet consisted of 6 Mac Mini's.
Each of those machines had some macOS installed, a specific Xcode version (we are a software house and build many projects under different Xcode versions), and of course a software that communicates between that machine and the main Gitlab service.
This software is represented by Go
language mascot because it is written in Go.
If you are interested in reviewing its source code, you should visit gitlab runner repo.
While this setup looks pretty simple - we can build concurrently on 6 different computers with different Xcode versions - there is actually nothing more positive than I can say about it. As you may guess - we soon started to suffer from many different problems that tend to interfere with our every-day work:
Well, having such problems caused, we wasted a lot of time with every Xcode release and spent dozens of hours debugging every user issue.
Our previous setup was flexible enough to allow us to unplug one computer and start experimenting with it. We came up with something completely different - we started virtualizing macOS with Xcode. A single machine instance looked like this:
Now, gitlab-runner
is not running CI jobs directly on mac, but doing this through virtualization software (Virtualbox in this case).
With this setup, we have achieved several new benefits:
At the same time, we solved most of the problems from the previous architecture. We don't need to update macOS on computer but just on a virtualized instance and thanks to templates and backups and copying of images, we have no problems of unstable runs between days/computers. This saved us a lot of time after all and simplified the process of adding new versions of Xcode.
But when everything sounds so ideal, then, of course, new issues are on the way for us to face. What were the new issues that we faced after introducing the improvements above? This is what we’ll look into in the next article…