Groovy Postbuild Plugin

Plugin Information

Plugin ID groovy-postbuild
Latest Release 1.9-h-2
Latest Release Date Oct 24, 2013
Sources Github
Support Eclipse Hudson Forum
Issue Tracking Eclipse Bugzilla

This plugin executes a groovy script in the Hudson JVM. Typically, the script checks some conditions and changes accordingly the build result, puts badges next to the build in the build history and/or displays information on the build summary page.

Usage

The groovy script can use the variable manager, which provides access to the following objects and methods:

  • contains(file, regexp) - returns true if the given file contains a line matching regexp.
  • logContains(regexp) - returns true if the build log file contains a line matching regexp.
  • getMatcher(file, regexp) - returns a java.util.regex.Matcher for the first occurrence of regexp in the given file.
  • getLogMatcher(regexp) - returns a java.util.regex.Matcher for the first occurrence of regexp in the build log file.
  • setBuildNumber(number) - sets the build with the given number as current build. The current build is the target of all methods that add or remove badges and summaries or change the build result.
  • addShortText(text) - puts a badge with a short text, using the default format.
  • addShortText(text, color, background, border, borderColor) - puts a badge with a short text, using the specified format.
  • addBadge(icon, text) - puts a badge with the given icon and text. In addition to the 16x16 icons offered by Hudson, groovy-postbuild provides the following icons:

    - completed.gif
    - db_in.gif
    - db_out.gif
    - delete.gif
    - error.gif
    - folder.gif
    - green.gif
    - info.gif
    - red.gif
    - save.gif
    - success.gif
    - text.gif
    - warning.gif
    - yellow.gif

  • addInfoBadge(text) - puts a badge with info icon and the given text.
  • addWarningBadge(text) - puts a badge with warning icon and the given text.
  • addErrorBadge(text) - puts a badge with error icon and the given text.
  • removeBadges() - removes all badges from the current build.
  • removeBadge(index) - removes the badge with the given index.
  • createSummary(icon) - creates an entry in the build summary page and returns a summary object corresponding to this entry. The icon must be one of the 48x48 icons offered by Hudson. You can append text to the summary object by calling its appendText methods:
    • appendText(text, escapeHtml)
    • appendText(text, escapeHtml, bold, italic, color)
  • removeSummaries() - removes all summaries from the current build.
  • removeSummary(index) - removes the summary with the given index.
  • buildUnstable() - sets the build result to UNSTABLE.
  • buildFailure() - sets the build result to FAILURE.
  • buildSuccess() - sets the build result to SUCCESS.

It is also possible to delete badges and summaries by using the following links:

  • remove all badges:
    • http://your-hudson/job/your-job/build-number/parent/parent/plugin/groovy-postbuild/removeBadges
  • remove all summaries:
    • http://your-hudson/job/your-job/build-number/parent/parent/plugin/groovy-postbuild/removeSummaries
  • remove the badge with the given index:
    • http://your-hudson/job/your-job/build-number/parent/parent/plugin/groovy-postbuild/removeBadge?index=idx
  • remove the summary with the given index:
    • http://your-hudson/job/your-job/build-number/parent/parent/plugin/groovy-postbuild/removeSummary?index=idx

Example 1

The script below puts a warning badge and mark the build as unstable if it detects that deprecated methods were used.

if(manager.logContains(".*uses or overrides a deprecated API.*")) {
    manager.addWarningBadge("Thou shalt not use deprecated methods.")
    manager.createSummary("warning.gif").appendText("<h1>You have been warned!</h1>", false, false, false, "red")
    manager.buildUnstable()
}

Example 2

Suppose we have a parameterized build, which uses the boolean parameter storeToDB in order to instruct the build to store some artifacts into the database. The script below puts a badge next to the builds for which this parameter is set.

if("true".equals(manager.build.buildVariables.get("storeToDB"))) {
    manager.addBadge("db_in.gif", "Stored to DB")
}

Example 3

Suppose we have a parameterized build, which uses the string parameter version. The script below puts a short text indicating the value of this parameter next to successful and unstable builds.

if(manager.build.result.isBetterOrEqualTo(hudson.model.Result.UNSTABLE)) {
    manager.addShortText("v${manager.build.buildVariables.get('version')}")
}

Example 4

The script below determines how long it took to build the project and displays the corresponding value as a short text next to each build.

def matcher = manager.getMatcher(manager.build.logFile, "^Total time: (.*)\$")
if(matcher?.matches()) {
    manager.addShortText(matcher.group(1), "grey", "white", "0px", "white")
}

Example 5

For badges, you can choose from the 16x16 icons provided by Hudson or from the icons provided by this plugin. Some of the names of groovy-postbuild icons conflict with the names of Hudson icons (e.g. yellow.gif). For these icons, you have to provide the complete path (e.g. /images/16x16/yellow.gif), in case you want a badge with the Hudson icon. You can also use icons provided by other plugins (e.g. Green Balls), by specifying the complete path to the icon.

manager.addBadge("star-gold.gif", "icon from Hudson")
manager.addBadge("yellow.gif", "icon from groovy-postbuild plugin")
manager.addBadge("/images/16x16/yellow.gif", "icon from Hudson")
manager.addBadge("/plugin/greenballs/16x16/green.gif", "icon from greenballs plugin")

Example 6

The script below displays on the build summary page all classes that use Sun proprietary API.

pattern = ~/.*src\/main\/java\/(.*)\.java:[^ ]* (.*) is Sun proprietary API and may be removed in a future release.*/
def map = [:]
manager.build.logFile.eachLine { line ->
    matcher = pattern.matcher(line)
    if(matcher.matches()) {
        ownClass = matcher.group(1).replaceAll("/", ".")
        sunClass = matcher.group(2)
        map[ownClass] = sunClass
    }
}
if(map.size() > 0) {
    summary = manager.createSummary("warning.gif")
    summary.appendText("Classes using Sun proprietary API:<ul>", false)
    map.each {
        summary.appendText("<li><b>$it.key</b> - uses $it.value</li>", false)
    }
    summary.appendText("</ul>", false)
}

Example 7

The script below removes all badges and summaries from previous builds.

currentBuildNumber = manager.build.number
for(i=1; i<currentBuildNumber; i++) {
    if(manager.setBuildNumber(i)) {
        manager.removeBadges()
        manager.removeSummaries()
    }
}

Example 8

The script below marks the running build as deployed and the previous build as undeployed.

manager.addShortText("deployed")
manager.createSummary("gear2.gif").appendText("<h2>Successfully deployed</h2>", false)

currentBuildNumber = manager.build.number
if(manager.setBuildNumber(currentBuildNumber - 1)) {
   actions = manager.build.actions
    actions.each { action ->
        if (action.metaClass.hasProperty(action, "text") && action.text.contains("deployed")) {
            actions.remove(action)
        }
    }
    currDate = new Date().dateTimeString
    manager.addShortText("undeployed: $currDate", "grey", "white", "0px", "white")
    manager.createSummary("gear2.gif").appendText("<h2>Undeployed: $currDate</h2>", false, false, false, "grey")
}

Example 9 (thanks to Ken Bertelson)

The script below changes the description of the first failed test.

def tr = manager.build.testResultAction.result
def cr = tr.failedTests.get(0)
cr.description = "My CaseResult desc"

Labels:

