I need to create two different Jenkins Builder classes. Each does different things and each requires its own .jelly, however, both require the same global configuration (global.
Avoid global.jelly
altogether. This is semi-deprecated. JobProperty
is also only suitable if you want per-job configuration, whereas the request is about global configuration.
Rather, use the GlobalConfiguration
API which is designed for this purpose. There is a standard archetype showing how to use it.
Yes, this is very much possible but not in the regular way of extending Builder. You will need to use it as a JobProperty. Lets take an example to explain how this is done.
You will have 3 classes/packages at minimum.
MyPluginClass
- Has fields for all your global configuration.MyBuildStepAClass
- Has the implementation of build step A.MyBuildStepBClass
- Has the implementation of build step B.The code for your build step classes MyBuildStepAClass
and MyBuildStepBClass
will be same as you would normally write it for a plugin with a single build step. Below is a sample for MyBuildStepAClass
..
public class MyBuildStepAClass {
private String name;
.....
@DataBoundConstructor
public MyBuildStepAClass(String name, ....) {
this.name = name;
....
}
public String getName() {
return name;
}
public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {
//logic for perform.
............
return true;
}
@Extension
public static class Descriptor extends BuildStepDescriptor<Builder> {
public Descriptor() {
load();
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return super.configure(req,formData);
}
@Override
public String getDisplayName() {
return "My Build Step A";
}
}
}
To share the configuration between both the plugin classes, You will extend your MyPluginClass
from JobProperty<Job<?,?>>
(instead of Builder
) and override the getDescriptor()
method to return the descriptor using Jenkins.getInstance().getDescriptor(getclass());
public class MyPluginClass extends JobProperty<Job<?, ?>> {
@Override
public MyPluginClassDescriptor getDescriptor() {
return (MyPluginClassDescriptor)Jenkins.getInstance().getDescriptor(getClass());
}
public static MyPluginClassDescriptor getMyPluginClassDescriptor() {
return (MyPluginClassDescriptor)Jenkins.getInstance().getDescriptor(MyPluginClass.class);
}
@Extension
public static final class MyPluginClassDescriptor extends JobPropertyDescriptor {
private String globalField1 = "";
public MyPluginClassDescriptor() {
super(MyPluginClass.class);
load();
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return super.configure(req,formData);
}
@DataBoundConstructor
public MyPluginClassDescriptor(String globalField1, ....) {
this.globalField1 = globalField1;
}
@Override
public String getDisplayName() {
return "IIBCI Plugin Configuration";
}
public getGlobalField1() {
return globalField1;
}
}
The contents of your global.jelly and individual config.jelly files for each build step will be normal as you would be referring them. Hope this helps you in understanding how JobProperty
helps you in having single configuration accessible in different build steps.
UPDATED to include information on jelly files.
You will have one global.jelly file in the package for MyPluginClass
. This jelly file will contain the fields that you want to render/store in global configuration.
<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:section title="MyPlugin configuration">
<f:entry title="Global field1" field="globalField1">
<f:textbox />
</f:entry>
</f:section>
</j:jelly>
Each of your Build steps will have their own index.jelly files which will contain the jelly code specific to the Build step. Hope that makes it more clear..