Jenkins插件开发

目录

一、本地搭建

1.修改maven配置文件

2.下载插件模板

3.本地运行项目

二、项目体系

1.项目体系图

2.项目代码描述

三、开发扩展

1.内部插件

2.外部插件


Jenkins插件开发_第1张图片Jenkins插件开发_第2张图片

 

概要:Jenkins是一种持续集成工具,同时也是一个强大的插件系统。使用插件,几乎可以影响到所有的jenkins操作。Jenkins 目前有超过 1500 个社区插件,用于支撑整个持续集成流程。除此之外,我们自己还能按需开发插件。本节内容主要面向jenkins插件的开发。
 

一、本地搭建

描述:本地搭建插件开发项目的完整流程。

搭建流程图:

Jenkins插件开发_第3张图片

 

1.修改maven配置文件


  
    org.jenkins-ci.tools
  
  
    
    
      jenkins
      
        true 
      
      
        
          repo.jenkins-ci.org
          https://repo.jenkins-ci.org/public/
        
      
      
        
          repo.jenkins-ci.org
          https://repo.jenkins-ci.org/public/
        
      
    
  
  
    
      repo.jenkins-ci.org
      https://repo.jenkins-ci.org/public/
      m.g.o-public
    
  

作用:通过配置的仓库地址或节点下载需要的文件。

如果没配置,则可能出现这种结果(maven无法找到文件并构建项目):

Jenkins插件开发_第4张图片

 

2.下载插件模板

命令:mvn archetype:generate -Dfilter=io.jenkins.archetypes:plugin

Jenkins插件开发_第5张图片

 

 

如果报错:Your filter doesn't match any archetype, so try again with another value

这是因为maven在本地仓库根目录archetype-catalog.xml文件中没找到groupId为io.jenkins.archetypes的archetype,之后会在远端仓库的该文件中查找,如果还是没找到则出现上述问题。
此时需要下载文件 archetype-catalog.xml放置到maven的仓库repository下面。

资源链接为:https://download.csdn.net/download/qq_37822090/12240539

 

3.本地运行项目

1.运行项目:mvn hpi:run

启动项目:

Jenkins插件开发_第6张图片

 

Jenkins插件开发_第7张图片

 

显示 Jenkins is fully up and running ,则项目启动完毕。

通过链接:http://localhost:8080/jenkins  进入到本地项目中。

第一次执行 mvn hpi:run 时,需要从网上下载work文件夹搭建jenkins项目环境,所以比较慢

 

2.远程调试项目

设置环境变量(windows):set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n

Jenkins插件开发_第8张图片

 

配置远程监听:

Jenkins插件开发_第9张图片

 

之后,通过 mvn hpi:run 启动项目,然后通过idea启动debug,显示连接上socket即可

Jenkins插件开发_第10张图片

 

显示socket连接上,则可通过断点进行调试

注意:1.idea若叉掉了terminal的运行窗口,则在下一次调试前需要再次设置环境变量

           2.eclipse也能进行调试,此处无教程

           3.mac和linux设置环境变量的方式与windows不一致

 

 

二、项目体系

描述:插件的内部处理过程。

1.项目体系图

Jenkins插件开发_第11张图片

 

详细描述:

  1. 整体分两块,一块存放代码,一块存放工作区。
  2. 代码分两块,一块为java代码,一块为资源文件。java代码处理主流程,资源文件做页面及参数传递
  3. java代码里可以继承抽象类实现不同功能。比如继承build,同时配置对应的jelly文件,则可以在jenkins控制台的"Build"配置构建处理。
  4. *.jelly文件形成操作界面。它的作用是将参数值传递到java对应类中。
  5. *.jelly文件可以有多个命名,默认使用config.jelly作为java同路径下的操作界面,还能使用global.jelly做jenkins的全局配置界面。
  6. config.jelly的字段传入java类中时,会根据字段名称做一次方法调用。比如传入的字段是“name”,则会调用类下被构建步骤所扩展的doCheckName()方法。
  7. 控制台保存的配置参数,由java类处理,保存在指定xml文件中。如果是全局配置,则保存在根工作区下的同路径类.xml中;如果是项目配置,保存在/job/项目名/config.xml 文件中。

2.项目代码描述

全局配置:
public class SampleConfiguration extends GlobalConfiguration {
...
 @DataBoundSetter
    public void setLabel(String label) {
        this.label = label;
        save();//通过调用save()方法保存全局变量值,他的作用是把配置放置在根目录下的通文件名的xml文件里。
    }
}


项目配置:
//继承build表构建时处理。
//build中有实现两个接口
//ExtensionPoint(插件开发扩展点):作用是标识它是扩展的插件,以便Jenkins自动发现,也能通过@hudson.Extension注解来注册
//Describable:作用是实现它的类将会产生全局唯一实例,让其实现类可以通过getDescriptor()取到对应实例。
public class HelloWorldBuilder extends Builder implements SimpleBuildStep {
    private final String name;
    private final String name2;
    private boolean useFrench;

