At Oak City Labs, we love our continuous integration (CI). In our world, CI means that we have a trusty assistant sitting in the shadows that watches for new additions to our code repository. Any updates get compiled, tested, packaged and shipped off for user consumption. If something goes wrong, the team is alerted immediately so we can get the train back on the tracks.
Let’s dive a little deeper at the toolset we use for CI. For iOS and Mac development, it might seem like a natural choice to use Xcode Server and we did, for a time. However, as our project load grew and our need for reliable automation increased, we found that Xcode Server wasn’t meeting our needs. We switched to TeamCity with very good results.
Xcode Server, after several years of evolution, has become a solid CI server and has some advanced features like integrated unit testing, performance testing and reporting. The great thing about Xcode Server is the integration right into Xcode. You don’t have to bounce out to a website to see the build status and any errors or failing tests link directly to your code. Unfortunately, that’s where Xcode Server runs out of steam. It doesn’t go beyond the immediate build/test cycle to handle things like provisioning profile management, git tagging, or delivery to the App Store.
Enter Fastlane. When we first adopted Xcode Server, Fastlane was in its infancy, only partially able to cover the iOS build cycle. In the years since, Fastlane has grown to be a full and robust set of automation tools that blanket the iOS and Mac build cycle, reaching far beyond the basic build/test routine. As Fastlane developed, we pulled more and more features into our CI setup. We built python scripts to integrate various Fastlane pieces with Xcode Server. Eventually, we were spending a good deal of time maintaining these scripts. Fastlane, on the other hand, handled all the maintenance internally, if we would embrace Fastlane fully. There were also some pieces we had built by hand (Slack integration, git tagging) that Fastlane included out of the box. It was clear that it was time to wholeheartedly jump on the Fastlane bandwagon to drive our automated build system.
One hiccup — Fastlane really wants to drive the whole build process. This is a great feature, but it means we can’t realistically do that from Xcode Server. We were already using TeamCity for CI with our other projects (Python, Angular, Android) and it seemed like a good fit. TeamCity is great at running and monitoring command line tools and now with Fastlane, our iOS and Mac builds are easily driven from the command line. Fastlane also creates TeamCity compatible output for tests, so our unit test reports are displayed nicely in the TeamCity dashboard.
Now that our build system is fully Fastlane-ed, we benefit from their rich library of plugins and utilities. It’s simple to compute a build number for each build and push that as a git tag. Success and errors are reported to the team via Sack. We can easily publish beta builds to Crashlytics and send production builds right to Apple’s App Store. Fastlane’s ‘match’ tool keeps our provisioning profiles synced across machines. There are even utilities to sync our DSYM files from iTunes Connect to our crash reporting service.
Having the CI for all our projects under the TeamCity roof also comes with some nice benefits. There’s a single dashboard that shows the status for all the projects. There’s one login system to manage. The TeamCity server queues all the builds, so if an Android project is building when an iOS project updates, the iOS build is queued until the Android project finishes. With separate CI servers before on a single machine, you might have projects building in parallel which push the memory and cpu limits of the build machine. Also, the artificially elongated build times could confuse the build server system that monitors build time.
Our fully automated iOS and Mac build configurations have been running in the TeamCity / Fastlane environment for almost a year now and we’re delighted with the results. The Fastlane team does such a great job keeping up with changes in Apple’s environment. On the few occasions that things have broken, usually due to changes on Apple’s end, Fastlane’s team has a fix almost immediately and a simple ‘gem update’ on our end sets everything right. Going forward, Fastlane and TeamCity are our tools of choice for continuous integration.