Fork me on GitHub
Showing posts with label hudson. Show all posts
Showing posts with label hudson. Show all posts

3 May 2010

Building your app on Hudson with Multiple Grails versions

For my Grails plugins I generally write a test project (or more than one). I thought it would be useful to be able to run these against multiple versions of Grails on my build server so I can spot any incompatibilities with the versions the plugin is supposed to support.

Using Hudson this turned out to be pretty straightforward.

You will need all the Grails versions you want to test against installed on your Hudson box. I put them in /opt so replace that with wherever you have them in the steps below. Also, if you want the builds to run in parallel and will be running any functional tests you'll need the Hudson Port Allocator plugin.

  • Start by creating a new job in Hudson and choosing "Build multi-configuration project".
  • The configuration dialog has an extra section "Configuration Matrix" where you can set up the different config combinations that will run. We're just interested in varying the Grails version so check the "Axes" and create a new axis named "GRAILS_VERSION" with the different versions you want in the "values" box, e.g. "1.2.0 1.2.1 1.2.2 1.3.0.RC2"
  • Set up your source code repository and build triggers as you would for any other project.
  • If you want to run the builds in parallel and are running any functional tests you will need to make sure that Grails starts up on a unique port. In the "Build environment" section add a new "Plain TCP port" named "GRAILS_PORT". If you're running anything else that needs a port such as a Selenium server you'll need one for that as well.
  • Add an "Execute shell" build step. Unfortunately the Hudson Grails plugin does not allow you to use a variable to specify the Grails version so you'll have to go old-school:
    export GRAILS_HOME=/opt/grails-$GRAILS_VERSION
    export PATH=$GRAILS_HOME/bin:$PATH
    # assign Grails a unique port (you can skip this if you're only running unit/integration tests)
    export JAVA_OPTS="$JAVA_OPTS -Dserver.port=$GRAILS_PORT"
    grails clean
    grails upgrade --non-interactive
    grails test-app --non-interactive
  • Check "Publish JUnit test result report" in the "Post-build Actions" section and specify target/test-reports/*.xml as the "Test report XMLs"

When you run the Hudson job you should see it kick off one sub-job for each Grails version. Each will check out the project, upgrade it to the relevant Grails version and run the tests.

I have my plugin test projects triggered by the plugin build and have them grab the plugin zip itself from the archived artefacts in the plugin's Hudson job. So I've added this before the grails test-app step:
grails install-plugin http://my.hudson.server/hudson/job/my-plugin/lastSuccessfulBuild/artifact/my-plugin-1.0.zip --non-interactive
There's a bug in Grails 1.3.0.RC2 that means you will need to split this into a wget followed by installing the zip from a file path rather than a URL. This is fixed in trunk so won't be a problem in Grails 1.3 final.

If you're using SVN I think you may need to revert any changes the grails upgrade has made to application.properties, etc. otherwise you'll get merge conflicts on the next run. This does not seem to be a problem with Git.

11 Mar 2010

Grails plugins on Hudson

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.

2 Nov 2009

Git and Hudson

I just encountered a rather annoying problem when running Hudson as a service on Ubuntu. I was getting the following exception whenever the build checked code out of GitHub:
hudson.plugins.git.GitException: Could not apply tag hudson-Selenium_RC_Plugin-23
 at hudson.plugins.git.GitAPI.tag(GitAPI.java:265)
It turns out Git needs a username to be set and the hudson user that the Debian package creates when Hudson is installed doesn't have one. Easily fixed by using sudo nano /etc/passwd to add Hudson,,, into the hudson user's entry (if you look at your own entry you should see where it needs to go).