一、环境依赖
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"?>
[/span>settings
[/span>localRepository
[/span>pluginGroups
[/span>pluginGroup
[/span>profiles
[/span>profile
[/span>id
[/span>activation
[/span>activeByDefault<span style="color: rgba(0, 0, 255, 1)"]true</activeByDefault<span style="color: rgba(0, 0, 255, 1)"]
[/span>repositories
[/span>repository
[/span>id
[/span>url
[/span>pluginRepositories
[/span>pluginRepository
[/span>id
[/span>url
[/span>mirrors
[/span>mirror
[/span>id
[/span>url
[/span>mirrorOf
二、插件开发
1.创建 插件程序
好了,关于Jenkins的使用怎么就不去做过多解释了,网上多得是,此处阅读推荐:
执行如下命令:
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 //代码效果参考:http://www.lyjsj.net.cn/wx/art_24053.html
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;
//代码效果参考:http://www.lyjsj.net.cn/wz/art_24051.html
}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;
//代码效果参考:http://www.lyjsj.net.cn/wx/art_24049.html
}@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 {
/**
表示对字段"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";
}
}
}
View Code
config.jelly配置文件:
<?jelly escape-by-default='true'?>
[/span>j:jelly xml