
A Jenkins automated build server is one of the best ways to distribute a new build of your app to stakeholders and testers during the development, QA and UAT phases of the project. Jenkins is a highly customizable solution and best of all it’s FREE! The tutorial below will walk you through setting up and configuring the server plus adding a web server to help distribute the builds to the team. Note that the build will only work on devices that are included in your application provisioning profile (just like manually installing).
Installing Jenkins
The first time I tried installing Jenkins I downloaded the software from their website. Everything was going pretty well until I linked by GitHub account to the project. Jenkins wasn’t able to find the SSH key needed to automatically download the source code. The problem was that when the standard version of Jenkins is installed it creates it’s own user on the system and runs under the name “daemon”. Since it runs under another user, not your user it doesn’t have access to your GitHub SSH key. I searched all over for a solution to this and there are a ton of people who were having the same problem. I tried changing the user that Jenkins is running on, but in order to do that I needed to switch to the Jenkins user then give access to my user on the system, but I couldn’t find the Jenkins user password. Next I tried copying the SSH keys to the Jenkins user account, but that didn’t work either.If you are like me and installed the standard Jenkins software and want to uninstall it from your system, use the commands below in Terminal to remove Jenkins from your system.
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist sudo rm -rf /Applications/Jenkins "/Library/Application Support/Jenkins" /Library/Documentation/Jenkins sudo rm -rf /Users/Shared/Jenkins sudo dscl . -delete /Users/jenkins sudo dscl . -delete /Groups/jenkins
After a lot of searching, I found another solution. Sami Tikka created a new version of Jenkins that you can find on the jenkins-app Github that will install Jenkins under your current user account. This saved the day and made the rest of the setup for Jenkins so much easier. Once Jenkins is installed it will be hosted at http://localhost:8080, but also available publicly at http://<your IP address>:8080 so you can configure your server from anywhere you can access your IP from.
Configuring Jenkins
After Jenkins is installed we need to setup the plug-ins that we need for our server. Note that Jenkins can be used for many languages (including Java) and many source control systems (including CVS and Subversion). To access the plugins, click “Manage Jenkins” from the left side bar, then “Manage Plugins” from the list. Select the “Available” tab and check the following pluglins (Since we’re using GitHub and iOS):1. GitHub API Plugin
2. GitHub Plugin
3. XCode integration
Let’s configure the system and enter in the details needed for the plugins to work. Select “Manage Jenkins” from the left side bar, then “Configure System” from the top of the list. You’ll notice the Home Directory at the top shows that Jenkins is installed under your user account, this means that the server can access all of your SSH keys and iOS Certificates from your user account. There isn’t much to change here, all of the defaults are good. Just enter your GitHub username and email address under the “Git plugin” section. Then scroll to the bottom and under “Git Web Hook” select “Let Jenkins auto-manage hook URLs” and enter your GitHub username and password. Click “Test Credential” to ensure that the server can verify you have the correct account information.
Setup your First Job
Now that the server is ready let’s setup our first project. Click “New Job” from the left side bar. Enter the name of your application and select “Build a free-style software project” and click “OK”. Under “Source Code Management” select “Git”, then enter your Git Repository URL. This URL must be the SSH URL found on GitHub, the HTTP URL will not work because the server cannot enter in the password needed. If you have not setup an SSH key for GitHub before, check out their tutorial on Generating SSH Keys.To setup the Build Steps, click “Add Build Step” and select “XCode”. Check “Clean before build?”. Enter the “SYMROOT” to where the build will be stored (i.e. ${workspace}/build/<YourAppName>/Build/Products). Enter the “Configuration” to build the release from in your Xcode project (i.e. Debug or Release). Enter “${BUILD_NUMBER}” in the “Technical version” field. Check “Build IPA?” and “Unlock Keychain?”, then enter in your “Keychain path” as “${HOME}/Library/Keychains/login.keychain” and your password (which is your User password on your Mac). With this setup you will need to access the Jenkins server and select the “Build Now” option for the job. However if you would like to have an automated build you can setup those options under the “Build Triggers” section. It can “Build when a change has been pushed to GitHub” or “Build periodically” where it can be set to build at a specific time. An example for midnight is “0 0 * * *”. The first zero is the hour and the second is the minute to start the build.
We want to setup our server so the rest of the team can access the builds directly from their iPhone or iPad so we need to make a shell script that will copy the compiled IPA file to the web server so the team can access it. Click “Add Build Step” and select “Execute Shell”. Below is a shell script to get your started:
#!/bin/sh export OTAURL="http://:8888/ " export OTASmallIcon=icon.png export OTALargeIcon=icon.png export OTADeployPath=~/Documents/JenkinsBuilds/ export OTATitle= cp build/ /Build/Products/Release-iphoneos/*.ipa $OTADeployPath/ .ipa export info_plist=$(ls / -Info.plist | sed -e 's/\.plist//') export bundle_version=$(defaults read $WORKSPACE/$info_plist CFBundleVersion) cat << EOF > $OTADeployPath/ .plist EOF items assets kind software-package url $OTAURL/ .ipa kind display-image needs-shine url $OTAURL/icon.pn kind full-size-image needs-shine url $OTAURL/icon.png metadata bundle-identifier com. . bundle-version $bundle_version kind software title $OTATitle
You’ll notice in the script above that you need to change the values of <YOUR PROJECT NAME> throughout. The OTADeployPath should be set to the path on your MAC that you set the web server root to (see more about that below). The “bundle-identifier” should be set to the Bundle Identifier set in your Xcode project.
Setting Up the Web Server
In order for the team to access the latest build they need to access it on their device. First, install MAMP on your MAC by selecting to download “MAMP: One-click-solution for setting up your personal webserver”. This is a FREE version for personal use. Once you have installed MAMP, change the Document Root to point to where you are copying the builds to in the OTADeployPath above. Once the Document Root is set you can “Start Servers” to begin. Next, create a simple index.html file to host in the Document Root.Apps
To see your server enter http://<YOUR IP ADDRESS>:8888/ into your web browser. You should see the page above with a link to the IPA of your build.
Start Testing
The web server is setup, the automated build and shell script is set. Now let’s see if it works. Access your Jenkins server at http://<YOUR IP ADDRESS>:8080/, select your job and click the “Build Now” button from the left side bar. You’ll see the progress on the left side bar. Jenkins will attempt to access your Git repository to pull the latest code, then build it to create the IPA. Once it’s been compiled the shell script will copy the IPA to a project sub-directory under your web server document root directory. Then go to your web server URL http://<YOUR IP ADDRESS>:8888/ from your iPhone or iPad and click the link to install the app on your device. That should all work well but if you run into issues on the way be sure to check Jenkins for a reason why it failed. This information can be found under the “Build History” and clicking the “Console” icon on the right side of the table for the build that failed. Scroll down to the bottom of the output to see why it failed. Maybe it couldn’t copy the IPA correctly to your web server document root, ensure that they match.Good luck with your automated builds. Once it’s setup and working it’ll be a valuable asset to your entire team to always have the latest version of your app without you having to manually install the app on their devices each time.