Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in /homepages/13/d92059571/htdocs/jeremymurray/inc/parser/handler.php on line 1458

Hudson Plugin Modifications

After learning a bit about groovy, it has become a bit of a catch-all for Hudson related tasks mid-build. Most of my investigation with it previously was with the groovy-postbuild plugin, but I wanted to be able to do some updates to the job immediately after the build started. This began a bit of a dive into the groovy plugin and into the Hudson plugin authoring setup, but it wasn't that hard in the end.

Note that the install steps are for windows, but the tools are available for Windows, Linux, and OSX and the basic steps are all the same (it is Java and Maven, after all).

Missing Functionality

  • The groovy plugin can run scripts on either the slave or the master. On the master, it has access to the Hudson instance in code, but it has no handle to the current build. The wiki shows ways of figuring it out via requesting the latest build by string name, but that is not reliable in a concurrent build job.
    • Expose current build to groovy script.
  • Most of my builds are initiated manually. I would like to send an e-mail to the initiator at the build start and at the end, along with notification of the build's success or failure. The submitter's e-mail address is currently an optional parameter, but it can be found via LDAP.
    • Expose submitter's e-mail to build.
  • There seems to be a lot of trouble getting the parameters of parameterized builds in a groovy script.
    • Verify that build parameters can be accessed by groovy script.

Getting the current build is a prerequisite for the other functionality, so I decided to start by getting the source for the groovy and groovy-postbuild plugins to see how the build could be exposed.

Plugin Source

Install:

  • Git
    • For windows, grab the latest msysgit (Git-1.7.3.1-preview20101002.exe) from msysgit downloads

Get the source:

Build A Plugin

Install:

  • Java 6 SDK (JDK)
    • For windows, grab the latest Java 6 JDK (jdk-6u23-windows-x64.exe) from Java Downloads
      • If you're having trouble finding it, search for “Java Platform, Standard Edition” then look for the button labeled “Download JDK”
    • For windows, this default installs to to C:\Program Files\Java\jdk1.6.0_23
  • Maven 2
    • Grab the latest maven 2 binary zip (apache-maven-2.2.1-bin.zip) from Maven Downloads
    • For windows, unzip it to C:\Program Files\Apache Software Foundation\apache-maven-2.2.1
    • Maven connects to the internet to download dependencies. If you have trouble running maven, especially if you are behind a fire wall, refer to the reference section for help.
  • Update environment variables either permanently or by running each line below prefixed with set on windows or export on most linuxes, adjusting the paths as needed
    • JAVA_6_HOME=C:\Program Files\Java\jdk1.6.0_23
    • M2_HOME=C:\Program Files\Apache Software Foundation\apache-maven-2.2.1
    • M2=%M2_HOME%\bin
    • MAVEN_OPTS=-Xms256m -Xmx512m
    • JAVA_HOME=%JAVA_6_HOME%
    • PATH=%PATH%;%JAVA_HOME%\bin;%M2%

Build the plugin:

  • cd into a plugin directory - it will have a pom.xml file
  • If you have made any modifications, update the version in the pom.xml file
    • e.g. <version>1.6-SNAPSHOT-PLUS_BUILD</version>
  • mvn install -Dmaven.test.skip=true
  • If all goes well, the build will eventually report: [INFO] BUILD SUCCESSFUL and produce a new plugin.hpi file in a target subdirectory.

Install a Plugin

Updating Hudson's groovy Plugin

Searching through the groovy plugin source, it looks like the perform method is the starting point for execution. It even takes a build as a parameter, so we probably just need to pass that through to the groovy script.

|h hudson-plugins/groovy/src/main/java/Hudson/plugins/groovy/SystemGroovy.java
...
public class SystemGroovy extends AbstractGroovy {
...
    public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
...
        shell.setVariable("out", listener.getLogger());
        shell.setVariable("build", build);              // Add this line to expose this specific build to the script.
...

This should now give us access to the current executing build via the build variable in a groovy script.

Testing the New groovy Plugin

|h Test Groovy Job - Build Number
println ("This is build number: " + build.number)
  • Save the changes and select “Build Now”
Test Groovy Job - Build Number - Results
Started by user murrayjw
This is build number: 1
Finished: SUCCESS

With the current build exposed to groovy, we should be able to get the rest of the information we were looking for.

Accessing the Submitter E-Mail Address

For the submitter's e-mail address, we first need to be sure the build was caused by a user selecting Build Now. If it was, the build causes will have a UserCause entry. If that exists, we can examine it to find the user's username then query the Hudson instance to both resolve that username to a user object and query that object for its e-mail address, if available.

|h Test Groovy Job - Submitter E-Mail Address
for (cause in build.getCauses())
{
  if (cause instanceof hudson.model.Cause.UserCause)
  {
    def username = ((hudson.model.Cause.UserCause)cause).getUserName()
    def user = hudson.model.Hudson.instance.getUser(username)
    if (user != null)
    {
      hudson.tasks.Mailer.UserProperty mailProperty = user.getProperty(hudson.tasks.Mailer.UserProperty)
      if (mailProperty != null)
      {
        println("Submitter address: " + mailProperty.getAddress())
      }
      else
      {
        println("No available address for " + username)
      }
    }
  }
}
Test Groovy Job - Submitter E-Mail Address - Results
Started by user murrayjw
Submitter address: Jeremy.Murray@example.com
Finished: SUCCESS

Accessing the Build Parameters

Build parameters are exposed in two ways, both as an environment variable and under their own buildVariables collection. This shows how to access both. For illustration, I created a few dummy parameters of different types.

|h Test Groovy Job - Build Parameters
println("Parameters:")
build.buildVariables.each{println("  " + it.key +': '+ it.value) }
 
def envVars = build.properties.get("envVars")
println("Environment variables:")
envVars.each{ println("  " + it.key +': '+ it.value) }
Test Groovy Job - Build Parameters - Results
Started by user murrayjw
Parameters:
  TestBooleanValue: true
  TestStringParam: myDefaultValue
  TestChoice: myTestChoice1
Environment variables:
  ... bunch of variables
  BUILD_ID: 2011-01-12_17-18-47
  BUILD_NUMBER: 30
  BUILD_TAG: hudson-Test Groovy Job-30
  BUILD_URL: http://hudson/job/Test%20Groovy%20Job/30/
  ... bunch of variables
  TestBooleanValue: true
  TestChoice: myTestChoice1
  TestStringParam: myDefaultValue
  ... bunch of variables
Finished: SUCCESS

Conclusion

Modifying an existing Hudson plugin wasn't hard at all. The tool install went smoothly on multiple systems and the get/modify/build/install had no issues. I was very surprised, actually, and I think this has encouraged me to forge on with the other plugins I had been thinking of coding.

Now to figure out github to make a branch of this one plugin. If you would like a copy of this small modification, I've put up a copy of my modified groovy.hpi.

Next up: the groovy-postbuild plugin has a bunch of built-in functionality for adding badges and such - it would be great to have that in the groovy plugin, too, or to have a script version that can be run.

Much later: better StarTeam support, or even just a more generic approach to version control than the current plugins.

References

 
blog/20110117_hudson_plugin_modifications.txt · Last modified: 2011/02/05 22:41 by Jeremy Murray · []
Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki