Saturday, 25 July 2009

Hudson for Java and Windows builds

Sometimes you might have both .Net and Java projects in your organization. When this happens you'll probably want to have a unified build server to display the outcome of all CI builds. Hudson has wonderful support for all aspects of Java building and also has some great integration for NAnt/NUnit/MSBuild/MSTest and even NCover for your .Net code coverage needs. This is great when you're building all your apps on the same OS but what happens when you want to build your Java apps on linux? Well Hudson has a solution for this too, Distributed Builds. This allows you to run a single master Hudson node with any number of slave nodes, which can all be different OS, Java/.Net versions, any configuration you want really.

Setting this arrangement up is very simple.

(This example describes setting up a Java master on linux and a .Net slave on Windows)

(On the master)
  • Install and start Hudson on the master box ( http://wiki.hudson-ci.org/display/HUDSON/Installation+and+Execution )
  • Create a node (Manage Hudson -> Manage Nodes -> New Node), the node name needs to be the ip or dns of the slave box and lauch should be via jnlp. Make sure usage is set to "Leave this machine for tied jobs only" or Hudson might start trying to run Java jobs on your windows box.

(On the slave)
  • Open a browser and go to the following url http://<ip>/computer/<node>/ (e.g. http://infrastructure.mycompany.com/hudson/computer/10.0.0.56/)
  • Click the big orange launch button
  • (One extra step if you want is to install the slave as a windows service. There is a menu option to do this on the slave agent window that opens on the slave box.)

And thats it, create your .Net jobs just like Java ones but make sure you check the "Tie this project to a node" option and select your .Net slave node.

NAnt, NUnit, MSBuild, MSTest and NCover support is available from the plugins menu.

Now at this point I should tell you about the gotcha. NAnt support doesn't seem to work when you run Windows as a slave service as the options for specifying tool locations (NAnt etc) only stretches to Java tools. If someone has managed to make it work please let me know. The workaround is to not use the NAnt support and use Windows batch commands, just enter the command you would do at a terminal window to run the build and Hudson will do it for you, simple :-)

Tuesday, 7 July 2009

Feedback is king

Have you seen these symptoms:

  • @ignore
  • maven.test.skip=true
  • Tests commented out

If so then you've probably been working on a project thats suffering from a lack of feedback.

Since the early 00's we've had the term "Continuous Integration", the essence of which being integrate often so you don't get a nasty surprise at the end. The problem here is that feedback is essentially a synchronous process, i.e. you have to be there to receive that information. Lets assume we've gotten into the healthy habit of atomic commits, say approx every 30 mins, how long are you prepared to wait to see if you've broken anything, 2 mins? 5 mins? What if your build process takes 60 mins? Would you wait? Probably not. In this situation one of two things tend to occur.

1.) Checkins continue at the same rate, which means that two subsequent checkins occur before checkin 1 has been tested. This usually means lots of wasted time reverting changes when bugs have been introduced.
2.) Checkin numbers are reduced to keep up to date with the build cycle, this causes more integration issues as the codebase across the team is out of sync for longer.

Eventually people stop relying on the build as an indication of stability and this is when you start seeing the aforementioned symptoms.

This almost certainly leads to brittle code, a decrease in velocity, an increase in bugs and a heavy reliance on manual testing.

So remember that builds need love and care to make sure they're as efficient as possible. Spend time making sure that heavy weight acceptance tests run in a separate target to your unit and integration tests and that your integration layers and tests are as thin as possible to make the rest of your code as light, as supple and as rapidly testable as possible.