jopen 12年前



为了能开发插件,开发环境需安装MavenJDK 6.0以上版本


<settings>    <pluginGroups>      <pluginGroup></pluginGroup>    </pluginGroups>  <profiles>  <!-- Give access to Jenkins plugins -->      <profile>        <id>jenkins</id>        <activation>          <activeByDefault>true</activeByDefault> <!-- change this to false, if you don't like to have it on per default -->        </activation>        <repositories>          <repository>            <id></id>            <url></url>          </repository>        </repositories>          <pluginRepositories>          <pluginRepository>            <id></id>            <url></url>          </pluginRepository>        </pluginRepositories>      </profile>    </profiles>  </settings>



mvn -cpu hpi:create


cd newly-create-directory   mvn package


mvn -DdownloadSources=true -DdownloadJavadocs=true -DoutputDirectory=target/eclipse-classes eclipse:eclipse

或者 使用m2eclipse插件在Eclipse打开即可









set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n  mvn hpi:run


$ export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n"  $ mvn hpi:run


mvn hpi:run -Djetty.port=8090

设置comtext path

mvn hpi:run -Dhpi.prefix=/jenkins


mvn package


import hudson.Launcher;  import hudson.Extension;  import hudson.util.FormValidation;  import hudson.model.AbstractBuild;  import hudson.model.BuildListener;  import hudson.model.AbstractProject;  import hudson.tasks.Builder;  import hudson.tasks.BuildStepDescriptor;  import net.sf.json.JSONObject;  import org.kohsuke.stapler.DataBoundConstructor;  import org.kohsuke.stapler.StaplerRequest;  import org.kohsuke.stapler.QueryParameter;    import javax.servlet.ServletException;  import;    /**   * Sample {@link Builder}.   *   * <p>   * When the user configures the project and enables this builder,   * {@link DescriptorImpl#newInstance(StaplerRequest)} is invoked   * and a new {@link HelloWorldBuilder} is created. The created   * instance is persisted to the project configuration XML by using   * XStream, so this allows you to use instance fields (like {@link #name})   * to remember the configuration.   *   * <p>   * When a build is performed, the {@link #perform(AbstractBuild, Launcher, BuildListener)}   * method will be invoked.    */  public class HelloWorldBuilder extends Builder {        private final String name;        // Fields in config.jelly must match the parameter names in the "DataBoundConstructor"      @DataBoundConstructor      public HelloWorldBuilder(String name) { = name;      }        /**       * We'll use this from the <tt>config.jelly</tt>.       */      public String getName() {          return name;      }        @Override      public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) {          // This is where you 'build' the project.          // Since this is a dummy, we just say 'hello world' and call that a build.            // This also shows how you can consult the global configuration of the builder          if (getDescriptor().getUseFrench())              listener.getLogger().println("Bonjour, "+name+"!");          else              listener.getLogger().println("Hello, "+name+"!");          return true;      }        // Overridden for better type safety.      // If your plugin doesn't really define any property on Descriptor,      // you don't have to do this.      @Override      public DescriptorImpl getDescriptor() {          return (DescriptorImpl)super.getDescriptor();      }        /**       * Descriptor for {@link HelloWorldBuilder}. Used as a singleton.       * The class is marked as public so that it can be accessed from views.       *       * <p>       * See <tt>src/main/resources/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly</tt>       * for the actual HTML fragment for the configuration screen.       */      @Extension // This indicates to Jenkins that this is an implementation of an extension point.      public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {          /**           * To persist global configuration information,           * simply store it in a field and call save().           *           * <p>           * If you don't want fields to be persisted, use <tt>transient</tt>.           */          private boolean useFrench;            /**           * Performs on-the-fly validation of the form field 'name'.           *           * @param value           *      This parameter receives the value that the user has typed.           * @return           *      Indicates the outcome of the validation. This is sent to the browser.           */          public FormValidation doCheckName(@QueryParameter String value)                  throws IOException, ServletException {              if (value.length() == 0)                  return FormValidation.error("Please set a name");              if (value.length() < 4)                  return FormValidation.warning("Isn't the name too short?");              return FormValidation.ok();          }            public boolean isApplicable(Class<? extends AbstractProject> aClass) {              // Indicates that this builder can be used with all kinds of project types               return true;          }            /**           * This human readable name is used in the configuration screen.           */          public String getDisplayName() {              return "Say hello world";          }            @Override          public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {              // To persist global configuration information,              // set that to properties and call save().              useFrench = formData.getBoolean("useFrench");              // ^Can also use req.bindJSON(this, formData);              //  (easier when there are many fields; need set* methods for this, like setUseFrench)              save();              return super.configure(req,formData);          }            /**           * This method returns true if the global configuration says we should speak French.           *           * The method name is bit awkward because global.jelly calls this method to determine           * the initial state of the checkbox by the naming convention.           */          public boolean getUseFrench() {              return useFrench;          }      }  }





<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">    <!--      This Jelly script is used to produce the global configuration option.        Jenkins uses a set of tag libraries to provide uniformity in forms.      To determine where this tag is defined, first check the namespace URI,      and then look under $JENKINS/views/. For example, <f:section> is defined      in $JENKINS/views/lib/form/section.jelly.        It's also often useful to just check other similar scripts to see what      tags they use. Views are always organized according to its owner class,      so it should be straightforward to find them.    -->    <f:section title="Hello World Builder">      <f:entry title="French" field="useFrench"        description="Check if we should say hello in French">        <f:checkbox />      </f:entry>    </f:section>  </j:jelly>



<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">    <!--      This jelly script is used for per-project configuration.        See global.jelly for a general discussion about jelly script.    -->      <!--      Creates a text field that shows the value of the "name" property.      When submitted, it will be passed to the corresponding constructor parameter.    -->    <f:entry title="Name" field="name">      <f:textbox />    </f:entry>  </j:jelly>






<prebuilders>      <org.wocloud.jenkins.manager.HelloWorldBuilder>        <name>Hello!!!!!!!!!!</name>      </org.wocloud.jenkins.manager.HelloWorldBuilder>    </prebuilders>



public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener)