Continuous Integration for iOS projects with Jenkins CI


At codecentric we are using a central Jenkins continuous integration server to build all our software modules automatically after every check in procedure. The status of all builds is permanantly visible for all employees through screens in the offices and beside the coffee machines. This gives us transperancy about all our software modules. All modules? – Oh well, at least about all our Java and Android modules. But what about all these tiny iOS applications? As iOS apps do not compile on our Linux based build server these modules abscond themselves from showing up on our build monitors.

This needs to be changed. This article is a step by step introduction showing you how to integrate iOS builds in an existing Jenkins CI build infrastructure. 

Definition of a new iOS Slave on Jenkins master

As a Jenkins master instance running on Linux is not able to build iOS projects we need to add a new Jenkins slave node running on MacOS as the first step.

To add a new slave node open up the “Manage Jenkins/Manage Nodes” screen on the Jenkins master and choose “New Node”. For our puposes we need to create a node of type “Dumb Slave” :

After that you have to add some more properties of the new slave:

The following fields are recommended:

  • Name
    unique name of the slave node, to keep it handy do not use blanks here
  • # of executors
    the number of builds prozessors the client should be able to instantiate
  • Remote FS root
    folder on the slave to store temporary files and workspaces. In case a relative path is specified it will be created from the working directory of the slave node (see “Starting and connection Jenkins slave” below)
  • Launch Method
    method used to start the slave instance. Please choose “Launch slave agents via Web Start”. When using this method the slave connects to the server using Java Web Start. The advantage of this approach is that the master does not need to know the slaves ip-address and you are able to use a client with a dynamic ip-address.

As the slave needs to be able to access the source code repository, you should specify all required environment variables and tool properties in the section “Node Properties”. These settings heavily depend on the configuration of your machine runnig MacOS and the version control system you are using:

Creating a new iOS job on Jenkins master

Prior to creating a new Job on you Jenkins master instance running iOS builds you need to install the  “XCode Integration Plugin”  which is available on the “Manage Jenkins / Manage Plugins” screen.  Please restart Jenkins after installing the plugin.

After the plugin has been installed successfully you have to create a new job of type “Free Style Software Project”:

For all your iOS builds it’s recommended to bind the build job to the iOS-Slave node you created earlier.  To do this choose the option “Restrict where this project can be run” from the properties of the build and enter the name of the iOS node in the field “Label Expression”:

Next step is to configure the properties of your source code repository in the “Source Code Management” section. Please keep in mind that the client running MacOS needs to be able to access the specified repository and make sure all required login credentials are provided.

Now you have to add the special build step invoking the iOS build on the slave. After installing the XCode Integration Plugin as mentioned earlier you are now able to choose the option “XCode” from the “Add build step” list.

For a very simple build containing just one Xcode project you only have to define two fields:

  • Configuration
    the name of the build configuration to use. You can get the correct name from the available build configurations in Xcode
  • Xcode Project Directory
    path to the folder containing the “.xcodeproj” project file. You have to specify a relative path starting at the root of the project you checked out from the source code management system.

After that please make sure the plugin is able to access the keychain on the slave. Therefore you have to check the option “Unlock Keychain” and specify the path to the keychain file and your password:

For more complex Xcode projects containing serveral modules organised in a workspace you have to specifiy the Xcode Workspace file and the scheme you want to use. To get all available schemes within a workspace just execute the command:

/usr/bin/xcodebuild -workspace yourworkspacefile.xcworkspace -list

on the command line on the slave node. All available options are described in detail on the wiki page of the Xcode plugin.

Enabling your Mac to act as a Jenkins slave

As a Jenkins slave we need a Mac with Xcode and an up to date Java runtime already installed. The software to enable this machine to act as a Jenkins slave node can easily be downloaded from the Jenkins Master. Just open up the url:


from within you browser or using “wget” from the command line and save the file “slave.jar” in a directory of your choice.

Starting and connecting Jenkins slave

The file slave.jar we downloaded earlier contains all the software needed to run a Jenkins slave node. To connect your slave node to the master you just need to specify the jnlpUrl of the Jenkins master to enable the slave to establish the connection and register itself at the master instance.
A slave with the name iOS-Slave can be connected and registered with the following command:

java -jar slave.jar -jnlpUrl http://jenkins_master_url/computer/iOS-Slave/slave-agent.jnlp

In case you used a different name in the node configuration of the master you just have to replace “iOS-Slave” in the above url. You can always get the correct jnlpUrl from the properties of your node in the Jenkins master (see: “Manage Jenkins/Manage Nodes/node_name”).
As soon as the slave node has been started successfully it gets a “connected” status on the node overview page in Jenkins master:

With this the iOS build job can be used in the exact same manner as all the other build jobs within the central Jenkins master instance. It’s also possible to archive build artifacts  so that “.ipa” files can be downloaded from Jenkins master. And, of course, it is possible to add the iOS build job to miscellaneous views.

So from now on our information radiator in the kitchen will show some additional green iOS builds. – What abour yours?


Lars Rückemann

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon


  • Nice post.

  • Thanks for the tutorial, was very helpful.

  • Thank you so much for the post, this is helps integrate our iOS apps to Jenkins CI. can i get some guidance on polling the code quality reports (checkStyle, findbugs …etc)

    Appreciate your inputs

    Shiva M

  • Nice post! Thanks a lot.

    Watch out with the URL in “Starting and connecting Jenkins slave”, it needs another slash on it if not a java URL parse error will appear.

    Thanks again!

  • November 4, 2014 von Houman

    Great article Lars. So in a nutshell, if the Jenkins server is running on a Linux machine, I could setup my own MacBookPro as a Jenkins.slave. Hence whenever I submit code from my Mac, Jenkins server would run the tests on my own laptop to see if the build is broken? Is this how it works?

    If my assumption is correct, each coder in the team requires to set his own Mac machine as a Jenkins.slave, is this correct?

    • Indeed you are able to setup your MacBook as a Jenkins slave. But it’s not required for every developer to set up his own. It’s totally sufficient to have one MacBook acting as a slave. Only if a single slave is always busy you may want to add more of them.

  • November 26, 2014 von Killian

    Hi Lars,

    Tried following your instructions here, but when building with the slave getting this error. Any ideas what might help?

    Building remotely on iOS-Slave in workspace /workspace/Test Project Failed to mkdirs: /workspace/Test Project

    • Hi Killian,

      have you already checked if the user which runs the jenkins slave process has permission to access this directory.
      Just try to create this directory manually and check again.


Your email address will not be published. Required fields are marked *