No description, website, or topics provided.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
Tomcat Setup
Xcode Bots

iOS Continuous Integration

A collection of scripts to automate the build and deploy steps of iOS applications for continuous integration via the excellent Jenkins.

Jenkins Automation A script to automatically update the Jenkins web application if a new version is available. The intention is for this script to be executed periodically as a Jenkins Job.

Continuous Integration

The following files make up the CI portion of this repository:


cupertino is used to fetch the latest distribution provisioning profile from the Apple iOS Developer portal.


Let's say you have a workspace set up called Foo.xcworkspace. At the same level of your workspace, there's typically a directory called "Foo" which contains your sources. These scrips are designed to reside in a directory named jenkins inside of that directory. So your directory structure should look like this:



Assuming you've created a Jenkins freeform job for your build, create an "Execute Shell" build step, and pass in the needed configuration values, like this:

#!/bin/bash -e
APP_NAME="Foo" \
DEV_USER="levi" \
DEV_PASSWORD="devsecret" \
KEYCHAIN_PASSWORD="supersecret" \
JENKINS_API_TOKEN="somereallylonggoop" \
TF_API_TOKEN="otherreallylonggoop" \
TF_TEAM_TOKEN="evenlongergoop" \
/bin/bash Archer/Archer/jenkins/

DEBUG (if set to 1) will enable verbose output of the script.

TF_UPLOAD (if set to 1) will upload the generated .ipa's and DSYM files to TestFlight.

APP_NAME is the name of the application being built; i.e. Foo.ipa

PROJECT_NAME is the name of the Xcode project (workspace) being built; i.e. Bar.xcworkspace

DEV_USER and DEV_PASSWORD are the credentials for the Apple Developer account which contains the desired distribution mobileprovision. If not supplied, the script will assume cupertino has the needed credentials in the keychain already.

KEYCHAIN_PASSWORD is the password for the default keychain on the build machine which contains the certificates and keys needed for the build.

To figure out your JENKINS_API_TOKEN visit the Jenkins Wiki

NOTE: You may want to specify the shell which Jenkins uses so sensitive information in your configuration is not output to the Jenkins log. To do this, simply add #!/bin/sh -e as the first line of the "Execute Shell" script. This will replace the default of #!/bin/sh -ex (note the 'x') which prints out all evaluations.

Build Configurations

Additional configuration may be desired within the script to specify the different Xcode schemes to build. See the Build Configurations section in

In the example below, there will be three builds. A "Tests" build, AdHoc and Enterprise. The following configurations are index-representative for each config type. For instance, the "Tests" scheme (defined in SCHEMES) is enabled (SCHEME_ENABLEDS) has the label "Tests" (SCHEME_LABELS), is of type $TEST_TYPE (BUILD_TYPES), uses the "AdHoc" Xcode configuration (CONFIGS), uses the mobileprovision profile called $PROJECT_NAME AdHoc (PROFILE_NAMES) which is of type "distribution" (PROFILE_TYPES) and uses the (PROFILE_ACQUISITION_SCRIPTS) to provide the actual mobileprovision file.

SCHEME_LABELS=("Tests" "AdHoc" "Enterprise")
CONFIGS=("AdHoc" "AdHoc" "Enterprise")
# The type of profile (used to download the profile from the Apple Developer portal)
PROFILE_TYPES=("distribution" "distribution" "distribution")
# Script relative to $RESOURCE_DIR/$CI_DIR which will download mobileprovision profile files


Each scheme listed in SCHEMES should have a corresponding TestFlight list defined.

In the example below, the "Tests" build does not get distributed to TestFlight, yet the second build will be distributed to the "Development" list while the third build wil go to the "Enterprise" list.

TF_DIST_LISTS=("" "Development" "Enterprise")

Additional configuration is needed within the script to specify the different hardcoded profiles to fetch from the filesystem. See the Configuration Section section in

#The hardcoded profile names we are expecting
#The matching profile files
PROFILE_FILES=("CHANGE_ME_AdHoc.mobileprovision" "CHANGE_ME_Enterprise.mobileprovision")


This work is licensed under the Creative Commons Attribution 3.0 Unported License. Please see the included LICENSE.txt for complete details.


A professional iOS engineer by day, my name is Levi Brown. Authoring a technical blog, I am reachable via:

Twitter @levigoker @levigroker

Your constructive comments and feedback are always welcome.