For a quick look at Hudson plugin development, you can have a look at this page.
This is a post about developing a trigger for Hudson which will monitor changes in folders (and subfolders if set to do so) and trigger build process.
All trigger plugins are subclasses of hudson.triggers.trigger.
The methods that can be overriden are:
public void start(Item project, boolean newInstance): Called when the trigger is loaded into the memory and started.
public void run(): Executes the triggered task. This method is called when the Trigger is instantiated with a cron string and the crontab matches the current time.
public void stop(): This method is called when the plugin is unloaded from the memory. This happens when the Hudson is going to restart/shut down or when the project configuration has changed.
The descriptor class is used to describe (hence the name) the plugin to Hudson environment. It should extend TriggerDescriptor for plugins extending trigger class and annotated with @Extension. isApplicable method should return true to allow user to configure this trigger in project configurations. getDisplayName method should return the name that will be shown on plugins page of Hudson.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| public class FolderChangedTrigger<Job> extends Trigger {
…
@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
@Extension
public static class DescriptorImpl extends TriggerDescriptor
{
@Override
public boolean isApplicable(Item item) {
return true;
}
@Override
public String getDisplayName() {
return "Folder Changed Trigger";
}
}
…
@Override
public void start(Item project, boolean newInstance) {
super.start(project, newInstance);
_project = project;
_fileMap = new HashMap<String, Long>();
}
…
} |
The constructor should take non-transient fields and annotated with @DataBoundConstructor. This annotation makes it possible for Stapler class to find the constructor which should the values from configuration page of project in Hudson be used with. Constructor of upper class is called with a cron timer string to make Hudson run the trigger on every minute.
1
2
3
4
5
6
7
| @DataBoundConstructor
public FolderChangedTrigger(String folderToMonitor, boolean recursiveCheck, String excludedFilesExp) throws ANTLRException {
super("* * * * *");
this._folderToMonitor = folderToMonitor;
this._recursiveCheck = recursiveCheck;
this._excludedFilesExp = excludedFilesExp;
} |
In overriden run method it just checks the folders (and subfolders if set to do so), and depending on a change in the structure it gets the Hudson build queue instance and schedules a build for the project it runs for.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| @Override
public void run()
{
if (_folderToMonitor != null && _folderToMonitor.length() > 0)
{
File folder = new File(_folderToMonitor);
if (folder.isDirectory())
{
RecursiveFileMonitor rfm = new RecursiveFileMonitor();
if (rfm.check(_folderToMonitor))
{
Queue qu = Queue.getInstance();
qu.schedule((AbstractProject) _project);
}
}
}
} |
The jelly files are configuration views of your plugin.
global.jelly contains the global configuration view which is shown on the Hudson management page and includes parameters that is going to be used for all Hudson projects. In our plugin we do not have such a file, as our configuration parameters should be set on a project-wide basis.
Config.jelly contains configuration parameters for one Hudson project. The values of these parameters are populated from the plugin object through properties. FolderToMonitor and excludedFilesExp fields are populated by calls to getFolderToMonitor and getExcludedfilesExp respectively while RecursiveCheck is set by a call to isRecursivecheck.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <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">
<f:entry title="Folder" field="folderToMonitor">
<f:textbox name="folderToMonitor" value="${folderToMonitor}"
checkUrl="'/fieldCheck?errorText=${h.jsStringEscape(h.encode('%Folder is mandatory.'))}&value='+encode(this.value)"
help="/plugin/folder-changed-trigger/help-folderToMonitor.html"/>
</f:entry>
<f:entry title="Recursive check" field="recursiveCheck">
<f:checkbox name="recursiveCheck" checked="${recursiveCheck}" help="/plugin/folder-changed-trigger/help-recursiveCheck.html"/>
</f:entry>
<f:entry title="Excluded Files" field="excludedFilesExp">
<f:textbox name="excludedFilesExp" value="${excludedFilesExp}" help="/plugin/folder-changed-trigger/help-excludedFilesExp.html"/>
</f:entry>
</j:jelly> |
For each entry in config.jelly file a help file can be set which will display a help icon on the right of the parameter. When this button is clicked the given help file is shown inside a panel. The path to help files are /plugin/$PLUGIN_NAME/help-propertyName.html where $PLUGIN_NAME is the name of your plugin. Help files are pure static html files, like shown below.
1
| <div> The folder to be monitored for changes. </div> |
The version of the plugin can be set inside the pom file created by maven.
1
2
3
4
| <groupId>com.burcsade</groupId>
<artifactId>folder-changed-trigger</artifactId>
<version>1.0</version>
<packaging>hpi</packaging> |
It is also possible to make it clear the required release of Hudson that the plugin should run on in pom file.
1
2
3
4
5
6
| <parent>
<groupId>org.jvnet.hudson.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.343</version><!-- which version of Hudson is this plugin built against? -->
<relativePath>../pom.xml</relativePath>
</parent> |
index.jelly file is used for give a brief description of the plugin in plugins list page.
1
2
3
| <div>
This plugin monitors a specified folder and triggers the build process depending on found added/modified/removed files.
</div> |
Full source code and compiled plugin file can be downloaded by clicking on the link below.
Hudson Folder Changed Trigger
You can start using the plugin right away by installing the hpi file found inside target folder. Source files are located in src folder.
If you have any comments, feel free to submit.
Java, Programming build trigger, hudson, Java, maven, plugin development, trigger