Thursday, April 02, 2009

Hudson Plugin 2: Adding a Post-Build action (for a Reporter/Publisher)

This is a follow-up to the Hudson Plugin 1. As told before, you create the plugin skeleton using:
mvn hpi:create
This creates a plugin skeleton through the maven-hpi-plugin. As of this writing, the latest version (1.34) generates a code that uses adeprecated way of doing so, and it is the skeleton of a Builder plugin.

Since we are building a Recorder/Publisher and we will use the recommended way of defining a plugin (through the Extension annotation), we will have to change most of the code. But it is important to understand what is the structure, so that's the value of generating the skeleton. Specially because of Hudson's choice of using Jelly for the plugin portions of the HTML page.
  • src/main/java
    plugin Java code
  • src/main/resource
    jelly files where you specify code for the configuration of plugin (global and project configuration).

Java Code
We need to create at least two classes to start testing our plugin. Since we want to see results quickly, let's do the minimum possible here. Let's remember what we want to do here: to add a new "Post-build action" where we can configure the file pattern that we will use to find files to report the test results.
  1. Subclass of hudson.Recorder.
  2. Descriptor class
For 2. there are many options, but we will create a subclass of BuildStepDescriptor<publisher>. More details below.

  1. config.jelly: jelly code that will be shown in the "Post-build action" section for our plugin
  2. global.jelly: jelly code that will be shown in the Manage Hudson/Configure System section (this file is not used here since we don't have global configuration so far)
  3. help.html: html code with help text for the "Post-build action". This is shown if you click on the ? on the right of your action.
  4. help-artifact.html: html code with help text for the plugin option that will be entered by the user. In our case, the file pattern for the report files.

Files and Details
1. Since our Descriptor class is an inner class, this is the only Java class so far:

public class DistributedTestRecorder extends Recorder {
public static String DISPLAY_NAME = "Distributed Test Report";

private final String report;

public DistributedTestRecorder(String report) { = report;

public String getReport() {
return report;

public boolean perform(AbstractBuild build, Launcher launcher,
BuildListener listener) {
return true;

public static final class DescriptorImpl extends
BuildStepDescriptor<publisher> {
public String getDisplayName() {
return "Publish " + DistributedTestRecorder.DISPLAY_NAME;

public void doCheck(StaplerRequest res, StaplerResponse rsp)
throws IOException, ServletException {
new FormFieldValidator.WorkspaceDirectory(res, rsp).process();

public boolean isApplicable(Class arg0) {
return true;
2. Jelly file with the code for our Post-Build action

<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:bh="/lib/health">
<f:entry title="Distributed Test Report pattern" field="report"
This is a file name pattern that can be used to locate the Distributed Test report files
(for example <b>**/performance/perf*</b>).<br/>
The path is relative to <a href='ws/'>the module root</a> unless
you are using Subversion as SCM and have configured multiple modules, in which case it is
relative to the workspace root.<br/>
<f:textbox />
3. HTML code for help files

(main help file)
(help file for "report" configuration field - see above in the config.jelly file)
This is the distributed test plugin help to be added later.
Yes, that's all for now. You should already have a post-build action being displayed when you launch Hudson (remember to use "mvn hpi:run" to run Hudson and do not run "mvn package" before that).
Post a Comment