In this tutorial series we will explore a rarely discussed (but highly valuable) process of developing software that is disappointingly absent in the iOS and mobile world: Continuous Integration.
Also available in this series:
- Continuous Integration: Series Introduction
- Continuous Integration: Tomcat Setup
- Continuous Integration: Hudson Setup
- Continuous Integration: Scripting Xcode Builds
- Continuous Integration: Script Enhancements
Where We Left Off
In part 1, we discussed the concept of Continuous Integration and how it can assist us in developing software faster. In part 2, we demonstrated how to install "Apache Tomcat", which is the web server that will host our CI software.
Hudson is an open-source Continuous Integration server written in Java. It is one of the more popular CI servers used alongside Jenkins and Atlassian's Bamboo. We're using Hudson because:
- It's easy to install and configure.
- It's easy to use.
- Robust plugin support is available.
- It's free!
Hudson is currently maintained by Oracle, who has stated that they intend to continue support and development for Hudson with the community.
What Does Hudson Do?
Hudson plays an important part of the CI process. It monitors the code repository and continually checks for updates. Once it determines there has been an update, it will do an update/pull and start the build. It is important to note that Hudson is not responsible for the build action itself. It can only call a script (which we will write) that will do the building and archiving. Once the script has started, Hudson will monitor the script. If it fails, it will report a broken build.
Step 1: Download And Install Hudson
Setting up Hudson is very easy. First, navigate to Hudson's website at http://hudson-ci.org/, and then click the download link for the latest production version (2.1.2 at the time of writing) this will download a *.war file.
Once the download is finished, rename the file to "hudson.war" and put the file into Tomcat's "webapps" folder:
mv hudson.war /usr/local/tomcat/webapps/
If the server is currently running, restart it by running the shutdown script, wait a few seconds, and then run the startup script again. When that's done, open a browser and navigate to:
Hudson will tell you that it's setting up. Once it's done, you'll see the main screen of Hudson.
Step 2: Create Your Project
Now that Hudson is up and running we need to set up a project or "job". This job will relate to a project that we want to add to our CI.
This 'job' will be responsible for monitoring our repository, staying up to date and building the project. Click on new job and enter your project/app name as the job name. Select "Build a free-style software project" as the type of job. This will give us the flexibility to customize the job to our needs. Click "ok" when you're done.
Next, we need to set up the project settings. The important sections on this page are "Source
Code Management", "Build Triggers", and "Build".
Step 3: Set Up Source Code Management
In "Source Code Management", we choose what type of repository we are using and se the URL. In this example, I'm using GIT, but Subversion follows the same process.
Be aware that the way you connect to your repository will define how this section is set up:
You may run into a problem if you use HTTPS (username and password) to connect with a GIT repository. Currently, Hudson does not easily support password authentication for GIT.
For those using SVN, simply enter in your repository url and it should prompt you for a username and password. For GIT users, try entering in details like this:
This should work for you unless you have an '@' symbol in your password, in which case you will not be able to use HTTPS for your authentication, you will have to use SSH.
If you use SSH (using private/public keys) then you will need to make sure you generate an SSH key for your build server and add it to your repository manager.
You will also need to make sure that the repository servers RSA fingerprint is added to the list of known hosts prior to starting your builds. The easiest way to do this is to connect to the server via SSH:
ssh -T firstname.lastname@example.org
You should see something like this:
Don't worry if you see an error like the one above after you have added the RSA fingerprint to your list of known hosts. This usually means that the server doesn't allow shell access. The important thing is that we can connect and we know the identity of the server.
Step 4: Set The Build Trigger
We need to tell Hudson when we want the build to begin. We're going to poll the repo every minute to see if there has been a change.
Check the "Poll SCM" box and enter (as per the below image):
* * * * *
You don't have to poll it every minute. If you want to change it to only do it daily, or hourly, you can set that too. Keep in mind though, that the more often we poll the repo the more continuous our process will be.
Step 5: Add The Build Command
Lastly, we need to compile the project and export it where appropriate. To do this, we need to add a build step in the build section.
Click on the 'Add build step' button and select "Execute Shell". We will then add a command that executes the build script from within the project directory (We haven't added this yet, we're going to do that later).
The '$Workspace' string in the above picture refers to the working directory of the project as it exists in Hudson. This is the top level of your repository.
When you're done, click "save". You will be taken to the main build screen and after a second or two you will see your project do its first build!
Step 6: Watch The Build Fail
After you've saved your project settings, you will be taken back to the Jobs dashboard. After a few seconds, you will see a build start up. Click on the little terminal icon to see the output of the build.
We can see what hudson is doing. It detected a change in the SCM (in this instance it's the first connection) and proceeds to checkout the repository code into the workspace. It does all this successfully, however it fails when it tries to execute our build script.
We can see from the output that it failed because the build script file doesn't exist yet. Let's add that to our project and commit it to the repository.
Step 7: Update The Repository
Add a folder called 'Scripts' into the top level of your repository. Once created, use any text editor to create a file called "build_script.sh" in the "Scripts" folder with the following text:
#!/bin/sh echo “We'll build later :)”
All this script does is print out a string to the command line. We'll cover how to build your project next tutorial but for now we just need to add the script into the repository.
Once the file has been created add it to your repository. After a minute or so you should see Hudson start a new build. Click on the terminal icon to view the output.
All going well you should see something like the following:
Now that the file exists, the build doesn't fail. If you look closely you can also see the output of our script on the 3rd last line.
Step 8: Explore Hudson
Before we finish up, it's important to explore a few features of Hudson.
Where Hudson keeps the files
If you ever want to see the hudson folder, look under the hidden folder ".hudson" in your user folder. You can access it by selecting go->go to folder' (in finder) and entering:
This is where the magic happens. All your code is kept in a workspace folder under the relevant job. For my project (AwesomeApp) the code would be kept in:
It is important to understand where the files are located within Hudson's directory. You may have an ignored file that you need to manually add or an SVN issue that you need to repair.
The project dashboard allows you to view all sorts of information thats useful for monitoring the health of the build. You can see a log of the recent changes (including a change that recently broke the build).
You can also explore the workspace from the browser and view the files currently in the workspace.
Hudson can notify you of the result of a recent build in any number of ways. It maintains an RSS feed that you can point monitor, it can send you emails, there is even a plugin to make it talk! When you have some time have a look at configuring Hudson to use these features.
In the next article we will go through writing the build script that will compile and sign your code into a .ipa file ready to be installed onto an iPhone or iPad. We'll cover bash basics, the commands used and how to overcome common pitfalls. Catch you next time!