Yesterday I spent some time setting up
Hudson continuous integration build for my various Grails plugins. It was pretty straightforward but I've
been asked to document the steps involved.
Each plugin has one or more test applications under
test/projects
each of which has
grails.plugin.location.whatever = "../../.."
in
BuildConfig.groovy
. So each plugin CI build needs to run not only the plugin's own unit tests but any integration and/or functional tests included in the test apps as well.
Hudson plugins
I installed the essential plugins I would need:
- The Grails plugin makes building Grails projects much easier and allows you to build against multiple versions of Grails.
- The Git plugin enables Hudson to pull from a Git repository such as GitHub.
- The GitHub plugin adds links to the GitHub project in the Hudson build.
- The Chuck Norris plugin encourages you to keep your tests from failing.
Configuring Grails
Under
Manage Hudson -> Configure System there is a
Grails Builder section where I entered the name and path of the various versions of Grails installed on the build box.
Connecting to GitHub
In the project configuration:
- I pasted the GitHub project URL in the Github project field (shown if you have the GitHub plugin installed).
- Under Source Code Management I selected Git then pasted the read-only repository URL into the URL of repository field.
- I entered master in the Branch Specifier field as I've seen Hudson do odd things picking up changes from other branches before. I don't really need this behaviour and haven't had time to investigate it further yet.
- I ticked Poll SCM under Build Triggers then set a cron expression of
*/5 * * * *
so Hudson will poll GitHub every 5 minutes.
Grails build steps
- Select Build with Grails from the Add build step drop down, then:
- Select the Grails Installation you want to use.
- Enter the Targets to run. These are the Grails commands that Hudson will execute. For example, I entered
"test-app unit: -clean --non-interactive" package-plugin
for the to run unit tests then package the plugin. The quotes allow arguments to be passed to individual targets so I'm telling the test-app phase to build clean and run non-interactively (i.e. Grails won't ask about things like installing or uninstalling plugins).
- The other fields can be left blank for now.
- Add further Grails build steps for test applications. The only difference in configuring these is that the targets will likely be different and Project Base Directory needs to be set to the relative path where the test apps lives, e.g.
test/projects/content-caching
Isolating each build
One thing I found is that it's probably a good idea to specify separate working directory for each build. I found that simultaneous builds would stomp over each other's compiled classes otherwise. This is particularly an issue for me where I have a build for the
Selenium RC plugin whilst one of the test apps for the
Springcache plugin uses the latest
Selenium RC release to run tests.
Hudson provides various
environment variables so I just set
grails.work.dir to
/tmp/.grails/${JOB_NAME}
in every case.
The other consideration is the port that Grails applications will use. If you are running any kind of functional tests the Grails application will start and it each Hudson job needs to use a separate server port or simultaneous jobs will experience port contention. The server port is also configured in the Grails build step. I've just assigned a different one to each job but I couldn't think of a particularly clever way to automate the port assignment.
Test reports
Under
Post-build Actions I ticked
Publish JUnit test result report then entered a comma-separated set of paths to the XML reports generated by each build step. For example, the
Springcache plugin has the following reports configured:
target/test-reports/*.xml,test/projects/springcache-test/target/test-reports/*.xml,test/projects/content-caching/target/test-reports/*.xml
That's picking up the root plugin's unit test reports and the reports generated by the
springcache-test and
content-caching test applications. Hudson does a good job of merging these together into a unified test report.
Running tests that need a browser
Some of my tests use
Selenium RC which drives a real browser. Given that Hudson is running on a headless box I had to get the display exported to a box with an X Windows environment.
Still to do
Right now all the plugins are building against Grails 1.2.1 only so the next task is to set up parallel builds using Grails 1.3-RC1. Ideally I would like to use Hudson's multi-configuration project capability to do that but I haven't had a chance to look into it yet. I'd also like to use Gradle to build the various project with one build step but I'd lose the convenience in switching Grails versions that the Hudson Grails plugin gives me.