I thought it was about time I should put together a simple guide on using Jenkins to build your iOS application – and for those of us that use the awesome testflightapp.com website for managing our iOS app distribution for testing, I have included details on creating a Jenkins job to publish the latest successful artifact to testflightapp.com.
Getting Started
I assume that anyone wanting to try this tutorial out already has an iPhone developer account with Apple and an iOS Xcode environment already setup.
The Sample iOS Project
I have created a simple iOS project that you can download from github @ https://github.com/shinetech/jenkins-ios-example. Clone it where ever you wish however I will assume you have installed it at “~/dev/iphone/jenkins-ios-example” for the tutorial.
This project has 2 targets one for the app and the other to execute our unit tests.
The project will try to use whatever default provisioning profile you have installed for “iPhone Developer”. Its best just to have a Team Provisioning Profile installed which has an application identifier of * to let you build and deploy anything for test purposes.
Installing the XCode plugin for Jenkins / Hudson
You are going to have to install the XCode plugin for Hudson CI that was created by Ray Hilton to allow you to build your iOS project from Jenkins. You can download the latest snapshot of the plugin @ http://rayh.com.au/xcode-hudson-plugin
Install the Git plugin for Jenkins / Hudson
For this tutorial you will also need to install the “Git Plugin” as we will be referencing an example git project on github. More details can be found @ http://wiki.hudson-ci.org/display/HUDSON/Git+Plugin
If you require any details on how to install Jenkins or on how to install plugins you can find all that information @ https://wiki.jenkins-ci.org/display/JENKINS/Plugins.
Ruby will need to be installed wherever the job is going to run
We need ruby to be installed wherever the iOS Jenkins job is going to be executed, to enable us to generate the correct junit test output that Jenkins is going to understand. (see below about setting up an OSX node)
Setting up your first Jenkins iOS job
- Create a new Jenkins job. Lets call it “first-ios-app” (make sure the name you choose doesnt have spaces, trust me its easier!) and select “Build a free-style software project” as your job type.
- Setup your “Source Code Management”
- Set URL of Repository to be “git://github.com/shinetech/jenkins-ios-example.git“
- Branch to build should be “*/master“
- Click on “Add build step“. If you have the Xcode Hudson plugin installed successfully you should be able to select “Xcode” (If not then the plugin was not installed correctly).
- Target “JenkinsIOSExample“
- Configuration “Debug“
- Check “Updated version with build number”, “Clean before build” and “Build IPA“
- Click on “Add build step” but this time click on “Execute shell” as we want to setup our Unit Test target
- Enter the following command “xcodebuild -target JenkinsIOSExampleTests -configuration Debug -sdk iphonesimulator4.3 | ./ocunit2junit.rb“
- Remember earlier I said dont create your Jenkins job name with spaces well the above command is why. Using ${WORKSPACE} will give you the absolute URL path to the current workspace … however it will NOT escape spaces.
- All we are doing above is excuting xcode from the command line and sending its output to the excellent ocunit2junit.rb script created by Christian Hedin. Which converts the ocunit test output into the same xml format that is used by junit.
- Under “Post-Build Actions”
- Lets archive the artifacts that have been successfully built and that we will us later to deploy to testflightapp.com. So in “Files to archive” specify “build/Debug-iphoneos/*.ipa“
- Check “Publish JUnit test result report” and for “Test reports XMLs” specify “test-reports/*.xml“.
If Jenkins is running on anything other than OSX you will need to create a Jenkins node
If your like the rest of the world and you have already got Jenkins running on your unix box then you dont really want to have another instance running on OSX.
Jenkins makes it pretty to create a node that we will then target in our “first-ios-app” job to always use when building.
- Select “Manage Jenkins” -> “Manage Nodes” -> “New Node“
- Give it the name “iOS slave” and select “Dumb Slave” then click “Ok”
- Set “# of executors” to “1“
- Set “Remote FS root” to be “dev/jenkins“
- You can now go back to Jenkins home and click on the offline slave “iOS slave” from the machine you wish to run as the slave.
- Start it up on your OSX box that is running XCode. JNLP is the easiest option.
- Select the “first-ios-app” job and then click on “Configure“
- Check “Restrict where this project can be run“
- Specify “iOS slave“
- Save
Time to run the “first-ios-app” job!
Lets build our project and see what happens! I am hoping you see something like the output below. (You only get test output after 2 builds)
If you had any errors please let me know as I would be interested in knowing what steps went wrong.
Creating a new Job to push our latest build to testflightapp
If you have a testflight account then please try out the steps below. If not I strongly suggest you sign up for free at testflightapp.com because it is a brilliant web app for iOS developers that lets you do over-the-air distributions!
- Create a new Jenkins job. Lets call it “Deploy latest successful build to testflight” and select “Build a free-style software project” as your job type. Click Ok
- Check “Restrict where this project can be run” and specify our “iOS slave“
- Click on “Add build step“, select “Execute shell” and in the “Command” specify
- Watch out for copy and paste errors! Please make sure you use correct single or double quotes. Copy everything below as your shell to execute.
# For this test lets just go up a directory and user the ipa we built.
cd ..
# Execute the magic to upload out IPA to testflight
curl http://testflightapp.com/api/builds.json -F file=@first-ios-app/build/Debug-iphoneos/JenkinsIOSExample.ipa -F api_token='<api token>’ -F team_token='<team token>’ -F notes=’This is an autodeploy build from Jenkins!’ -F notify=True -F distribution_lists='<name of test distribution list>’
- Watch out for copy and paste errors! Please make sure you use correct single or double quotes. Copy everything below as your shell to execute.
- Click “Save“
- If your feeling lucky click on the Jenkins Job “Deploy latest successful build to testflight” and then select “Build now“
{
"bundle_version": "1.0 (1.0.9) #2",
"install_url": "https://testflightapp.com/install/be17d5gfdd68ed742625534a4b1-MjEx124/",
"config_url": "https://testflightapp.com/dashboard/builds/complete/214228/",
"created_at": "2011-06-23 06:28:12",
"device_family": "iPhone",
"notify": true,
"team": "My Testers",
"minimum_os_version": "4.3",
"release_notes": "This is an autodeploy build from Jenkins!",
"binary_size": 21467
}Finished: SUCCESS
Spread the word on how easy it is to do iOS dev with Jenkins!
I strongly believe one of the first things developers should be doing when beginning work on an iOS project is to setup an Continuous Deployment environment. Regardless on the team size because it really will save you time down the track.
The last 2 iOS projects I have worked on our team has used Hudson / Jenkins to successfully build, test and produce our dev, test and production ready binaries.
I hope this tutorial helps to make your next iOS project even easier to develop and distribute!
Image may be NSFW.
Clik here to view.
Clik here to view.
