Teach Xcode 6 CI new tricks

pip install cavejohnson==1.3


The road to 2.0

This repo is for CaveJohnson 1.0. If you wanted 2.x, click here.

CaveJohnson is a program to teach XCode6 Server new tricks. It's a set of commands that perform various commonly-used tasks in a continuous build system. While designed primarily for use inside an XCS trigger script, many of the commands are useful to other build systems (Jenkins, TeamCity, etc.) because the author is unusually good at reverse-engineering and duplicating weird Xcode behavior.

In true Unix style, these commands can all be used separately:

  • Build status reporting to GitHub
  • Detecting the GitHub repo and git sha of the current XCS integration
  • Set the CFBundleVersion based on the XCS integration number
  • Re-sign an IPA with a new provisioning profile and certificate
  • Install a mobile provisioning profile to XCS
  • Resolve missing SwiftSupport that prevent builds from being processed correctly in iTunesConnect
  • Generate .symbols files so iTunesConnect symbolicates your crash reports
  • Submit to iTunesConnect (new TestFlight) so you can get fully automatic deployments
  • Submit to HockeyApp


Report status to GitHub inside trigger

First configure GitHub credentials

sudo -u _xcsbuildd cavejohnson setGithubCredentials

Now from inside trigger we can do

cavejohnson setGithubStatus

Figure out what SHA or repo is being integrated

$ cavejohnson getGithubRepo
$ cavejohnson getSha

Set minor build number (CFBundleVersion) to XCS integration id

cavejohnson setBuildNumber --plist-path ./path/to/Info.plist

Very quick guide to automating New TestFlight:

  1. First, you need to copy your distribution certificate and key into the System keychain
  2. Make sure the key's Access Control is set to "Allow all applications to access the item" or you will get a hang.
  3. Check your provisioning profile into source control
  4. In build settings, ensure your Code Signing for Release is set to distribution, and your provisioning profile for release is Not automatic. More detail on the why can be found in my Xcode CI missing manual
  5. Set up a pre-integration trigger
cavejohnson setBuildNumber --plist-path ./MyiOSApp/MyiOSApp/Info.plist
cavejohnson installMobileProvision --provisioning-profile ./MyiOSApp/myIosApp.mobileprovision

This installs the provisioning profile from source control and creates a unique build number for the app.

Now you need a post-integration trigger:

cavejohnson xcodeGUITricks --new-ipa-path myapp.ipa #only required for projects that include Swift
cavejohnson uploadiTunesConnect --itunes-app-id 12345678 --itunes-username --itunes-password mypassword --ipa-path myapp.ipa

This works around some Xcode CLI bugs and sends the fixed IPA to iTunesConnect.


Requires Python 3

pip3.4 install cavejohnson

#or to grab development version
pip3.4 install git+


You may also find my Xcode CI missing manual helpful, which explains the rationale for some things in this program.