Setting up an Automated Build in an iOS environment – part 2
by George on Aug.18, 2010, under Coding, Project Management
After last week’s introduction, it’s time to get on with making this thing. After looking at both CruiseControl and Hudson, I went with Hudson – mainly because it’s very simple to set up and start using straight away. So without further fuss, let’s download Hudson from here. I created a build folder ~/AutomatedBuilds (there’s nothing special about this location, put it wherever suits you) and put the downloaded file hudson.war.zip in it.
Open a terminal window and cd to the build folder. The online documentation says that you should unzip hudson and run it using the command:
java -jar hudson.war
This works fine on Windows, however under OS X, unzipping the file and trying to run it causes the following error:

If anyone can explain the issue, I’d appreciate the insight. However it turns out we can just run Hudson as-is out of the zip file:

Ok, so what’s happened? Hudson is now running as a Java application in the terminal. As well as running the build, it also provides a web interface for us to work with. Open a browser and point it at http://localhost:8080/ and you should see something like:

Before we set up our first job, we should grab a couple of handy plugins first. Click on the Manage Hudson link on the left, then Manage Plugins and finally the Available tab. You should see a long, slightly exciting (or intimidating, depending on your outlook on life) list of plugins. Have a look through the list – there’s lots here to play with – but for now select the Twitter and Mercurial plugins (assuming I’ve convinced you to try Mercurial), and click on the Install button.
You should see the plugins being downloaded and installed, along with a message to restart Hudson. When Hudson is running, there’s a Prepare for Shutdown option on the Manage Hudson page. For now though, it’s enough to go to the Terminal window you’re running Hudson in and kill it with Ctrl+C (I’m a bit old fashioned that way).
Run Hudson again from the terminal window, and we’re ready to set up our first automated build. For a start, let’s create a build that monitors our source control repository and kicks off a build when it sees any changes.
On the main Hudson dashboard, click New Job. Give the job a name, choose the “free-style software project” option and click OK.
On the resulting page you can configure a bunch of options. Feel free to go nuts here. Each option has a ‘?’ icon that provides useful help. Here’s the settings I used:
Under Source Code Management, I chose Mercurial and pointed it at my Fogbugz Repository. The Fogbugz repository requires the user to be authenticated, so we do this by including the user name and password in the URL in the form:
https://USER_NAME:PASSWORD@PATH_TO_REPOSITORY
Note that, if your user name has a ‘@’ symbol in it, replace the ‘@’ with ‘%40′ to avoid the URL being incorrectly parsed by Hudson or Fogbugz (see the screen shot below).
Hudson also supports many other types of source control, pick the one that you use. Another small note here – when setting up an automated build for the first time, it’s a good idea to use a small test project first, to allow faster testing of your set up. My actual production code can take many minutes to build (not my fault! OpenFeint is slow to build), so instead, for this article, I’ve created AwesomeGame from one of the standard XCode templates. Once I have a running build system, I’ll then go back and add in my production code.

Next up, we want to check if we need to trigger a build by polling SCM for changes. We schedule Hudson to check SCM every minute using CRON-like syntax :

Then, we add the actual build step, executing a shell command to run XCode from the command line using xcodebuild. Have a look at the xcodebuild man page for all the various options. For now, we want to build our AwesomeGame target in both Debug and Release modes. I’ve done this below using two build steps:

Finally, let’s tell Hudson how to notify us when the build is done. I selected email and Twitter notifications. If you’re on a team, notice the option to notify the individual who committed the changes that broke the build – without having to notify the entire team. As well as the person responsible for the break it’s good practice to have a nominated ‘build monkey’ whose job it is to check all builds – so make sure they’re getting all the build results as well. A quick note on Twitter here – don’t use your own Twitter account unless you want to spam all your followers! Instead, create a bogus build account for Hudson to use, and follow it from your main account.
Assuming we’re all happy with the settings (we can always come back and tweak them), click Save.
Hudson now takes us to the page for our project. On the left is a Build Now option – let’s try it out… After a few seconds, you should see a progress bar in the bottom left, telling you that Hudson is building your project. If nothing happens, check the top right of the page for an Enable auto-refresh option.
Once finished, we’ll see a blue ball that indicates a successful build (your code in source control does build, right?). If instead you see a red icon, then the build has broken, and we need to fix something. Either way, click on the most recent build link to see details of the build:

On this page, we can see the status of this particular build (remember blue ball means success), the changes in source control from the last build (none in this case, as we manually triggered the build) and the console output, where we can see the details of the code being checked out from source control and built using XCode. If your build has failed, this is a good place to look for the problem.
Phew! The system works! Checking Twitter, sure enough there’s a success message there:

But hang on, where’s my email? The problem here is that we need to configure Hudson with an smtp server so that it can deliver mail to us. Go back to the Manage Hudson page, and click on Configure System. Near the bottom you can configure the global settings for email and Twitter. If you’re unsure what smtp server to use, check the settings for your email program – you’re looking for the name of your outgoing smtp server.
So enter in your smtp details, and the system admin email address (that’s you). Click on the Test button and make sure that you get the test email message.

Going back to the main Hudson page, you should notice that our project is listed, and on the right hand side is a Build Now icon (so you don’t have to go into the project to kick off a build). Click it to start another build, and then click on your project to follow the build’s progress… Still no email. Bugger. Going to the project’s Configure screen, I look up the help for email, which sheds some light on the issue:

