CICD — Build, Test, Ship — iOS Apps

By — Akshat Kukreti (Engineer, App Platform)

UC Blogger
Urban Company – Engineering
4 min readMay 27, 2020

--

Continuing from our first blog post on CI/CD for Android, this blog post describes how we automated our iOS app build and distribution process.

Manual iOS App Build and Distribution Process

Following sequence diagram describes the manual iOS app release process.

  1. Manually trigger build on development machine and wait: The build had to be triggered on the development machine. Important work had to be stopped for creating ad-hoc and release builds.
  2. Manually upload Dsyms to Crashlytics: After the archive was built, the Dsyms had to be extracted and uploaded to Crashlytics. This step could easily get skipped and later result in critical crashes not being identified.
  3. Manually upload IPA to AppStore: The IPA was exported from the Archive and uploaded to the AppStore.
  4. Wait for IPA processing to finish: After uploading the IPA, one had to wait for processing to finish. Only after the processing was done could the app be submitted for review.
  5. Submit the app for review

It is clear from the above diagram that a lot of developer intervention was required. This affected productivity as one had to keep jumping between one’s work and the release process. Also, being a manual process, there was scope for mistakes like forgetting to upload the Dsyms to Crashlytics.

Ad-hoc debug builds:

The ad-hoc debug build and distribution process was worse and involved several manual steps:

  1. Manual registration of test devices: Register new test devices on the developer portal. This is another step that could be easily missed would lead to frustration later on.
  2. Build scheme related changes: Edit the Xcode Debug scheme to build for all architectures and not just the active ones.
  3. Trigger app build and wait for it: This, like the Release process described above, would require busy waiting on the part of the developer.
  4. Manual distribution: We use Diawi for ad-hoc distribution. One had to manually create the Diawi install link and share the same on Slack/email.
  5. No tracking of test builds: TestFlight maintains all versions of your iOS app for the last 90 days. We didn’t have a similar system for test builds.

The process for building release and testing builds was quite different, and each had a lot of manual intervention. The next section describes how we created a unified automated process for managing the above scenarios.

Automated iOS Build and Distribution Process

The following section describes how we automated the iOS build and distribution process using Jenkins and Fastlane.

Our CI/CD setup for iOS has the following components:

  1. Jenkins running in an EC2 container.
  2. A Mac Mini connected to Jenkins via SSH tunnel since iOS apps require a Mac to build. The Mac Mini has Fastlane setup.

Fastlane is a Ruby wrapper over the Xcode command line that enables us to write scripts (lanes) for automating iOS app build, test, and release process. Build parameters are passed to the script via environment variables or by maintaining environment files using DotEnv.

Our Fastlane script takes care of the following tasks without any manual intervention:

  1. Cocoapod install.
  2. Build version change.
  3. Build app using automatic provisioning. We decided to go ahead with automatic provisioning because we didn’t want to maintain an extra repository for certificates and provisioning profiles. So far, we haven’t encountered any issues with Fastlane and code signing is working fine.
  4. Zip and upload Dsyms to Crashlytics.
  5. Upload IPA to App Store.
  6. Notify on Slack when the build has finished processing on the AppStore.
  7. Notify on Slack when the build and distribution process has succeeded/failed.

For ad-hoc distribution, our lane script takes care of the following steps:

  1. Register new devices on the developer portal.
  2. Create and share Diawi install links.
  3. Share Diawi install links on Slack or email.

Jenkins enables us to:

  1. Trigger manual builds with options such as build environment, build version, distribution medium, new UDIDs, tester emails and so on.
  2. Trigger the build via Gitlab web-hooks as explained in the previous blog post.

Through Jenkins and Fastlane, we were able to eliminate several manual steps involved in building and distributing our iOS apps, and remove busy waiting on the part of the developer.

About the author –

Akshat Kukreti is part of the app infrastructure team solving for developer happiness, efficient processes and tooling. A quiet person in office, he is quite the show stopper during offsites. He enjoys gaming in his spare time.

Sounds like fun?
If you enjoyed this blog post, please clap 👏(as many times as you like) and follow us (@UC Blogger) . Help us build a community by sharing on your favourite social networks (Twitter, LinkedIn, Facebook, etc).

You can read up more about us on our publications —
https://medium.com/uc-design
https://medium.com/uc-engineering
https://medium.com/uc-culture

https://www.urbancompany.com/blog/humans-of-urbanclap

If you are interested in finding out about opportunities, visit us at http://careers.urbancompany.com

--

--

UC Blogger
Urban Company – Engineering

The author of stories from inside Urban Company (owner of Engineering, Design & Culture blogs)