Continuous integration is a hugely important process in a modern software team. A good software team should have automated tests. A good software team should run these tests frequently. A good software team should ensure that the project keeps building and tests keep passing. There are lots of tools out there to help us achieve these goals but the one I’m going to talk about is Xcode Server. Whilst not the most popular tool, Xcode Server is incredibly quick to get up and running. This isn’t a tutorial about how to get started with your build server; instead, we’re going to look at how to speed up your Xcode Server build pipeline.
Xcode Server is a very simple tool to set up and has a unique way of keeping a clean copy of source code and derived data when running integrations but has disadvantages. The biggest is that every time we create a new bot, Xcode Server downloads the entire code base from your remote repository. But all is not lost; it is very simple to overcome this problem to create lightning fast integrations.
I’ve written ‘Xcode Server’ a few times already so to spare my word count I’m going to use ‘XCS’ instead.
XCS works in a different way to many other build tools. Every bot contains its own copy of the source code and its own derived data. The advantage of this approach is that consecutive integrations have the ability to run very quickly and reliably, often without the necessity of cleaning the build every time. When running automated test suites we want quick feedback; ideally, we don’t want multiple builds to be queued on the server so we need these integrations to be lightning fast. One flaw with the XCS approach is that if you have a remote repository, such as one hosted by GitHub, your integration can take a long time to check out your code. Depending on your project size and Internet connection this can take 5 minutes to half an hour or beyond. (My current project took 30 minutes just to download the source code!)
To get the best of both worlds you can use XCS to host a repository on your server which will speed up your download time from minutes to seconds. But we don’t usually want our build server to be the single point of truth for our source code. We’d like to take advantage of features found on GitHub and BitBucket such as pull requests and perhaps even issue tracking. The good news is that leveraging the power of git we can simply, quickly, and automatically keep our remote and XCS repository in sync.
First thing we need is a repository hosted by XCS. There are a few different ways to do this. The most simple way is to directly create a repository in the Server app. See “Create Git Repositories in OS X Server Running Xcode Server and Access Them from Your Development Mac”.
Once set up, we can then add our new XCS repository as one of our remotes:
git remote add xcs https://my-server.local/git/my_project.git
All you need now is to keep the XCS repository in sync with your remote:
git fetch –prune # download the latest code from your default remote repository.
git push –prune xcs +refs/remotes/origin/*:refs/heads/* # push the remote branches to the XCS repository and remove any branches that no longer exist.
After running these commands your XCS repository branches are identical to the branches on your remote repository.
This set up has reduced the time it takes to download code, run tests, and distribute the build to under 4 minutes! In the future I would like to improve this process by tracking new and deleted branches to support automatic synchronisation and bot creation but that will be a topic for another day.
If you’re new to Xcode Server check out these really great tutorials by Honza Dvorsky.