plugin-post-build plugin-post-build Delete
Enter labels to add to this page:
Wait Image 
Looking for a label? Just start typing.
  1. Feb 01, 2010

    Jason Stiefel says:

    Not seeing a component set up in JIRA for this plugin, and I'm reluctant to open...

    Not seeing a component set up in JIRA for this plugin, and I'm reluctant to open an issue without assigning a component. Any chance the plugin author is subscribed to this page?

    The issue I'm having has to do with the images provided with the plugin. I'm getting broken image icons when adding a badge to a build.

    thanks!

    1. Feb 04, 2010

      Serban Iordache says:

      The groovy-postbuild component is now available in JIRA.

      The groovy-postbuild component is now available in JIRA.

      1. Feb 10, 2010

        Jason Stiefel says:

        Awesome, thanks! Still seeing broken images for images specific to this plug...

        Awesome, thanks! Still seeing broken images for images specific to this plugin. I'll log a bug shortly.

  2. Mar 25, 2010

    Rob Petti says:

    I think having a way to remove or edit badges and summaries would be awesome. Th...

    I think having a way to remove or edit badges and summaries would be awesome. The only real way I can see to do this is to edit the config files directly. Even just providing some public methods that we can call through the groovy console (or the postbuild plugin itself) would be nice

    1. Mar 30, 2010

      Serban Iordache says:

      I have released a new version of this plugin (1.3), which offers support for add...

      I have released a new version of this plugin (1.3), which offers support for adding and removing badges or summaries of previous builds. See examples 7 and 8.

  3. Mar 25, 2010

    Ken Bertelson says:

    This plugin is great. I wondered how I could ever programmatically edit the des...

    This plugin is great.

    I wondered how I could ever programmatically edit the descriptions for failed testcases without writing a plugin.  But with this plugin installed, it's basically just a few lines of code...something like this:

    def tr = manager.build.getTestResultAction().getResult()
    def cr = tr.getFailedTests().get(0)
    cr.setDescription("My CaseResult desc")

    1. Mar 30, 2010

      Serban Iordache says:

      Great tip, thank you! It's now available as "Example 9".

      Great tip, thank you! It's now available as "Example 9".

  4. Apr 15, 2010

    Ken Bertelson says:

    Is there a way to use the same groovy script within multiple jobs without having...

    Is there a way to use the same groovy script within multiple jobs without having to cut-and-paste it each time?
    I got a groovy postbuild script running, then I copied its contents verbatim to a file on Hudson master.  Then, I tried this from Groovy Postbuild:
        Eval.me(new File("/var/lib/hudson/userContent/postbuild-plugin.groovy").text);
    But got this:
        ERROR: Failed to evaluate groovy script.
        groovy.lang.MissingPropertyException: No such property: manager for class: Script1
    I tried a few things, but I couldn't get the embedded script to recognize my calls to the manager class.

    1. Apr 16, 2010

      Ken Bertelson says:

      So after looking at source code plus trial and error, here's my solution: Bindi...

      So after looking at source code plus trial and error, here's my solution:

      Binding binding = new Binding();
      binding.setVariable("manager", manager);
      GroovyShell shell = new GroovyShell(binding);
      shell.evaluate(new File("/var/lib/hudson/userContent/postbuild-plugin.groovy").text);

      1. Apr 26, 2010

        Serban Iordache says:

        Actually, you don't need to create a new GroovyShell. Instead, you can directly ...

        Actually, you don't need to create a new GroovyShell. Instead, you can directly call the evaluate() method:

        evaluate(new File("/var/lib/hudson/userContent/postbuild-plugin.groovy"))

        Or, you can put your groovy script under SCM and specify a path relative to the workspace:

        evaluate(new File(manager.build.workspace.getRemote() + "/postbuild-plugin.groovy"))
        1. May 31, 2010

          Wim Rosseel says:

          Just a word of warning there! The post build plugin runs on the manager and ...

          Just a word of warning there!
          The post build plugin runs on the manager and doing it as you say will fail if you are working with slaves!

          As I found out with my windows manager and mixed windows/linux/solaris slave setup :-(

          The best option is to define an extra env parameter in your runtime environment.

          Read: in the environment for the user as which you run hudson, e.g. your start script

          then you can do something link this

          def env = System.getenv();
          evaluate(new File(env['HUDSON_SCRIPT_DIR']+"/groovy/postbuild-ci.groovy").text);
          
          1. Jun 15, 2010

            Ken Bertelson says:

            I've switched over to your better way of doing this.  Thanks to the both of...

            I've switched over to your better way of doing this.  Thanks to the both of you for your suggestions.

          2. Jul 30, 2010

            Marcin Przybyla says:

            HI. I found yours post and it interest me.I like to set new runtime variable in...

            HI.

            I found yours post and it interest me.I like to set new runtime variable in one project and then us this variable in other (buildis parametrized, but not trigered by first one). How to do it by groovy script (or in diferent way)? I was trying to do that like you wrote, but I'm new user of Hudson and groovy scripts and I have some problems with that.

  5. Aug 19, 2010

    Harold Shinsato says:

    This might seem a basic question - but how do you query the manager.build object...

    This might seem a basic question - but how do you query the manager.build object to determine the whether the build was successful or not? Is there a reference page to these various objects to see the methods available?

    1. Aug 23, 2010

      Serban Iordache says:

      You can use the following code: if(manager.build.result == hudson.model.Result....

      You can use the following code:

      if(manager.build.result == hudson.model.Result.SUCCESS)

      See also Example 3.

      The variables available in your groovy scripts have the following java types:

      See the javadoc or have a look at the Hudson source code to learn how to use them.

  6. Nov 10, 2010

    Ken Bertelson says:

    I love this plugin. Here's another thing that you can do... How to set the ba...

    I love this plugin. Here's another thing that you can do...

    How to set the badge for the "Parent" Build of a Multi-configuration Project:

    import hudson.matrix.MatrixRun;
    import hudson.matrix.MatrixBuild;
    
    MatrixRun matrixRun = manager.build
    
    // Create logic to avoid setting the badge repeatedly.
    // I have a User-defined Axis named "RUN".  For my matrix,
    // only one child job runs when RUN=fmodel
    if (matrixRun.buildVariables.get("RUN") == "fmodel") {
        MatrixBuild matrixBuild = matrixRun.parentBuild
        manager.setBuild(matrixBuild)
        manager.addShortText("hi","grey", "white", "0px", "white");
    }
  7. Nov 23, 2010

    Carlos Oliveira says:

    Excellent plugin! How can I read a user defined property of my Ant build file i...

    Excellent plugin!

    How can I read a user defined property of my Ant build file inside the Groovy Script?

    Cheers

    1. Nov 23, 2010

      Serban Iordache says:

      You can echo the value of your user-defined property and then grep for it in the...

      You can echo the value of your user-defined property and then grep for it in the log file.

      Put in your ant script something like:

      <echo>myProp=${myProp}</echo>

      Put in your groovy script something like:

      def matcher = manager.getLogMatcher("^.*myProp=(.*)\$")
      if(matcher?.matches()) {
          def myProp = matcher.group(1)
          manager.addShortText(myProp, "grey", "white", "0px", "white")
      }
      1. Nov 23, 2010

        Carlos Oliveira says:

        Nice workaround! Works great. Cheers!

        Nice workaround! Works great.

        Cheers!

  8. Nov 30, 2010

    robbie says:

    Hi, Using this priority plugin, I'd like to change the priority of the job base...

    Hi,

    Using this priority plugin, I'd like to change the priority of the job based on whether or not the most recent build passed or failed. Any suggestions on how I could achieve this or if it is even possible?

    thanks

    1. Dec 02, 2010

      Serban Iordache says:

      This is rather a hack, but it will probably do the job: def properties = manag...

      This is rather a hack, but it will probably do the job:

      def properties = manager.build.project.properties
      def it = properties.values().iterator()
      while(it.hasNext()) {
          property = it.next()
          if(property.class.name == "hudson.queueSorter.PrioritySorterJobProperty") {
              def priority = property.priority
              it.remove()
              def result = manager.build.result
              if(result == hudson.model.Result.SUCCESS) priority += 10
              if(result == hudson.model.Result.FAILURE) priority -= 10
              def ctor = property.class.constructors[0]
              def newPrioProperty = ctor.newInstance(priority)
              manager.build.project.addProperty(newPrioProperty)
          }
      }
  9. Dec 03, 2010

    Rene Groeschke says:

    I'm using the pmd and the report violoations post build action to trace it. Now ...

    I'm using the pmd and the report violoations post build action to trace it. Now it would be nice to add a batch if the number of pmd violations has increased during this build. Is there a way to get these informations from the build model?

    regards,
    René

  10. Dec 03, 2010

    Rene Groeschke says:

    I'm using the pmd and the report violoations post build action to trace it. Now ...

    I'm using the pmd and the report violoations post build action to trace it. Now it would be nice to add a batch if the number of pmd violations has increased during this build. Is there a way to get these informations from the build model?

    regards,
    René

    1. Dec 07, 2010

      Serban Iordache says:

      You can use the following code to retrieve the number of pmd violations: def p...

      You can use the following code to retrieve the number of pmd violations:

      def pmdViolations = 0
      manager.build.actions.each { action ->
          if(action.class.simpleName == "ViolationsBuildAction") {
              pmdViolations = action.report.violations.get("pmd") ?: 0
          }
      }
      manager.addShortText("$pmdViolations pmd violations", "grey", "white", "0px", "white")

      The above code works only if GroovyPostbuild runs after the Violations plugin. One way to ensure this is to edit the config.xml of your project and to place the <org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildRecorder> element after the <hudson.plugins.violations.ViolationsPublisher> element. Then, restart Hudson. The annoying thing is that the order of publishers is reset when saving the configuration, so you will have to repeat these operations each time you make a change to the project configuration.

      To avoid these annoyances, you could build a custom version of GroovyPostbuild that will always run after the Violations plugin. In order to this, you have to retrieve the source code of GroovyPostbuild and adjust the annotation of GroovyPostbuildDescriptor: @Extension(ordinal=-1).

  11. Jun 30, 2011

    Christian Pagel says:

    Hi all, I am trying to read the content of a file in the (remote) workspace usin...

    Hi all,
    I am trying to read the content of a file in the (remote) workspace using the GroovyPostbuild Plugin.

    However, even without all functionality, I always end up with a "Failed to deserialize the Callable object" caused by a NullPointerException.

    Any pointers?

    Here is my code:

    my try:
    import hudson.remoting.VirtualChannel;
    import hudson.FilePath;
    
    def tag = "unknown"
    
    public class GetTag implements FilePath.FileCallable<String> {
            public String invoke(File workspace, VirtualChannel channel) {
              return "test";
        }
    }
    
    tag = manager.build.getWorkspace().act(new GetTag());