This is sensible – no point in spamming out emails when builds are all going well.
So by now we know that we can check out our code and build it automatically. But where is the build? Hudson creates a working folder in your root directory. Have a look in ~/.hudson, and you’ll see all of Hudson’s internals. In particular, the folder ~/.hudson/jobs/Awesome Game contains all of our build history and a workspace folder in which the code is checked out and built. So if I want to get the built app, I can grab it from:
~/.hudson/jobs/Amazing%20Game/workspace/build/Release-iphoneos/
Later we’ll look at packaging up the build and putting it somewhere handy, but for now, let’s make sure that it’ll pick up on changes in source control. Check out a working copy (if you don’t have one) of your project and put in a small change that will cause the build to break. This ought to do it:

Commit the change (or commit and push if you’re using a remote Mercurial server like I am) and wait for a minute. You may notice a message mentioning a ‘quiet period’ before the build kicks off properly. This quiet period is Hudson waiting after it detects a change in source control to make sure all changes have been committed – this is particularly useful with CVS, where every file is committed separately.
Ah, BOOM! Our build has failed nicely. And I got an email this time, which is nice
A broken build is something that shouldn’t be left broken, so let’s fix it and check the build comes back happily. Fix the code, push, commit, wait… success! Twitter and email confirm everything’s OK.
We’ve covered quite a bit so far so it’s probably a good time to take a break and see what we’ve achieved, and how that matches our goals from last week.
What works?
- Monitor source control (Mercurial and Subversion in my case), kicking off a build whenever changes are checked in.
- We’ll be able to manually kick off a build as needed.
- The build will grab all our source code from source control and build it in all relevant configurations – debug, release, simulator, device and so on.
- When the build is finished, it’ll notify people of the success / failure.
- There’ll be a handy location (web page most likely) where we can monitor / control the whole thing.
What do we still need to do?
- We’ll schedule a nightly build as well, just in case anything outside of source control has changed. This is fairly simple – an exercise for the reader!
- Copy a successfully built app to somewhere useful, preferably packaging it up with a provisioning profile in a zip archive, ready for emailing.
- Automatically update version numbers on our ‘stable’ build with each build.
- Bundle up the resulting builds with a provisioning profile and copy them to a shared folder.
- Start up automatically under when your build machine is booted.
- Paint a unicorn.
OK, plenty to work on, I’ll be back next week with some more detail, or if you’re keen have a crack yourself and let me know how you get on!
Related posts:
August 20th, 2010 on 7:34 pm
I think the zip issue might be Safari automatically extracting zip, but forgetting to rename it. Try downloading the zip with curl and then unzipping. I don’t have my mac with me so I didn’t try it.
August 20th, 2010 on 8:08 pm
I was downloading with Chrome, but it may be a similar issue. I’ll try that out – thanks for the suggestion.
August 22nd, 2010 on 12:45 am
On a second look, I see that you have actually linked to a war file, so in that case, it actually downloads the war file, and Chrome incorrectly appends a .zip extension to it. That’s why it works when you specify java -jar as argument the zip file name. Just rename the zip to hudson.war then, without extracting. This is either a bug in chrome or a misconfiguration in MIME headers on the webserver. I think the following is related: http://groups.google.com/a/chromium.org/group/chromium-bugs/browse_thread/thread/b7413d93610856e3/92def5101aea90bd?lnk=raot&pli=1
August 22nd, 2010 on 8:20 am
Hi Ustun,
That makes sense based on what I was seeing. Thanks for the help!
December 9th, 2010 on 5:43 pm
Hey George,
Just stumbled upon your post here. Fantastic stuff. I’ve done a ton of CruiseControl.NET based CI before and had heard only a little about Hudson. I’m super impressed by what you’ve demonstrated it can do. What made you decide to use Hudson over CruiseControl?
While I’m not at the point where I need to be worrying about CI for iOS builds, when I do I’ll be referring back to your article. Great job!
December 10th, 2010 on 12:49 pm
Hey Gavin,
I’m glad the article was useful for you. I’ve used CC.Net before, and it’s a good tool. However setting up XML config files is a pain. Hudson is all setup through the web front end. Adding plugins is trivial, and one thing I like is how easy it is to take an existing project and creating a new cloned project.
I agree that CI can be overkill for iOS work, especially if you’re a sole developer. However, using Hudson to generate AdHoc builds is well worth your while, especially when combined with agvtool. A fiddly, error-prone process suddenly becomes a one click job. Magic!
December 27th, 2010 on 6:00 am
I had never heard of agvtool – it looks awesome. Thanks again for the great post!
August 3rd, 2011 on 6:58 am
I am totally new to this. I am not an iOS developer and have no idea what xcode is but I have been given a task to create a continuous integration build on Hudson. I tried following these steps but it failed. This is foxing me:
xcodebuild -project otsync.xcodeproj -target otsync – configuration Debug
I have a folder in the project source called otsync.xcodeproj which is the only thing with xcodeproj I could find. Am I doing this right?
August 20th, 2011 on 9:02 pm
Hi Richard,
Sorry, I’ve been a bit slack and only just seen your question. As typed, there is an extra space between ‘-’ and ‘configuration’ which I’m assuming is just a typo.
As for why this isn’t working, it’s not immediately obvious. Can you load this project in XCode by double clicking the otsync.xcodeproj? If you can load this project in XCode and compile from there, the Hudson side of things should be fairly straight forward…