    //参数赋值,并将参数保存到项目下xml文件中
    @DataBoundConstructor
    public HelloWorldBuilder(String name,String name2) {
        this.name = name;
        this.name2 = name2;
    }
    public String getName2() {
        return name2;
    }
    public String getName() {
        return name;
    }
    public boolean isUseFrench() {
        return useFrench;
    }
    //同上
    @DataBoundSetter
    public void setUseFrench(boolean useFrench) {
        this.useFrench = useFrench;
    }
    /**
     * 核心方法,表示在step过程中将会执行此操作,这是插件开发过程中的主要作用区
     * @param run   当前步骤属于step
     * @param workspace 工作区
     * @param launcher 用于启动进程
     * @param listener 监听并发送输出
     * @throws InterruptedException
     * @throws IOException
     */
    @Override
    public void perform(Run run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException {
        //构建时增加Jelly视图
        run.addAction(new HelloWorldAction(name));
        if (useFrench) {
            listener.getLogger().println("Bonjour, " + name + "!");
        } else {
            listener.getLogger().println("Hello, " + name + "!");
        }
    }

    @Symbol("greet")//类的扩展标识符,可以在pipeline通过该标识符调用该扩展类
    @Extension//声明为插件扩展标识
    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 {
            System.out.println("value:"+value);
            System.out.println("useFrench:"+useFrench);
            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();
        }
        //判断当前Step是否能用于目标类型的项目
        @Override
        public boolean isApplicable(Class aClass) {
            return true;
        }
        //这个步骤的名称
        @Override
        public String getDisplayName() {
            return "插件开发helloworld";
        }
    }
}

 

类的接口实现:
需要实现接口:ExtensionPoint(插件开发扩展点)
作用是标识它是扩展的插件,以便Jenkins自动发现,也能通过@hudson.Extension注解来注册

需要实现接口:Describable
作用是实现它的类将会产生全局唯一实例。让其实现类可以通过getDescriptor()取到对应实例。(自己的理解)


注解:
@DataBoundConstructor:绑定对象时使用的构造器,用来把jelly传入的值绑定到当前对象上。点击包存时将会调用子类的该构造方法,将数据保存到文件。
@DataBoundSetter:绑定参数时使用的注解,作用同上。
@Extension:声明为插件扩展标识。
@Symbol("greet"):类的扩展标识符,可以在pipeline通过该标识符调用该扩展类

 

方法:
configure:可实现的配置方法,接收传入的配置参数,然后通过save()把具体参数保存到全局配置中。继承于:Descriptor 。它相当于全局唯一实例的父类。
perform(Run run, FilePath workspace, Launcher launcher, TaskListener listener):
SimpleBuildStep的核心方法,表示在项目运行过程中将会执行此操作,这是插件开发过程中的主要作用区。传递的参数:run:当前步骤属于step; launcher:用于启动进程 ; listener:监听并发送输出

doCheckName(@QueryParameter String value, @QueryParameter boolean useFrench):
表示对字段"name"做检查,"name"被填写时将会被调用。传入参数"value"表示字段"name"传入的值,而后的参数useFrench是传入的同名字段的值。
它的内部通过抽象父类Descriptor执行方法getCheckMethod(String fieldName) ,内部通过反射找到参数名称对应方法。

 

isApplicable:判断当前Step是否能用于目标类型的项目

getDisplayName:这个步骤的名称。

 

 

三、开发扩展

1.内部插件

描述:Jenkins自身提供可供实现的插件。

官网地址: https://jenkins.io/doc/developer/extensions/jenkins-core/

Jenkins插件开发_第12张图片

 

2.外部插件

描述:一部分已经实现的插件,可供二次开发。

官网地址: https://jenkins.io/doc/developer/extensions

Jenkins插件开发_第13张图片

 

内容很多,但不是很完整,有些插件连github地址都已经丢失了。

案例:

Jenkins Jira Plugin作用之一:Jenkins构建页面的后处理来更新Jira问题

 

参考文档:

官网:

https://jenkins.io/doc/developer/extensions/

https://jenkins.io/doc/developer/extensions/jenkins-core/

https://wiki.jenkins.io/display/JENKINS/Defining+a+new+extension+point

https://jenkins.io/doc/developer/tutorial/extend/

博客:

https://juejin.im/post/599bdddb6fb9a0248e5cb45f

https://blog.csdn.net/weixin_38652136/article/details/81116455

https://blog.gmem.cc/jenkins-plugin-development  

https://blog.csdn.net/weixin_38652136/article/details/81116455

 

若有错误,还望指出

 

 

 

你可能感兴趣的:(jenkins插件开发,Jenkins)