Automated Builds Made Easy with Hudson
By Tom Wheeler, OCI Senior Software Engineer
Nearly any software project will have its share of build problems. As a project grows larger, errors that "break the build" tend to increase — and unfortunately tend to have a greater impact on the project's quality. Finding the source of integration problems becomes harder as time elapses between when developers commit code and that code is built as a single entity. As Martin Fowler points out in Continuous Integration, an automated build process is essential to reducing these integration problems.
Given that most experienced developers recognize that having a consistent and repeatable build process is a cornerstone of configuration management, one wonders why their implementation is not universal.
One reason might be that setting up an automated build system seems like a lot of work, and is perhaps a task better suited to an experienced system administrator than a software developer. I'd like to dispel those myths by demonstrating how any developer can easily set up an automated build with Hudson. In fact, assuming you've already installed a Java servlet engine like Tomcat, I'll show you how to have it running in less than ten minutes.
- About Hudson
- Installation and Configuration
- Implementation Notes
- Setting Up A Project
- Convenient Configuration Management
Hudson is an open-source project licensed under the MIT license. Broadly speaking, it's actually an application that monitors the status of a recurring task, such as a script to run under the operating systems task scheduler. However, it contains a continuous integration system that provides a Web-based interface for configuring, executing and viewing software builds, and that capability will be the focus of this article.
Hudson can be seen as a competitor to other continuous integration tools such as CruiseControl or Continuum. Since no single system is likely to meet every developer's needs, you'll need to compare the features that these tools offer with your project's needs in order to determine which is the best for you. This comparison of continuous integration tools is probably the most comprehensive one around. Unfortunately it does not yet contain information about Hudson, but I'll describe many of Hudson's features in a moment.
Hudson can be configured to start a build in several ways, including:
- On demand
You can start a build whenever you like by simply following the "Build Now" link from the project page of your Hudson Web site.
- Fixed interval
Like the Unix cron system, Hudson allows you to schedule a build to run at fixed intervals, such as every ten minutes, every hour or every Sunday at 8:00 P.M.
- Source Code Management (SCM) Polling
Hudson can detect changes to your project by polling your CVS or Subversion server at a fixed interval. This creates some additional load on the SCM server, but its advantage is that it won't produce a build unless something in your project actually changed.
The Hudson build documentation also describes how you can set up a build to start by e-mail.
Hudson currently works with the popular CVS and subversion source code management systems and can build projects using Ant, Maven, Windows batch files or UNIX shell scripts. Following a successful build, it can execute additional actions, such as archiving build artifacts, publishing javadoc and test results and sending e-mails to notify others that the build is complete.
The fact that Hudson is Web-based is convenient since it allows any interested party to easily check on the status of the builds. And since it can archive output from previous builds, it provides a ready repository of different software versions that you can use for regression testing.
You can easily monitor your builds by viewing the project's page on your Hudson Web site, but it's always nice to have other options. Java Posse host Tor Norbye points out that Tom Ball and Jesse Glick created a plugin for the NetBeans IDE that shows you the status of your builds right from the IDE's status bar (I was unable to find a plugin for Eclipse or IDEA). Perhaps more adventurously, Hudson developer Kohsuke Kawaguchi created a USB-based lamp to monitor build status.
It's true that Hudson does lack some of the more complex features of older automated build tools, such as the ability to work with obscure SCM tools or the ability to send build status updates via IRC. Perhaps more importantly, it's thoughtfully designed and very easy to use. And it's possible to extend Hudson's capabilities by writing a plugin. Now that I've explained some of the basics of what Hudson can do, it's time for me to show you how to set it up.
Installation and Configuration
This section assumes you've already installed the Java Development Kit, Apache Ant and a servlet container such as Apache Tomcat. My server is configured to listen on the default port for Tomcat, so the server is accessible at the URL
http://localhost:8080/. Adjust the URL as needed if your configuration differs.
- Software Versions Used
I used Tomcat version 5.5.20 and Hudson version 1.64; these were simply the latest versions available at the time of writing and Hudson should work just fine with any recent version of Tomcat or other servlet container.
- SCM Details
For the purpose of this example, I imported a copy of the JScience project source code into my local CVS server — you will need to replace the specific CVS details shown in my example with the proper ones for your own project.
- User/Environment Settings
The simplest possible way to set up Hudson is to run the servlet container under your own account on your development workstation, which is what I did for this article. This will ensure that your PATH will contain your build tool, JDK and
.cvspassfile. However, this approach is somewhat less secure for a shared machine, so an alternative is to simply set the Ant, JDK and
.cvspasspaths from the main Hudson configuration page.
Setting Up A Project
The following steps show how you can have Hudson running an automated build in under ten minutes:
- Download the Web application archive (WAR) file from the Hudson Web site.
- Optionally, you can set the
HUDSON_HOMEenvironment variable to specify the directory under which builds are done. It will default to a directory inside the servlet container, but you might wish to change it to to a filesystem with more available disk space.
- Deploy the
hudson.warfile to your server and then open a browser to your Hudson installation's site: http://localhost:8080/hudson/. You'll see Hudson's main page, as shown below:
4. Click the "create new jobs" link.
5. Type a name for your job (project). This name is used as an ID and will be part of a URL, so you may wish to avoid using spaces here. Since the name will be used in hyperlink text on the main Hudson page, it should also be brief, yet as descriptive as possible. For my job, I will use the value "jscience_dist_head" to indicate that it is going to build a binary distribution of the JScience project based on the source code on the HEAD (trunk) in CVS.
6. Ensure that the "Create new job" radio button is selected, and that the "Building a software project" option in the dropdown list is selected, as shown below. Next, click the "OK" button.
7. Enter a free-form description of your project in the description field.
8. Choose the "CVS" radio button in the "Source Code Management" section and then specify the following details:
- The CVS module you want to build
- If you want to build a branch other than the CVS HEAD, specify the branch name
9. Check the "Poll SCM" box in the "Build Triggers" section, which will expand to give you a field to type in the schedule. The format of this field is nearly identical to the UNIX crontab format, but like most input fields in Hudson, you can click the blue question mark icon adjacent to the field to see a detailed description. I am going to enter
*/5 * * * * to signify that my source control system should be polled every five minutes. Again, polling creates additional load on the CVS server, so you should use a conservative value here at first and then lower it in small increments once you're sure of how your server will react.
In order to avoid starting a build while you're still committing changes, Hudson will wait after polling until the end of a "quiet period" before starting the build. This quiet period is five seconds by default, but you can override the value for this build by clicking the "Advanced..." button above the Source Code Management section. You can also set it globally on the main Hudson configuration page.
10. Check the "Invoke top-level Ant targets" box in the "Build" section and then type the name of the Ant target you want to run. You can run multiple Ant targets by separating their values with a space, such as
test javadoc dist. For the JScience project, I will use the "distribution" target, which creates source and binary ZIP files complete with javadoc.
11. Click the "Save" button.
You're all set — you can start a new build manually by clicking the "build now" link on your project's page. Since you set up SCM polling, you could also make a change to a file inside your project and commit it to CVS. Within five minutes, Hudson will detect the change, check out the code from CVS and start a build.
Convenient Configuration Management
The page for any project in Hudson will show the most important details about the project, such as information about recent changes and history of recent builds.
After you've produced at least one build, Hudson will be able to detect what's changed since the previous one. For example, I made a minor change to the file
src/org/jscience/JScience.java and then committed it to CVS using a commit log message of "fixed bug #6493." Hudson noticed it a few minutes later and created a build that included this change. Afterwards, the page for that build lists this change:
This page also contains a detail link that can show you exactly who committed the change, as well as the specific file and revision committed. This will help you to produce reports about what new features or bugfixes have gone into a new release.
The working directory for your most recent build (called the workspace) will also be linked from the page, allowing you to view and download any file that was used in — or produced by — that build. Hudson can also store a "fingerprint" (checksum) of each file, which will help you identify the build in which a given JAR file originated.
Depending on the options you chose when configuring the build, you might also have links to items such as unit test reports or javadoc from the project page.
Finally, one of the nicest features is the ability to tag all the files that went into a given build. It's even smart enough to remember which specific revisions were used, so that you can reliably tag files even though they were checked out on the HEAD and have subsequently changed.
Since this article can't describe every single feature Hudson offers, I encourage you to look around your Hudson installation and experiment to see what's available.
Continuous integration can help you identify build problems faster, enabling you to produce better software in less time. Though there are a number of automated tools available, I've shown how Hudson is one of the most innovative. It works well with popular tools like Ant, Maven, CVS and subversion, and its intuitive Web-based interface makes it simple for any developer to set up and managee an automated build process.
Tom Wheeler would like to thank Mario Aquino and Jeff Brown for their help in reviewing this article.