From commit to Testflight – Part 1

Recently I have received several requests to explain how to automate iOS builds from checkin to Testflight.  Since I have been using Jenkins to automate iOS applications for almost 2 years, I feel like it is time to share.  In this series of posts I will explain how I automate my iOS projects to perform the following steps:

  • Compile the App and build an IPA file
  • Execute Clang scan-build and fail when leaks are detected
  • Execute copy-paste detection and fail when infractions are found
  • Execute GHUnit tests with code coverage and fail when tests fail
  • Generate AppleDoc documentation
  • Upload the IPA to Testflight with a proper build number and commit history


  • A Mac OSX computer to serve as a Jenkins server or Jenkins slave.  Must have Xcode installed.
  • iOS App source code accessible from a common source code control system such as Git, Subversion, Perforce, etc.
  • The ability to download and install open source software.
  • A Testflight account with a team already configured.


For those of you who are not familiar with Jenkins, it is an open-source continuous integration server.  Jenkins is written in Java but can be used to automate almost anything.  Jenkins is backed by a vibrant community of developers who continually contribute bug fixes and new plugins. If you have never setup Jenkins on a Mac, you should begin by running the Jenkins Mac OSX installer which can be found on the Jenkins home page.  If you plan to use a Windows or Unix machine as a Jenkins master, you will have to configure your Mac as a slave machine.

Once you have Jenkins installed and running, you should use the Jenkins update center to install all of the necessary plugins.  You can access the plugin update center by clicking ‘Manage Jenkins’ and then clicking ‘Manage Plugins’.  Next, go to the ‘Available’ tab and begin checking the plugins you wish to install. I have broken the plugins down by function below in order to help you figure out which ones you need to install:

New Freestyle Job

After you have installed all of the plugins for the features you wish to implement, you’ll need to create a new freestyle job in Jenkins which will perform the automation.  If you plan to automate more than one App you would create a freestyle job for each App.  Create your job by clicking ‘New Job’ in the upper left, providing a job name, and choosing the ‘Build a free-style software project’ option.  I recommend not using spaces in your job names because they can cause some scripts to function improperly.

Once you have created a freestyle job for your App, you should configure the Job to connect to your source control system and pull the source code to the Job’s workspace.  Open your Job in Jenkins and click on the ‘Configure’ link on the left to access build settings.  You can setup your source control in the ‘Source Code Management’ section.  If you do not see an option for your source control server you’ll need to go install a suitable plugin.  The Jenkins job configuration page also has a ‘Build Triggers’ section which will allow you to configure source code polling.  I usually enter something like ‘*/5 * * * *’ in the ‘schedule’ field so that Jenkins will poll my source control server for changes every 5 minutes.

After you have configured your Job to pull your source code you should execute a build by clicking ‘Build Now’ on the left side of the screen.  Jenkins should execute successfully (blue ball instead of red) and your source code should now be visible in the Job’s workspace.  You can confirm this by clicking the ‘Workspace’ link on the left side of the Job page.  If you see your code in the workspace you are ready to move onto the next step.  If you do not see your source code, try clicking on a failed build and viewing the console output for clues.

Compile the App and build an IPA

XCode Preferences - Downloads

A note for XCode 4.3 users:  Apple recently began distributing Xcode via the Mac App Store.  When Apple made this change they also split XCode into several separately installed components.  Many of the tools detailed in this post require the ‘XCode command line tools’ download.  You can install this download by opening Xcode on your build server and going to ‘Preferences’.  Once you have opened XCode preferences, click the ‘Downloads’ tab and install the ‘Command line tools’ download.  After the ‘Command line tools’ are installed you should test them by opening Terminal on your build server and execute the ‘xcodebuild’ command.  If you get an error stating that no /Developer directory could be found, execute the following command from Terminal: sudo xcode-select -switch /Applications/

The most basic Jenkins/iOS continuous integration system should at least compile the App.  This ensures that commits made by developers are not missing files which would cause headaches for the rest of the team.  There are currently two ways you can configure Jenkins to compile an iOS App.  You can either use xcodebuild directly from an ‘Execute Shell’ build step or use the SICCI for XCode plugin.  I have been using the SICCI for XCode plugin for about a year and have found that it is reliable and easy to use.  This guide will assume you are using the SICCI for XCode plugin.

The SICCI for Xcode plugin requires access to your XCode workspace/project so that it can list out the targets/schemes for your App.  Because of this, you will need to make sure that Jenkins is happily pulling your source code into the workspace before you move on with this step.  Once you have confirmed that your source code is being pulled properly, you will need to go to the job’s ‘Configure’ page.  On the Configure page locate and click the ‘Add Build Step’ button.  Once you click the ‘Add Build Step’ button you should see a popup with a list of build step types.  You should choose ‘SICCI for Xcode’.  Jenkins will add the SICCI for Xcode build step and you should see a list of the build targets in your project.  If you do not see your project folder and a list of build targets, your source code is probably not in the job’s workspace.

To have the SICCI for XCode plugin compile your App you should change the platform to ‘iOS’ and check the checkbox next to your App’s main target or scheme.  Once you check a target or scheme, the SICCI for XCode plugin will display several options.  You should check ‘clean before build’ and ‘create IPA’.  If you wish to have the SICCI for XCode plugin also zip up the App’s DSYM, you should also check ‘archive App’.

You may also wish to change the SICCI for XCode ‘Filename template’ to something more simple.  I usually use something like ‘AppName_<BUILD>’ where AppName is anything you want.  The <BUILD> token will be replaced automatically with the Jenkins build number during a build.  I also recommend that the you don’t use spaces in the ‘Filename template’.

Next, save your configuration changes by clicking the ‘Save’ button and run your Job by clicking the ‘Build Now’ link.  If your job passes, you are ready to move onto the next step.  If you job fails, you should click the failed job link on the left to view the job details page and then click the ‘Console Output’ link.  In order to see the entire console output you may need to click the ‘Raw’ link.

The job console will show the typical build output from xcodebuild and will show any compile errors that may have occurred.  If you still can’t figure out how to get your code to compile you should try running xcodebuild directly on your project from your local workspace using Terminal.

In the next part, I will explain how automate GHUnit tests in Jenkins.

About these ads

Published by


Software craftsman

10 thoughts on “From commit to Testflight – Part 1”

  1. Thanks for writing this up! Fantastic. I’ve been setting this same thing up lately for all my projects. Already learned a few things from this article.

    First, why so much love for GHUnit? I haven’t done much with it, but it gets a lot of love.

    1. To be honest I haven’t experimented with much outside of GHUnit. GHUnit includes built in support for outputting the xUnit XML format during headless test runs. This XML can be used by Jenkins to trend your pass/fail rate and fail the build when tests fail. I also like that the GHUnit tests target is compile into an App which allows me to run the tests manually and on the device.

  2. So does this work if you are pulling source code from source control? —meaning, how is the plugin keeping track of the build numbers? And if I am doing a force get every time I build, will this plugin be reusing the same build number?

    1. There are many different ways to handle the build numbers. I think the best way is to have your Jenkins job update your plist file before each build. I usually just insert the Jenkins build number into the plist so that the App version matches the build that compiled it.

  3. Hi,
    I have followed the steps but, Selecting “SICCI for Xcode” as a build step does nothing in my browser. Any suggestions?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s