Wednesday, September 12, 2012

Continuous Deployment for Mobile Apps with Jenkins: Xcode Builds with MacOS Slaves

At a recent meetup organized by the Silicon Valley Cloud Computing Group, Kohsuke, Matt Solnit of SOASTA and I did a demonstration of how to manage end-to-end continuous deployment for mobile app development using Jenkins CI, with everything managed in the cloud using CloudBees DEV@cloud PaaS service.

In this blog, I’ll walk you through the setup for the demo.  You can find the slides online at SlideShare here and the Jenkins configuration we used is available at For the demo, we showed how to configure Jenkins on CloudBees to manage the build, testing and deployment of the StockFish iOS chess app, as well as continuous deployment and integration testing with a set of back-end REST web services to record games and moves.  You can find the source code for both on GitHub: the front-end StockFish app ( and the back-end MongoChess server (

Configuring the GitHub Hook URL

First, let’s look at the setup for building and testing the iOS mobile application: you can see the configuration here.  As you can see from the Source Code Management section of the configuration, the build is triggered whenever a change is pushed to the GitHub repository: to do this, I simply have to enter my GitHub credentials at the bottom of the Jenkins System Configuration page and tell Jenkins to auto-manage hook URLs, like this:

You can see the hook URL by going to the Repository Administration tab on GitHub: click on Test Hook and then go to the Jenkins GitHub Hook Log and you should see confirmation of the trial push.

Running a MacOS Slave

Next we need to configure the Xcode build for the iOS application.  Obviously, this needs to run on a MacOS slave and, in production scenarios, one would normally configure headless MacOS servers to handle the builds – however, you can easily do the same thing using a MacBook laptop, by running jenkins-cli.war in a terminal window:

This is very convenient to test out the Jenkins configuration with your local Xcode development environment. You will need to make sure your SSH keys are configured correctly, but you should just be able to use the same key pair you use for your CloudBees/Jenkins account. There are full instructions on how to run customer provided slaves with a link to download an up-to-date version of jenkins-cli.war here:

For example, on my MacBook, I run the following command:
java -jar jenkins-cli.jar -s -i ~/.ssh/id_rsa_partnerdemo customer-managed-slave -fsroot ~/Jenkins -labels xcode -labels 4.4 -executors 1 -name markmacbook

Here ~/.ssh/id_rsa_partnerdemo is the private key I use with my Jenkins/CloudBees account, ~/Jenkins is a scratch directory that is used for temporary artifacts and the labels “xcode” and “4.4” are examples that show how different builds can be targeted to particular build environments. In this example, we check “Restrict where this project can be run” and specify “xcode” as the Label Expression to ensure that this project will only be built in the MacOS environment:

Setting up Xcode iOS Builds 

Once the channel has been established (as shown in the screenshot above), you will see the new node (here it’s “markmacbook”) appear in the Jenkins console, and we are ready to configure the actual Xcode build using the Jenkins Xcode Plugin.  In this example, to keep things simple, I am running jenkins-cli.war in my Xcode project directory, so most of the fields are either blank or take default values:

You will probably want to define a unique version number for each build and the easiest way to do that is with Jenkins macros, such as 2.2.${BUILD_NUMBER} as we have done in this example. Note that we have also checked the option to save the build as an .ipa archive, which is what we will want when distributing the app for beta testing using a service like TestFlight or Appaloosa.

Distributing the Mobile App for Beta Testing

Finally, we want to upload the app (as an .ipa archive) for distribution to beta testers: here we are using the Jenkins Appaloosa Plugin.  To speed up the upload process, we have taken advantage of the Fast Archiver Plugin, which is part of Jenkins Enterprise by CloudBees and which uses rsync-style delta encoding to optimize archiving.  You will need to make sure that you have the device IDs for the mobile devices that the beta tests will use included in the Provisioning Profile that you are including with your app; there are lots of helpful videos and how-tos on the iOS Provisioning Portal page (note: Apple iOS Developer Program login required).

In a follow-up blog, I’ll describe how to set up continuous deployment and integration testing for the back-end services.

Want to see this technology in action?

My friends at SOASTA and I will demo it live on Sept 27 at 10amPT on our new webinar, Automated Testing & Continuous Deployment for Mobile Apps in the Cloud. Sign up and join us!

Attend Jenkins User Conference SF - A Special Discount For You!

To find out more about this and all things Jenkins, please join us at the 2012 San Francisco Jenkins User Conference on Sunday, 30 September, and enjoy a full day of Jenkins-focused learning and networking opportunities.  Register here and as a special "Thank You" for reading all the way to the bottom of my blog, enter promotional code JUC-2012SF to get a $100 discount off the full-price registration!

Mark Prichard, Senior Director of Product Management

Mark Prichard is Java PaaS Evangelist for CloudBees. He came to CloudBees after 13 years at BEA Systems and Oracle, where he was Product Manager for the WebLogic Platform. A graduate of St John's College, Cambridge and the Cambridge University Computer Laboratory, Mark works for CloudBees in Los Altos, CA.  Follow Mark on Twitter and via his blog Clouds, Bees and Blogs.

Follow CloudBees:



  1. Thanks for sharing this info!!! This must be interested. I liked your blog layout.Web Design Professionally

  2. If you think you are great at Drag Racing then test your knowledge by trying to answer the questions asked by our members, candy crush it level 69help them out at the same time!