Achieving consistent and continuous delivery for iOS – Part 1: Simplify

Alain Stulz
5 min readOct 10, 2022

--

Since I started developing iOS apps professionally in 2015, the tooling for our projects has evolved dramatically. Back then, as a junior developer, I was handed the time-consuming task of building and uploading our projects to the App Store. As you might imagine, with an increasing number of projects, I quickly grew tired of this busy-work and started looking for better solutions.

Over the years, we went from building and exporting by hand, to deploying our projects fully automatically whenever it‘s necessary. This is the story of how continuous deployment evolved at Apps with love. We‘ll explore different tools in the order in which we started using them. Each technique builds on the ones that came before it, and unlocks new benefits, so the evolution is seamless and allows you to gradually improve your setup over time as well.

In case you aren‘t aware of CI/CD and why you should use it, please do read up on it as soon as possible! A good setup will save future you lots of time and frustration.

As a quick outline, we can divide our progress over the years into three steps:

  1. Simplify your builds
  2. Automate building and testing
  3. Standardize across all projects

Let‘s get started with the first part, simplifying the builds. Our tool of choice here is Fastlane. Perhaps the most widely used build scripting tool for iOS, this amazing open source project has saved developers in the Apple ecosystem thousands of hours and countless headaches. With it, you can create lanes, which are series of instructions to run. There are many actions available, which can be used to test, build and upload your projects.

Building with Fastlane

We first started using Fastlane in 2015. It helped us simplify the exporting of .ipa files from our Xcode projects. We set up a Gymfile in each project. This tells Fastlane which scheme to use, how it should be exported, and any other configurations, if necessary. Using ˋgymˋ meant that we no longer had to click through Xcode to export builds, instead we could do it from the terminal, which often saved a couple of minutes and was less error-prone because the requirements were already defined in the Gymfile.

Beating Code Signing with Match

As iOS developers, we’ve all faced the moment where we finally completed our first app. Then came the part of releasing, where you find out about the struggle that’s called Code Signing. It is often pretty annoying, especially if you have to create certificates and profiles manually in the Apple Developer portal. But once you multiply this effort by dozens of App Store teams and different projects, it grows to become a huge effort to keep track of everything.

We started by automating the generation of Code Signing assets using ˋfastlane sighˋ. This generated, downloaded and installed the required signing assets on the developer‘s machine before building the application. In a similar way, Xcode started supporting Automated Provisioning a few years ago. However, both share a major drawback – they don’t support easy collaboration.

One big reason why we used to have just one developer building and deploying our projects was that it used to be an absolute pain to share certificates and provisioning profiles between different machines.

For a while, we stored our profiles and certificates in Google Drive. But still, if one developer forgot to upload them or just couldn’t find them there, they would often simply create a new certificate and profile. This would break other dev’s workflows at best, and break builds delivered to clients at worst. (Also, yikes from a security standpoint, but hey, that‘s how it was done back then.)

Salvation came in the form of a new Fastlane tool called match. This takes your signing assets (certificates and profiles) and syncs them through an encrypted Git repository. We started adding match in all our projects and to this day it proves to be a huge time-saver and a foundational building block of our CI system.

We use a single repo for match, with a separate branch for each App Store team. We like to use one repo because we don‘t need scoped access for different teams. But if your scenario requires that, match also works with different repos or even S3 buckets.

Building for Multiple Environments

For basically any professional project, you will face the need to create different versions of your builds. Perhaps you have different staging and production environments. Or you have debug feature flags for developer builds. Or you want to deliver builds made from the develop branch to devs and QA, but builds from the main branch to your client as well.

Facing this challenge, we needed to reconsider storing our build configurations in Gymfile, Matchfile and so on. We soon moved all of our configurations to .env files and changed the other files to simply read from the environment. Creating the right build is now simply a matter of specifying the right environment:

fastlane release -env ent-staging

Deploying to Updraft

Many teams use TestFlight to distribute preproduction builds, and for certain testing scenarios (IAP is one) this is your only reliable option. For most of our projects, however, we prefer to share builds using our own custom tool, Updraft, which allows for easy distribution via E-Mail, Slack and MS Teams, without pre-registering your testing devices. And because we use it so often, we made our own custom Fastlane action, which grabs the .ipa file you exported with ˋgymˋ and delivers it to your testers via Updraft instantly. You can check out Updraft at getupdraft.com – it‘s free to use and also works for Android projects.

Other Tidbits

We have also experimented with other fastlane actions to improve our process. Things we perform using Fastlane include, in no particular order:

  • Linting with Swiftlint
  • Running tests and gathering coverage reports
  • Updating Cocoapods before building
  • Uploading DSYMs to Firebase Crashlytics
  • Incrementing the build number
  • Registering new test devices

As you can see, this tool is incredibly versatile; definitely something every iOS developer should know their way around.

The Story Continues…

Next time you‘ll learn how we get faster feedback and ensure that our testers and clients always have access to up-to-date builds while removing another manual step for our developers in favor of automation. Thank you for reading, I hope it was interesting. If you have any questions or suggestions, please write a comment. See you then!

Bonus

I wanted to share an example of a full Fastlane setup with you. This should give you an overview how everything fits together.

https://gist.github.com/ast3150/786c676e6c7639f9a5137cbd00cf33c6

--

--

Alain Stulz

I create various products (mostly iOS) at @appswithlove and am looking to reach new levels of technical excellence with our team of engineers.