How to Automate iOS Project Delivery

ios device

Until recently there were not many great options for iOS developers when it came to continuous integration and continuous delivery. The job of archiving and distributing builds was often done manually by developers, a tedious and often time-consuming task, when developers should really be focused on coding features and fixing bugs. There is also the additional overhead of managing credentials like provisioning profiles and developer certificates. These tasks add up to a lot of yak shaving, and the context switching involved decreases productivity. Developers want to build great apps, not spend hours solving certificate errors.

Fortunately this is where a toolchain like Fastlane comes in. Created by Felix Krause, Fastlane is a tool for iOS, Mac, and Android developers to automate tedious tasks such as archiving builds, code-signing, managing provisioning profiles, and releasing applications. The automation of these processes allows developers to reclaim time lost on mundane tasks and get back to being productive.

Fastlane contains a host of tools that you can use as a whole (via a Fastfile) or individually on the command-line. Gym, for example, compiles and generates a signed ipa file. The Spaceship library connects to Apple Developer Center and iTunes Connect, serving as the foundation to manage provisioning profiles or handle uploading a release to the App Store. You can automate certificate management via Cert and even automate deployment of your iOS app to iTunes Connect with Deliver. Fastlane also supports app beta delivery providers like TestFlight, Fabric Betas, HockeyApp, and TestFairy.

Installing Fastlane is simple through Homebrew or Rubygems. Let’s say you’re working on an iOS app. The first step is to make sure the latest version of Xcode is installed, and then install Fastlane from the command-line:

$  xcode-select —install
$ sudo gem install fastlane -NV

With Fastlane installed you can now initialize it in your existing Xcode project. If you are starting fresh, you can initialize Fastlane in your project root.

$ fastlane init

Fastlane will prompt you for an Apple ID and then generate a configuration file and an application file, both of which will be contained in a fastlane directory. The Fastfile is a series of steps defined as 'lanes'. The Appfile contains additional metadata about your app and an Apple ID which can be reused in other configuration files for Fastlane tools, like a Snapfile.

While the Fastfile defaults are more than enough to handle beta testing and a full App Store release, there are a myriad of other options in the documentation to customize your Fastfile if desired. There are many examples of more advanced configurations published on the open source drivers of the project.

Below is a sample Fastfile:

# Customise this file, documentation can be found here:
# All available actions:
# can also be listed using the `fastlane actions` command

# Change the syntax highlighting to Ruby
# All lines starting with a # are ignored when running `fastlane`

# If you want to automatically update fastlane if a new version is available:
# update_fastlane

# This is the minimum version number required.
# Update this, if you use features of a newer version
fastlane_version "2.19.2"

default_platform :ios

platform :ios do
  before_all do
    # ENV["SLACK_URL"] = ""


  desc "Runs all the tests"
  lane :test do

  desc "Submit a new Beta Build to Apple TestFlight"
  desc "This will also make sure the profile is up to date"
  lane :beta do
    # match(type: "appstore") # more information:
    gym # Build your app - more options available

    # sh ""
    # You can also use other beta testing services here (run `fastlane actions`)

  desc "Deploy a new version to the App Store"
  lane :release do
    # match(type: "appstore")
    # snapshot
    gym # Build your app - more options available
    deliver(force: true)
    # frameit

  # You can define as many lanes as you want

  after_all do |lane|
    # This block is called, only if the executed lane was successful

    # slack(
    #   message: "Successfully deployed new App Update."
    # )

  error do |lane, exception|
    # slack(
    #   message: exception.message,
    #   success: false
    # )

# More information about multiple platforms in fastlane:
# All available actions:

# fastlane reports which actions are used
# No personal data is recorded. Learn more at

Fastlane uses Cocoapods for Xcode project dependencies as a default, and if there is a Podfile present it will use that to install any dependencies. There is also great support for chat clients like Slack built right in. When paired with a continuous integration service, Fastlane can notify your development team about the status of builds and releases. This is a great feature for transparency and accountability – in the case that someone breaks the build, you can figure out who has to buy the donuts.

There is a lot of flexibility with Fastlane. For the individual developer, installing and running locally with Fastlane will absolutely save time from the start. For the development team, the benefits of Fastlane are exponential when combined with continuous integration and delivery systems. Some common continuous integration options include Jenkins, Travis CI, Buddy Build, and TeamCity. Since Fastlane is a command-line tool, setting up continuous integration to use Fastlane can be as easy as adding a build step.

At Mad*Pow we use TeamCity for our continuous integration Since Xcode, Fastlane, and CocoaPods are required a separate Mac OS build host is used. The build host has a TeamCity build agent that communicates with a master TeamCity server. The server monitors source control on a 60 second interval looking for changes from developers. When a code change is identified, the master TeamCity server will begin orchestration of a build.

For example, let’s say a developer is working on a new feature for an app. Once the feature is developer-complete and ready for testing, the developer will merge the changes into a branch. The changes are then pushed to the remote repository where the master TeamCity server will detect the changes and begin to execute the steps for the build, as defined in Fastlane. These steps include:

  • Pulling down the most recent code changes from the remote repository
  • Downloading dependencies via CocoaPods
  • Compiling the source code
  • Running unit tests
  • Downloading provisioning profiles
  • Code-signing the application
  • Uploading the app to a beta testing platform such as TestFairy
  • Notifying testers that there is a new version available to download

Build Steps

When the build is ready for release, Mad*Pow uses TestFairy for distribution. TestFairy's Upload API allows for the automatic upload of builds directly from the build server. Once a build is uploaded, TestFairy can e-mail it to a distribution list of people who can upload it directly to their phones. Through this series of steps, the entire delivery process is automated; the release is successfully installed on devices without developer intervention. The automated process minimizes human error while maintaining high-quality standards, and, best of all, allows developers to focus on the work they enjoy.

Contributed by
Matt Teece
Job Title
Senior Developer