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

  1. 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.
  2. Setup your “Source Code Management”
    1. Set URL of Repository to be “git://github.com/shinetech/jenkins-ios-example.git
    2. Branch to build should be “*/master
  3. 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).
    1. Target “JenkinsIOSExample
    2. Configuration “Debug
    3. Check “Updated version with build number”, “Clean before build” and “Build IPA
  4. Click on “Add build step” but this time click on “Execute shell” as we want to setup our Unit Test target
    1. Enter the following command “xcodebuild -target JenkinsIOSExampleTests -configuration Debug -sdk iphonesimulator4.3 | ./ocunit2junit.rb
    2. 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.
    3. 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.
  5. Under “Post-Build Actions
    1. 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
    2. 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.

  1. Select “Manage Jenkins” -> “Manage Nodes” -> “New Node
  2. Give it the name “iOS slave” and select “Dumb Slave” then click “Ok
    1. Set “# of executors” to “1
    2. Set “Remote FS root” to be “dev/jenkins
  3. 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.
  4. Start it up on your OSX box that is running XCode. JNLP is the easiest option.
Now you will need to modify your “first-ios-app” build job to always use this slave to build.
To do this simply:
  1. Select the “first-ios-app” job and then click on “Configure
  2. Check “Restrict where this project can be run
  3. Specify “iOS slave
  4. 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)

After 2 successful 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!

  1. 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
  2. Check “Restrict where this project can be run” and specify our “iOS slave
  3. Click on “Add build step“, select “Execute shell” and in the “Command” specify
    1. 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>’
  4. Click “Save
  5. If your feeling lucky click on the Jenkins Job “Deploy latest successful build to testflight” and then select “Build now
You should see something like below in your build console output if your deployment to testflight was successful.

"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!


  1. Hi there.

    I’ve followed your steps and the process works fine. Anyway, I’m trying to connect master and slave over a SSH connection. I’ve managed to do so, but the build process fails at ProcessProductPackaging execution. This is the last step of the build process.

    I’m afraid it has something to do with file copy permissions using a SSH connection. Sounds weird but i can’t find a better explanation.The compiler shows no information.

    Have you managed to perform the master-slave process over a SSH connection? JNLP works fine but I prefer a SSH connection.


  2. By the way, I’ve created a fresh build job and executing

    xcodebuild -target = ProjectApp -configuration = Release -sdk iphoneos4.3

    Doesn’t work either over an SSH connection.

  3. I’ve finally fixed it. You must include a previous step to unlock the key-chain

    security unlock-keychain -p *******

  4. Hey jcristo2,

    Good work on getting the app to build over SSH! I have never actually tried to setup a master-slave process over SSH before. Can you tell me what are the benefits and do I need to install any additional plugins to set one up as I am keen to try this out.

    Just to recap are you saying In order to build the app successfully over SSH, the only changes you had to make to the build steps listed above was to make sure the very first build step was a shell job that ran the “security unlock-keychain -p ****” command?

  5. Exactly. If you connect both machines using JNLP, the client must start the connect. In order to do so, it must open a local session which also unlocks the keychain. The SSH session must unlock the keychain explicitly.

    if you need more information, send me an e-mail and I’ll help you if I can. 😀

  6. Please publish the codes for making this work with the VB softs language. The Jenkins soft is limited to appeal but the VB softs have much appeals too allover mens.

  7. I’ve tried your receipt on setting up a Xcode project in jenkins. Unfortunately by build failed with the following error message:

    [BEROR]Code Sign error: The identity ‘iPhone Developer’ doesn’t match any valid certificate/private key pair in the default keychain

    Do you have any advice what might be the cause for this problem?

    1. Hey Ralf,

      Have you installed your iPhone developer certificate and keys in your keychain? They should be visible if you open up “Keychain Access” and select your “login” keychain.

      Under “Category” if you select “My Certificates” and you dont see a certificate with the name “iPhone Developer: XXXX” or a private key attached the to certificate that is probably your issue.

      Hope that helps

      1. Hi Shaun,

        Good tutorial but I also ran into the same problem as Ralf. I discovered that if you run xcodebuild in jenkins and it is setup to run with another user account (e.g., UserName:jenkins) but that user is not logged in when running a job, then you hit the problem described here: http://stackoverflow.com/questions/6416121/keychain-wont-unlock-from-jenkins-script-unless-user-logged-in . So it sounds like you are running jenkins with your own user account while you are logged in. Is that true? Perhaps Ralf, like me, is/was trying to run jenkins with a different user account. (I ended up changing my jenkins user to my own user account – I haven’t tried moving all of my keys and certs to System.keychain as suggested in the foregoing link.)

        Has anybody had success running jenkins with another user account – or even better, on a “headless” build agent?

      2. I’ve recently spend some time looking at that issue. The Jenkins installation i’ve used for development of OSX / iOS based software made used of the jenkins installer provided by Ingo Richter.

        Any changes required to enable keychain access to the jenkins process is included in the change prepared for integration into a new release:


        It’s quite easy to apply to your local installation.

        Nevertheless, after applying those changes you have to add your developer certificates to the jenkins users login keychain and grant access to Xcode using the Keychain utility. But if applied correctly, it is possible to create valid .ipa for your iOS applications.

  8. Brilliant Ralf! Thank you for providing that patch. (I just had to remove your “Exit 0” at line 35.) Then, I simply provided the default setting for $unlock via `sudo defaults write /Library/Preferences/org.jenkins-ci unlockPassword $PASSWORD` and I was good to go. Now, I’m able to run hudson builds unattended as user jenkins and without being logged in.

  9. I can’t seem to get any solution working for making an ipa. jenkins only seems to want to run as user daemon, as soon as i change the username in the launchDaemon plist i cant get jenkins to even launch.

    i do notice that any change to the plist file changes the owner from system to my user. launchctl then refuses to load it saying it has dubious permissions. :-\

    in addition it wants to write ssh keys to /var/root/.ssh (ya cause thats gonna work) i suspect because its running a daemon whos home if im not mistaken is /var/root/ (yes?)

    i was able to use ralfs patch, but that only fixed the identity problem. then jenkins couldn’t find the mobiprofile even if i placed it directly in workplace and pointed the xcode build phase at it.

    am i doing something wrong? or could this be a problem with an apple update osx 10.7.2, and i just have to wait for an updated jenkins RC?

    1. Hey redpyxllnick did you ever find a solution to your problem? Are you still having issues building your IPA?

  10. Pingback: hyoki's me2day
  11. Thanks for a very useful post.

    We are using some third-party frameworks which are installed on the developer machines. What is the approach when building apps on the build server – is there a way to get XCode to bundle the frameworks for source control or would you install the framework on the build server as well?

    1. Are you looking for a kind of iOS framework dep manager? When building apps on the server it should be the same as on a node. As long as your server is running OSX, has xcode installed and can checkout your source code you should be in business. Your thrid party frameworks are checking into source control with your project right?

  12. Thanks so much for an excellent post, I managed to follow your steps fine. I was just wondering whether you had integrated ui automation tests to your CI builds? We have a number of scripts written using Apple’s UI Automation framework which are runnable from instruments via the command line but the issue I see is that I believe you can only have 1 simulator active at a time hence only 1 jenkins job could run ui tests at a time. Would be interested to hear your experiences on this.

    1. Funny you should ask! I am currently working on a project right now that is using UI Automation for running our automated tests. We are also using jasmine to inject some BDD love into out test scripts and then generating the test reports so Jenkins is happy. I am hoping to write up a post on it soon!

      With regards to your problem … I can’t say I have ran into it purely because I only have 1 project running at a time on my node. Is there an issue with only have 1 executor configured for say a test node and your UI tests can simply queue?

      1. Hi Shaun, thanks for your reply. Yes good idea, I’ll just configure 1 executor. Sorry to ask another question but looking at your sample project, your unit test does not actually import & use a class from the project, it just logs. Since I’ve started writing unit tests which import & use classes from the model in my application I’ve had a nightmare with linker errors. I’ve fixed some of these by following the instructions here – http://twobitlabs.com/2011/06/adding-ocunit-to-an-existing-ios-project-with-xcode-4/ to set a bundle loader etc. but now I keep getting the following error:

        Run unit tests for architecture ‘i386’ (GC OFF)
        /Developer/Tools/RunPlatformUnitTests.include:419: note: Running tests for architecture ‘i386’ (GC OFF)
        2011-12-08 11:39:27.666 otest[2017:7803] The test bundle at /Users/Mandy/Documents/TheElementsTwo/build/Debug-iphonesimulator/AnotherTryUnitTest.octest could not be loaded because a link error occurred. It is likely that dyld cannot locate a framework framework or library that the the test bundle was linked against, possibly because the framework or library had an incorrect install path at link time.
        /Developer/Tools/RunPlatformUnitTests.include:448: error: Failed tests for architecture ‘i386’ (GC OFF)

        /Developer/Tools/RunPlatformUnitTests.include:462: note: Completed tests for architectures ‘i386’

        ** BUILD FAILED **

        The following build commands failed:
        PhaseScriptExecution “Run Script” build/TheElements.build/Debug-iphonesimulator/AnotherTryUnitTest.build/Script-38382AC61490D6FE00DE43EA.sh

        Would be very interested to hear how you managed to get your more complex unit tests running as I seem to get this error on every project I try & run tests against, it’s driving me mad!

        Many thanks

      2. Hey Mandy,

        The only thing that springs to mind is that since your Test target is a completely different target to that of your App (and you have probably added some frameworks such as CoreLocation for example) have you checked to make sure that any frameworks your referencing in the classes your trying to test are also linked to your Test target? Same goes for any classes that you want to test you have to make sure they are added to the Test target as well.

        Hope this helps, let me know if your still having issues.

      3. Hi Shaun, thanks again very much for taking the time to reply, couldn’t quite work out how to get this reply inline but in response to your last post, I’ve fixed the issue as follows:-

        – added the TEST_HOST build setting to be $(BUNDLE_LOADER) – I had missed this step out from the instructions at http://twobitlabs.com/2011/06/adding-ocunit-to-an-existing-ios-project-with-xcode-4/

        – once I did this I ran into the issue where running the test target on the command line resulted in “warning: Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set).”

        – so then I did the “hack” as described in http://longweekendmobile.com/2011/04/17/xcode4-running-application-tests-from-the-command-line-in-ios/

        Finally my tests run on the command line… Note that an alternative fix would have been to add the individual .m files to the Test Target compile sources but this becomes painful if you have a lot of dependencies.

        Phew, I’m exhausted!

      4. @Mandy

        I actually ran into this same issue, it seems to be due to the build settings values in the default XCode templates when you choose to create a project and check the include unit tests. Rather than hacking my developer build settings, which is not ideal and could easily get overwritten with an upgrade or system change, I simply cleared “$(BUNDLE_LOADER)” from my targets build settings for TEST_HOST. I just set it to empty values and all is well again.

        Just wanted to share in case someone else runs into this.

  13. Can we built and run an iPhone app through SubVersions in xCode iPhone Simulator 4.3 of Slave Mac machine using Jenkins ?

    1. Definitely can you just need to make sure you checkout your source from SVN rather than GIT for example.

  14. Great tutorial. I have it set up but when I attempt a build I get the following error:


    CodeSign build/Debug-iphoneos/ContinuousBuildTest.app
    cd /Users/Shared/Jenkins/Home/jobs/ContinuousBuildTest/workspace
    setenv CODESIGN_ALLOCATE /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
    setenv PATH “/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin”
    /usr/bin/codesign –force –sign “iPhone Developer:XXX)” –resource-rules=/Users/Shared/Jenkins/Home/jobs/ContinuousBuildTest/workspace/build/Debug-iphoneos/ContinuousBuildTest.app/ResourceRules.plist –entitlements /Users/Shared/Jenkins/Home/jobs/ContinuousBuildTest/workspace/build/ContinuousBuildTest.build/Debug-iphoneos/ContinuousBuildTest.build/ContinuousBuildTest.xcent /Users/Shared/Jenkins/Home/jobs/ContinuousBuildTest/workspace/build/Debug-iphoneos/ContinuousBuildTest.app
    CSSM_SignData returned: FFFF1598
    /Users/Shared/Jenkins/Home/jobs/ContinuousBuildTest/workspace/build/Debug-iphoneos/ContinuousBuildTest.app: unknown error -2070=fffffffffffff7ea
    Command /usr/bin/codesign failed with exit code 1

    1. Are you running your test target against the Device or Simulator? Tests should be executed against the iOS simulator.

  15. Hi,

    Really good tutorial.
    FYI I worked with Ray to move it’s plugin in Jenkins official update-center.
    I succeeded to follow your tutorial but I didn’t have to use the ruby script for tests.
    Like you I created a a freestyle job with your git repository for the SCM. Then I added 2 Xcode build steps.
    1st XCode build step (to build the IPA) :
    * Clean before build? : checked
    * Target : JenkinsIOSExample
    * Configuration : Debug
    * Technical version : ${BUILD_NUMBER}
    * Build IPA ? : checked
    * Everything else is unchecked/unset
    2nd XCode build step (to execute tests) :
    * Target : JenkinsIOSExampleTests
    * SDK : iphonesimulator4.3
    * Configuration : Debug
    * Technical version : ${BUILD_NUMBER}
    * Everything else is unchecked/unset
    And then like you I configure to publish JUnit result and to archive the generated IPA.
    For now the latest version of the xcode plugin available is 1.2.1
    I hope it may help



  16. my goal is to do end to end automation in following way
    user check in a piece of code –> jekin do build for developer profile –> fetch build from jenkins –> run UI automation script through CLI –> generate automation build reports
    now i want to showcase a demo before implementing it for whole system. i have installed jenkins on my local mac machine then installed Xcode plugin as per your instructions.
    1. can i work with my local directory as SVN, where i can do code check in through xcode SCM?
    2. if yes or no for above question then in either condition , how can i build xcode project placed in my local directory, through jenkins?
    3. after a successful build, can jenkins trigger any mac script placed on my local machine , which will run automation script?

    Please guide me for this initiative and let me know if it have any feasibility issues?

  17. Hi Shaun , could you share how do you create the sample project?
    I can finish the tutorial with your sample project , but can’t do it with my own project.
    My project is created by XCode 4.2 and check “Include Unit Tests”.

    1. Here is error log : /Developer/Platforms/iPhoneSimulator.platform/Developer/Tools/Tools/RunPlatformUnitTests:95: warning: Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set).

      1. Hi Mary,

        Are you trying to run Application tests or Logic tests? I think you can only run logs tests if I remember correctly?


      2. Thanks for your reply. Creating by XCode 4.2 and check “Include Unit Tests” , it’s default setting is “Application tests”. As you say, Application tests can’t run in simulator.
        When I created my own logic tests , it worked. Thank you.

  18. Hi all,
    I am following this great tutorial, but I have an issue: my XCode is installed in a non-standard folder, because we need to use several XCode versions. I get the following error:

    FATAL: Cannot find xcodebuild with the configured path /usr/bin/xcodebuild.
    Build step ‘XCode’ marked build as failure

    Is there a place in the xcode plugin to configure XCode path?
    Thanks in advance

    1. hey Luca….my xcode is also installed in different directory, so in this case there is a option available in Xcode plugin “SDK ” , here you need to give full path of your Xcode SDK. i have done it successfully. i have done end to end automation from code checkin to automation testing. let me know if you need further help.

  19. Thank you Vikas for the prompt answer!
    I have tried that option and it works, meaning that it calls the ‘xcodebuild’ in my custom folder.
    so good with one XCode SDK installation, but my actual need is to be able to configure different XCode installation folders on a per-project basis. E.g.: project A needs XCode 4.2, project B needs XCode 3.2.6, and so on. With this plugin, one can define only a single path for XCode. Perhaps I might try and modify the plugin in order to move that setting at the ‘job properties’ level; any suggestion ?
    Thanks in advance once again

  20. Hey

    Thanks a lot for this tutorial.
    However I am joining some people here who had a problem with the user account executing the build.
    The default installer for Jenkins installs the service as a different user (jenkins). Compilation fails because of certificate errors or some error of not accepting xcode’s terms and conditions.
    I had to stop the service of Jenkins and run the war (/usr/bin/java -jar /Applications/Jenkins/jenkins.was) in a terminal console under my current user.
    Please go through the steps again, as I think this tutorial is outdated.
    Thanks again though – you saved me a lot of time.

  21. Hi, did you ever get the UI Automation tests to run from Jenkins? I’ve been trying this but run into the issue that because I am running Jenkins as a daemon user it can’t connect to the Window Server to run the tests against the simulator. I found a workaround here: https://github.com/stisti/jenkins-app#readme but it doesn’t seem ideal as it requires a user account to automatically login on boot. Any ideas appreciated!

  22. Hi,

    Thank you for the tutorial!

    I am having problems compiling a workspace. The build fails at the packaging stage.
    Can see the build directory created in the workspace. Please help.


    Cannot remove *.ipa files from a non-existing directory: /Users/leon/Work/projects/wearehive/flatstr/build/Flatstr/dev/jenkins/workspace/Snug-debuOLD/build/Debug-iphoneos
    Packaging IPA

    Thank you.

  23. It seems that my Jenkins is having problems with locating the artifacts (IPA file).
    After successfully creating an ipa build and then trying to upload it to testflight I get this:

    curl: (26) couldn’t open file “first-ios-app/build/Debug-iphoneos/JenkinsIOSExample.ipa”

    I notice that when traversing the file for the ipa build it is located at the path :localhost:8080/job/first-ios-app/ws/build/JenkinsIOSExample-Debug-1.0.ipa

    I’ve tried changing the path to file=@first-ios-app/ws/build/JenkinsIOSExample-Debug-1.0.ipa
    but this still doesn’t work. Any ideas?

      1. Great blog post.

        Will this not fail if the bundle version is changed? i.e.
        JenkinsIOSExample-Debug-1.0.ipa might become

        is there any way to access this filename/path either through jenkins or locally?

    1. as a workaround I just before the testflight script I rename the .ipa:
      mv /build/Debug-iphoneos/*.ipa Story/build/Debug-iphoneos/prjname.ipa

      so that I can use the fixed name to automate the testflight upload.

      1. sorry I messed up the path, I do something like this:
        mv build/Debug-iphoneos/*.ipa build/Debug-iphoneos/.ipa

  24. Have you run into an issue with Jenkins creating a “jenkins” account on your machine? As soon as that appeared, Jenkins runs as this new account, which doesn’t have access to git or my mobileprovisioning files. Fixed the git issue by creating new SSH keys (using sudo su with my known user account) , but I can’t gain access to the Library in order to move the mobileprovisioning files to where the XCode plugin expects them under “jenkins”.

    Is there a Jenkins build that introduced this account?

  25. That is great if i’m using GIT, what about tfs. I found a plugin for TFS, but not ‘Git tfs’ which i have on mac

  26. I am getting this error “No matching codesigning identity found: No codesigning identities (i.e. certificate and private key pairs) matching “iPhone Developer” were found.”

Leave a Reply to Vladimir Grichina (@vgrichina) Cancel reply

%d bloggers like this: