一、环境依赖
JDK版本要求在1.6以上,Maven官方要求版本在3以上,此处本人使用的是JDK1.8 maven3.5.2
然后呢就是你maven的 setting.xml(此setting文件直接放在了C:\Users\xie_7\.m2下)文件要变成这样:
<?xml version="1.0" encoding="UTF-8"?> <settings> <!-- 指定本地仓库的存放地址,可选 --> <localRepository>E:\Jenkins\jar</localRepository> <!-- 下面的东西都不用管知道不,只需要copy就ok --> <pluginGroups> <pluginGroup>org.jenkins-ci.tools</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>repo.jenkins-ci.org</id> <url>http://repo.jenkins-ci.org/public/</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>repo.jenkins-ci.org</id> <url>http://repo.jenkins-ci.org/public/</url> </pluginRepository> </pluginRepositories> </profile> </profiles> <mirrors> <mirror> <id>repo.jenkins-ci.org</id> <url>http://repo.jenkins-ci.org/public/</url> <mirrorOf>m.g.o-public</mirrorOf> </mirror> </mirrors> </settings>
二、插件开发
1.创建 插件程序
好了,关于Jenkins的使用怎么就不去做过多解释了,网上多得是,此处阅读推荐:
https://blog.csdn.net/shuizhihun07/article/details/80168076
执行如下命令:
mvn -s E:\apache-maven-3.5.3\setting.xml -Uorg.jenkins-ci.tools:maven-hpi-plugin:create
然后会根据上文指定的setting.xml文件,下载到本地仓库中,下载完成后会提示如下信息
然后cd到指定的文件夹下,执行如下命令:
mvn -s E:\apache-maven-3.5.3\settings-jenkins.xml archetype:generate -DgroupId=com.ydzbinfo -DartifactId=sendActiveMessage -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeCatalog=internal
就会在相应文件夹下面创建项目
但是没有模板,只是一个空项目
但是如果不写-DarchetypeCatalog=internal参数,那么就会卡住,如下:
下载archetype-catalog.xml文件,根据以下说明,
archetypeCatalog用来指定maven-archetype-plugin读取archetype-catalog.xml文件的位置:
internal——maven-archetype-plugin内置的
local——本地的,位置为~/.m2/archetype-catalog.xml
remote——指向Maven中央仓库的Catalog
将该文件copy到本地仓库的org\apache\maven\archetype\archetype-catalog\3.2.0文件下,
然后配置-DarchetypeCatalog=internal,但是依然无效,还是报如下信息:
不知道哪里有问题,最后将archetype-catalog.xml文件copy到本地仓库的根文件夹下,然后设置参数-DarchetypeCatalog=local,一个带有模板的项目终于创建好了
完整命令如下:
mvn -s E:\apache-maven-3.5.3\settings-jenkins.xml archetype:generate -Dfilter=io.jenkins.archetypes: -DarchetypeCatalog=local
执行结果如下:
选择第2个hello-world-plugin模板,然后maven自动创建项目,整个项目的结构大致如下:
注意HelloWorldBuilder.java类,就要对应一个resource中的HelloWorldBuilder文件夹
2.开发 插件程序
插件的钩子应该是可以根据继承的抽象类(抽象类继承的接口)的不同,确定插件运行的不同步骤
这里按照教程,在build阶段发送一个构建项目是否成功的通知,具体代码如下:

import cn.hutool.http.HttpUtil; import hudson.Launcher; import hudson.Extension; import hudson.FilePath; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; import hudson.util.FormValidation; import hudson.model.AbstractProject; import hudson.model.Run; import hudson.model.TaskListener; import hudson.tasks.Builder; import hudson.tasks.BuildStepDescriptor; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import javax.servlet.ServletException; import java.io.IOException; import java.util.HashMap; import java.util.Map; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundSetter; public class HelloWorldBuilder extends Builder implements SimpleBuildStep { private String receivers=""; private String amServiceUrl=""; private String projectName = ""; private Boolean noPojectNotify=false;//没有构建结果 private Boolean successNotify=false; //成功 private Boolean failureNotify=false; //失败 private Boolean abortedNotify=false;//中断 private Boolean unstableNotify=false;//不稳定 public String getProjectName() { return projectName; } @DataBoundSetter public void setProjectName(String projectName) { this.projectName = projectName; } public String getAmServiceUrl() { return amServiceUrl; } @DataBoundSetter public void setAmServiceUrl(String amServiceUrl) { this.amServiceUrl = amServiceUrl; } public String getReceivers() { return receivers; } @DataBoundSetter public void setReceivers(String receivers) { this.receivers = receivers; } public Boolean getNoPojectNotify() { return noPojectNotify; } @DataBoundSetter public void setNoPojectNotify(Boolean noPojectNotify) { this.noPojectNotify = noPojectNotify; } public Boolean getSuccessNotify() { return successNotify; } @DataBoundSetter public void setSuccessNotify(Boolean successNotify) { this.successNotify = successNotify; } public Boolean getFailureNotify() { return failureNotify; } @DataBoundSetter public void setFailureNotify(Boolean failureNotify) { this.failureNotify = failureNotify; } public Boolean getAbortedNotify() { return abortedNotify; } @DataBoundSetter public void setAbortedNotify(Boolean abortedNotify) { this.abortedNotify = abortedNotify; } public Boolean getUnstableNotify() { return unstableNotify; } @DataBoundSetter public void setUnstableNotify(Boolean unstableNotify) { this.unstableNotify = unstableNotify; } @DataBoundConstructor public HelloWorldBuilder(String projectName,String receivers,String amServiceUrl) { this.projectName=projectName; this.amServiceUrl=amServiceUrl; this.receivers=receivers; } /*perform 真正开始执行的地方 你所有构建时的任务都将在此内完成 * 在此之内你可以执行 任意想执行的业务操作,Web Service等 */ @Override public void perform(Run<?, ?> build, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { String string =""; String displayName = build.getDisplayName(); Boolean isNotify=false; //获取构建结果 if(build.getResult() == null){ string="no project"; } else{ string= build.getResult().toString(); } int number = build.getNumber(); String resuit = null; if(string.equals("no project")){ resuit="无构建结果"; isNotify = this.noPojectNotify; } if(string.equals("SUCCESS")){ resuit="构建结果:成功"; isNotify = this.successNotify; }else if(string.equals("FAILURE")){ resuit="构建结果:失败"; isNotify = this.failureNotify; }else if(string.equals("UNSTABLE")){ resuit="构建结果:不稳定"; isNotify = this.unstableNotify; }else if(string.equals("ABORTED")){ resuit="构建结果:中断构建"; isNotify = this.abortedNotify; } String url = build.getUrl(); String content = displayName + projectName+"任务"+resuit; Map map = new HashMap(); map.put("subject","集成编译平台编译通知"); map.put("messageBody",content); map.put("recivers",receivers); if(isNotify) { String post = HttpUtil.post(amServiceUrl, map); listener.getLogger().println("result, " + post + "!"); } else { listener.getLogger().println(isNotify); } } @Override public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.NONE; } @Symbol("greet") @Extension //通过此注解 告诉系统该内部类是作为BuildStepDescriptor的扩展出现 public static final class DescriptorImpl extends BuildStepDescriptor<Builder> { /** * 表示对字段"name"做检查,"name"被填写时将会被调用,它的内部通过抽象父类Descriptor执行方法getCheckMethod(String fieldName) ,内部通过反射找到参数名称对应方法。 * @param value 传入参数"value"表示字段"name"传入的值 * @param useFrench 而后的参数useFrench是传入的同名字段的值 * @throws IOException * @throws ServletException */ public FormValidation doCheckName(@QueryParameter String value, @QueryParameter boolean useFrench) throws IOException, ServletException { if (value.length() == 0) { return FormValidation.error("value.length() == 0"); } if (value.length() < 4) { return FormValidation.warning("value.length() < 4"); } if (!useFrench && value.matches(".*[éáàç].*")) { return FormValidation.warning("else"); } return FormValidation.ok(); } @Override public boolean isApplicable(Class<? extends AbstractProject> aClass) { return true; } //这个步骤的名称 @Override public String getDisplayName() { return "SendActiveMessage"; } } }
config.jelly配置文件:
<?jelly escape-by-default='true'?> <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="任务名称" field="projectName"> <f:textbox /> </f:entry> <f:entry title="接收人(多个接收人用分号隔开)" field="receivers"> <f:textbox /> </f:entry> <f:entry title="am服务地址" field="amServiceUrl"> <f:textbox default="http://172.20.104.227/sendAmMessage/CICDSendActiveMessage.ashx"/> </f:entry> <f:advanced> <f:entry title="无构建结果通知" field="noPojectNotify"> <f:checkbox checked="true"/> </f:entry> <f:entry title="失败通知" field="failureNotify"> <f:checkbox checked="true"/> </f:entry> <f:entry title="中断通知" field="abortedNotify"> <f:checkbox checked="true"/> </f:entry> <f:entry title="不稳定通知" field="unstableNotify"> <f:checkbox checked="true"/> </f:entry> <f:entry title="成功通知" field="successNotify"> <f:checkbox /> </f:entry> </f:advanced> </j:jelly>
然后maven clean package 打包,会在target文件夹下生成一个后缀为.hpi的文件,然后在jenkins的插件管理,采用离线上传的方式
最后,在需要配置的项目中选择该插件:
参考文章:
Maven创建项目时出现Generating project in Interactive mode就一直卡住的解决方案
免费的maven的archetype-catalog.xml文件下载