With thanks to Depeche Mode for the title.
This week I’ve been having a bit of fun with my own Jenkins setup. I use jenkins/hudson at work on a daily basis within our agile processes and thought it might be OK to set my own up for Beadbash.
For those that don’t know, Jenkins is a java based continuous integration server that will automate building, testing and deploying software for you. The power of this software comes from the fact that it has dozens of plugins for all sorts tasks. In my case I needed to
- grab the source code from my bitbucket git repository (although it could quite easily have been svn, mercurial or many other source code management SCM tools).
- compile it up as an iOS build
- deploy it to my phone via testflight
Jenkins Continuous Integration
I watched this youtube video first to see what’s possible, then I got started configuring it all.
To make things a bit easier, I decided to install Jenkins on my mac in the office rather than trying to run it on my laptop. This would make doing the xcode build a bit simpler as I wouldn’t need to create a slave server and configure all that up. (I might if I end up needing lots of build servers if I were anything more than a one man band for this project but as this is my first time setting it all up I felt that adding a slave component was overkill.). Installation was painless! Download the dmg from jenkins-ci.org, run the installer package, select the custom options so it would not run as a boot process as a different user and then run it manually using java -jar jenkins.war. That’s enough to get it all running and opening localhost:8080 gives me the start screen.
I then added all the plugins I would need the bitbucket hook, git, testflight, xcode etc. I also took a moment to configure a username and password so I could restrict access and then make it available externally via my firewall.
First pest problem was getting the source from bitbucket. I tried using ssh keys, but my keys always have a password set. I can understand why people create their keys without passwords so services can use them without needing input each time (like apache ssl certificates) but for personal certs I’m not happy just letting them being used. If my laptop was stolen or I lost a backup usb key then all sorts of mischief could be done before I managed to revoke the keys. Anyways’ it seemed that other people had come across the same problem and after a few false starts I found that actually bitbucket would work with just a username and password setup instead of ssh keys. So job 1 done.
Next step was getting my repo downloaded. Because I have both the full cocos2dx tree and then a separate repo for beadbash under projects, I needed to use the multiple SCM configuration and set the second scm download to put the files in a sub-directory. That was pretty straightforward but then I came up against another problem. The cocos2dx repo was too large and Jenkins was timing out before getting the whole repo down. A few searches later and some serious stackoverflow.com reading and I found a solution. I had to create a local bare git repo of the source code and use advanced clone with a longer timeout. This is only a problem the first time the workspace tries to get a copy of the repo as the next time through it only grabs the changes.
Repo sorted, next step was to get xcode to compile the code via the Jenkins plugin. This is where things got a bit hairy for a while. I hadn’t actually tried compiling it natively on the mac, so the first time I tried a build, it failed unable to open the keystore, and dozens of errors. I opened the current code properly in xcode I had a whole lot of fixing to do:-
Add the resources, *.cpp,* .h files to the project. Modifying the linux makefile just doesn’t do it. (Note to self, I’m going to have the same problem when setting up the android build!).
Create the signing certificates in my keystore. This is the bit of voodoo that I still don’t understand fully but xcode takes care of it for you when developing. When releasing an app to the app store, then you need to create a new certificate via the apple connect interface and apply that to the .ipa package anyway so that’s fairly straightforward when the time comes.
There are a lot of deprecated warnings that I’m not going to fix just yet but will probably mean I need to upgrade to cocos2dx-3 at some point when it becomes stable. Perhaps someone will write a migration tool at the same time else I’ll have to get busy with sublime doing a lot of search and replaces.
So after several false starts, I’ve got the app to build.
The final step for this setup was to get the app deployed to my phone via testflight. This is where things got much easier. I already had a testflight account so I could grab my api keys and plug them straight into the Jenkins Plugin. A few settings later and its ready to test.
I did run into one problem which is that testflight searches the whole repo for apk’s and ipas to upload – which then also included some stuff in the cocos2dx which I didn’t need. So I fixed that by being specific to the android and ios project directories for beadbash.
A few nights work and now I’ve got a superb system for delivery to testers! Write the code, push it to the repo. Jenkins will check once a day (unless I kick off a build manually) if the repo has changed and if it has will build a new version of the code, push it to testflight and an email automatically arrives on my phone with a link to download and install the new version. Slick.