Jenkins插件開發


一、環境依賴

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";
        }

    }

}
View Code

 

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就一直卡住的解決方案

最最最全的Jenkins插件開發教程

【Jenkins】Jenkins插件開發

免費的maven的archetype-catalog.xml文件下載

archetypeCatalog參數的配置

Jenkins使用教程

 Jenkins企業微信通知開發

jenkins參數化構建過程(添加多選框)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM