How to build a specific SVN (Subversion) revision in Hudson and Jenkins

Think about a scenario where you are working on some functionality of a project and committed a partially completed functionality to the subversion (probably because you were told Commit Early, Commit Often for continuous integration if you are working on an agile team). Now, you don’t want to, however, build and deploy the latest code to your test environment because some of the features are not ready yet. You are still working on those. In that case, if you need to do a build, you might wonder how to run a build from old and probably stable revision in your repository.

This is exactly what I am going to show you here.

I am hoping you are already using a subversion plugin to checkout the code, if not the plugin is available for Hudson at the following URL. Jenkins also has similar plugin.

http://wiki.hudson-ci.org/display/HUDSON/Subversion+Plugin

Once you have installed this plugin, go to ‘Configure’ your Hudson Job and scroll down to Source Code Management section. Underneath subversion in that section (see the picture below), there is a field where you specify the repository URL. If you provide the plain URL to your subversion branch/trunk/tag, it will always pull the latest code from that branch/trunk/tag.

But you want to specify a specific revision,then you can append @revision at the end of the url. Where ‘revision‘ is your actual revision number.

For a fictitious svn url below, Hudson will always pull the latest code from the forexpro branch.

https://svn.icodejava.com/branches/forexpro

If you just need a revision 234, then the url you specify here would be

https://svn.icodejava.com/branches/forexpro@234

There are also other parameters that you can pash to this URL.e.g.

https://svn.icodejava.com/branches/forexpro@HEAD

The above url builds with latest revision in the repository.

https://svn.icodejava.com/branches/forexpro@BASE

The above url builds with the the revision number of an item in a working copy. If the item has been locally modified, this refers to the way the item appears without those local modifications.

https://svn.icodejava.com/branches/forexpro@COMMITTED

The above url builds with the most recent revision prior to, or equal to, BASE, in which an item changed.

https://svn.icodejava.com/branches/forexpro@PREV


The URL above builds with the revision immediately before the last revision in which an item changed. Technically, this boils down to COMMITTED-1.

N-Things You Can Do With Continuous Integration Tools Hudson and Jenkins

Hudson (or Jenkins) is a great tool for continuous integration. Once I learned about it and started doing continuous builds and integration for my projects using hudson, I am simply in love with it. It is so flexible, light weight and does a variety of things. With over 400 different plugins available at their update website (see Jenkins Plugins Page and Hudson Plugins Page) , you can extend your base installation of this tool to do a variety of things.

If you still evaluating why you or your company needs this tool, here are a few things I noted down that you can look at to make your decision. This is by no means  a complete list of items. Hudson and Jenkins are far more powerful that just doing the items that I have listed below.

  1. Poll subversion for any changes and trigger a build if any new changes are available.
  2. Tag the release back to subversion.
  3. Schedule Ant or Maven builds based on cerain triggers such as code change or time,
  4. Trigger another build when one build completes.
  5. Trigger a build when Maven dependencies have been updated by Maven 3 integration
  6. Trigger a build when Maven SNAPSHOT dependencies have been updated externally.
  7. Build a project after another project is built.
  8. Automatically reschedule a build after a build failure using “Naginator Plugin”
  9. Build a project with Parameters via “Parameterized Trigger” plugins. The parameters passed could be for example, build label etc.
  10. Run your JUnit Tests automatically and get a nicely formatted graph
  11. Run the code coverage (Clover, Emma or Cobertura) automatically and get a nicely formatted graph
  12. Configure to run Checkstyle for capturing the code formatting issues and present the output in a nicely presented graphs.
  13. Look at the list of recent changes that were made on subversion by revision numbers.
  14. Copy the build artifacts to FTP, SCP, Network folders or other local folders.
  15. Run automated Tests using Cucumber
  16. Run automated tests using QTP
  17. Code Quality Metrics via “Violations” plugin.
  18. Run multiple builds in parallel.
  19. Send a list of people an email (Can be customized) when the build fails, is successful or has JUnits failing.
  20. Group your build jobs on different Views that are displayed as tabs.
  21. View quickly what builds are currently running.
  22. Look at the build history for build time taken, build status etc.
  23. Look at the console output of the build that is constantnly updated via Ajax calls.
  24. View the disk space usage.
  25. View the build time trend graphically
  26. Integrate Hudson Build With Sonar – via Sonar Plugin
  27. Run the build from web – no more kicking the builds from consoles or terminals.
  28. Secure the hudson access via LDAP. Users and user permissions can be added, modified or removed to finer levels.
  29. Run the hudson server itself as a service.
  30. Limit the maximum number of builds to keep on the server.
  31. Monitor your build via iPhone app – “Hudson Helper iPhone app”
  32. Monitor your build via RSS

Configuring Hudson Java Memory Settings When Running It As A Service

The default hudson installation as a windows or linux service is configured to use 256MB of system memory. While the memory might be good enough to start with, it might not be high enough to do complex or larger builds. If your application build process is memory intensive, you will probably start seeing the build failures with Hudson complaining about heap space.

For example, when I try to run the Cobertura code coverage, which is a memory intensive process as it requires loading of several thousands of JUnit XML reports for my fairly large project, into the Hudson server that is running as a service, here is the exception stack trace that I encountered.

Publishing Cobertura coverage report...
Publishing Cobertura coverage results...
FATAL: Java heap space
java.lang.OutOfMemoryError: Java heap space
	at com.sun.org.apache.xerces.internal.util.XMLStringBuffer.append(XMLStringBuffer.java:205)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.refresh(XMLDocumentScannerImpl.java:1522)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.invokeListeners(XMLEntityScanner.java:2070)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipChar(XMLEntityScanner.java:1415)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2793)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
	at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
	at javax.xml.parsers.SAXParser.parse(SAXParser.java:198)
	at hudson.plugins.cobertura.CoberturaCoverageParser.parse(CoberturaCoverageParser.java:81)
	at hudson.plugins.cobertura.CoberturaCoverageParser.parse(CoberturaCoverageParser.java:52)
	at hudson.plugins.cobertura.CoberturaPublisher.perform(CoberturaPublisher.java:265)
	at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:36)
	at hudson.model.AbstractBuild$AbstractRunner.perform(AbstractBuild.java:630)
	at hudson.model.AbstractBuild$AbstractRunner.performAllBuildSteps(AbstractBuild.java:608)
	at hudson.model.AbstractBuild$AbstractRunner.performAllBuildSteps(AbstractBuild.java:584)
	at hudson.model.Build$RunnerImpl.post2(Build.java:159)
	at hudson.model.AbstractBuild$AbstractRunner.post(AbstractBuild.java:553)
	at hudson.model.Run.run(Run.java:1391)
	at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46)
	at hudson.model.ResourceController.execute(ResourceController.java:88)
	at hudson.model.Executor.run(Executor.java:145)


Where does hudson define the memory settings for the service?

The memory settings for service are generally located in hudson.xml file in the same directory as your hudson.war.

Here is what a default memory configuration looks like (the content is formatted to remove the comments)

<service>
  <id>hudson</id>
  <name>Hudson</name>
  <description>This service runs Hudson continuous integration system.</description>
  <env name="HUDSON_HOME" value="%BASE%"/>
  <executable>java</executable>
  <arguments>-Xrs -Xmx256m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "%BASE%hudson.war" --httpPort=8080</arguments>
  <logmode>rotate</logmode>
</service>



How the change the memory setting?

Just by looking at the hudson.xml file above, you must have noted that the memory settings are located in the element.

Edit the arguments to change the memory. For example, if you want the hudson to run with 1GB memory,

replace -Xmx256m with -Xmx1048m

Make sure to restart the hudson windows service once you have made the changes.