Jenkins插件开发

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jenkins插件开发相关的知识,希望对你有一定的参考价值。

参考技术A

安装 JDK Maven 并配置 Maven 仓库 settings.xml

使用脚手架创建项目

运行, 注意需要在 pipeline 下测试插件,jenkins 需要先安装 pipeline 插件

打包插件并安装
mvn package 生成一个 hpi 文件,直接在 jenkins 后台上传即可。

Jenkins 插件开发就是对于一系列的「扩展点」进行扩展实现自定义的功能。

扩展点是 Jenkins 系统某个方面的接口或抽象类。这些接口定义了需要实现的方法,而 Jenkins 插件就需要实现这些方法,比如我写的插件需要实现 Builder 这个扩展点:

Descriptor 静态内部类是一个类的描述者,用于指明这是一个扩展点的实现,Jenkins 通过这个描述者才能知道我们写的插件。每一个描述者静态类都需要呗 @Extension 注解,Jenkins 内部会扫描 @Extension 注解来获取注册了哪些插件:

@DataBoundConstructor 注解作用于构造器上,用于在页面上配置的插件参数

Jenkins 插件的页面使用 jelly , 一个正常的插件可以分成 3 个 jelly 文件:

请注意 config.jelly 文件的位置,它的文件名需要与插件的类名一致

config.jelly 文件示例:

jenkins插件开发

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

1. 向导

  jenkins是一个强大的插件系统,开发者使用插件,几乎可以影响到所有的jenkins操作。这个章节演示了简单的插件功能。

1.1 准备插件的开发环境

  安装JDK环境,安装maven,保证mvn路径被添加到path变量。

1.2 创建插件

  打开命令行,进入我们希望的目录中,然后执行

mvn -U archetype:generate -Dfilter=io.jenkins.archetypes:

  运行结果

$ mvn -U archetype:generate -Dfilter=io.jenkins.archetypes:
…
Choose archetype:
1: remote -> io.jenkins.archetypes:empty-plugin (Skeleton of a Jenkins plugin with a POM and an empty source tree.)
2: remote -> io.jenkins.archetypes:global-configuration-plugin (Skeleton of a Jenkins plugin with a POM and an example piece of global configuration.)
3: remote -> io.jenkins.archetypes:hello-world-plugin (Skeleton of a Jenkins plugin with a POM and an example build step.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 3 
Choose io.jenkins.archetypes:hello-world-plugin version:
1: 1.1
2: 1.2
3: 1.3
Choose a number: 3: 3 
[INFO] Using property: groupId = unused
Define value for property artifactId: demo 
Define value for property version 1.0-SNAPSHOT: : 
[INFO] Using property: package = io.jenkins.plugins.sample
Confirm properties configuration:
groupId: unused
artifactId: demo
version: 1.0-SNAPSHOT
package: io.jenkins.plugins.sample
 Y: : y 

  以上标出了关键的地方:

  1. 选择hello-word-plugin作为我们的插件结构
  2. 选择1.3最新版本
  3. artifactid是强制要求的,而且在jenkins中运行时要求唯一,我们设置为demo。
  4. 默认是 1.0-SNAPSHOT作为开发的版本号。(maven中的版本号区别可以查看: 这里
  5. 最后最列举出来的信息进行确认Y

  以上会创建一个目录,名字与artifactid的值一致(这里的值是demo),而且里面有一些基本的可运行的插件结构。执行以下指令来校验这个插件源码是否可以运行:

$ mv demo demo-plugin
$ cd demo-plugin
$ mvn verify

  这里第一步就是重命名这个文件夹,接着verify会下载一系列依赖,然后进入生命周期,包括FindBugs静态分析和测试,直到显示如下信息:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 06:11 min
[INFO] Finished at: 2017-03-02T14:14:34+01:00
[INFO] Final Memory: 73M/872M
[INFO] ------------------------------------------------------------------------

1.3 构建和运行插件

  maven的HPI插件用来构建和打包jenkins插件,这个插件提供了一个简单的方式来运行插件:

mvn hpi:run

  以上指令会运行一个jenkins实例(这个jenkins实例的数据保存在插件目录的work目录下),在 http://localhost:8080/jenkins/,然后自动打开一个控制台(这个控制台对应jenkins实例),控制台显示

INFO: Jenkins is fully up and running

  接着自动打开一个浏览器,我们可以通过这个浏览器看到这个插件具体做了什么。

  在jenkins中创建一个自由风格的项目,在构建设置中,启用我们的插件“Say Hello Word”,在出现的选项中随便输入一个问候语“Hello Jenkins!”,然后保存,进行项目构建,打开这次构建的控制台,可以看到我们之前输入的值,被输出到控制台上了:

Started by user anonymous
Building in workspace /Users/mrjenkins/demo/work/workspace/testjob
Hello, Jenkins! 
Finished: SUCCESS

1.4 扩展插件

  这次通过以下特征来扩展插件:

  1. 用合适的数据结构来保存我们的问候语,而不是仅仅在构建控制台中输出
  2. 添加一个新的页面来显示我们用过的问候语

 1.4.1 记录问候语

  首先,在HelloWorldBuilder所在的包中创建一个类HelloWorldBuilder:

package io.jenkins.plugins.sample;
import hudson.model.Action;
public class HelloWorldAction implements Action {
    @Override
    public String getIconFileName() {
        return null;
    }
    @Override
    public String getDisplayName() {
        return null;
    }
    @Override
    public String getUrlName() {
        return null;
    }
}

  Action都是jenkins的基础构建扩展单位,这些单位可以访问并且保存许多对象,而且还可以把这些对象显示到界面上。

  我们往这个Action类中添加我们希望保存的数据(私有字段和对应的geter、setter):

(...)
public class HelloWorldAction implements Action {
    private String name;
    public HelloWorldAction(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    (...)

  现在,需要我们在构建的时候,生成这个类的实例,在HelloWorldBuilder类的perform方法中,添加如下一行标注的代码:

(...)
    @Override
    public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException {
        run.addAction(new HelloWorldAction(name)); 
        if (useFrench) {
            listener.getLogger().println("Bonjour, " + name + "!");
        } else {
            listener.getLogger().println("Hello, " + name + "!");
        }
    }
(...)

  保存后,mvn hpi:run来运行插件。之后每次进行构建,上面的Action都会被应用。可以通过查看build.xml来确认,这个文件在这里work/jobs/JOBNAME/builds/BUILDNUMBER/。文件大致如下:

<build>
  <actions>
    <hudson.model.CauseAction> 
      <causes>
        <hudson.model.Cause_-UserIdCause/>
      </causes>
    </hudson.model.CauseAction>
    <io.jenkins.plugins.sample.HelloWorldAction plugin="[email protected]"> 
      <name>Jenkins</name> 
    </io.jenkins.plugins.sample.HelloWorldAction>
  </actions>
  (...)
</build>

  对于以上三个标注的地方:

  1. 代表了构建的原因(如果触发这次构建)也被作为action来保存了,这里指出了是匿名用户触发的构建
  2. 这是我们新建的Action
  3. 这个name值就是我们在构建配置中设置的值

1.4.2 添加个页面来显示数据

  首先,回到HelloWorldAction中修改如下函数的返回值:

    @Override
    public String getIconFileName() {
        return "document.png"; 
    }

    @Override
    public String getDisplayName() {
        return "Greeting"; 
    }

    @Override
    public String getUrlName() {
        return "greeting"; 
    }

  分别代表了多出的侧边栏的图标、标题,以及地址(http://JENKINS/job/JOBNAME/BUILDNUMBER/greeting/)。

  接着,以上地址的页面需要被配置。在jenkins中创建视图,通过Jelly来实现。

  在src/main/resources/io/jenkins/plugins/sample/中创建一个目录,名为HelloWorldAction。这个目录对应我们的HelloWorldAction类,代表这个目录中的资源给对应的类来使用。目录中有如下资源:

  1. config.jelly:代表构建配置中的表单界面
  2. config*.properties:contain the localizations for the build step configuration
  3. help*.html:provide the localized inline help for the configuration

  在以上目录(src/main/resources/io/jenkins/plugins/sample/HelloWorldAction/)中创建一个 index.jelly,这个界面会显示在http://JENKINS/job/JOBNAME/BUILDNUMBER/greeting/中。index.jelly内容如下:

<?jelly escape-by-default=‘true‘?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:st="jelly:stapler">
    <l:layout title="Greeting"> 
        <l:main-panel> 
            <h1> 
                Name: ${it.name} 
            </h1>
        </l:main-panel>
    </l:layout>
</j:jelly>

  对于以上四个标注的地方:

  1. layout标签是jenkins提供的一个基础界面容器,包含了header、footer、主内容区域,侧边栏等
  2. main-panel标签中的内容代表了容器中的主内容
  3. jelly中可以使用任意html标签
  4. 这是一个JEXL表达式,it代表了这个视图所属的Java对象(类似于this),在这个例子中就是指向了HelloWorldAction实例,it.name等价于调用了这个属性的getter,也就是调用了getName方法

  做好以上配置后,当我们访问http://JENKINS/job/JOBNAME/BUILDNUMBER/greeting/时,jelly以及里面的name数据就显示出来了

 1.4.3 为页面添加侧边栏

  以上的显示的界面中没有侧边工具栏,这里我们要做的就是把侧边工具栏显示出来。要实现这个效果,

  1. 在Action中获取到这次构建的引用
  2. 从这个引用中获取到工具栏fragment
  3. 将这个fragment引用到我们的界面中

  实现第一步,让HelloWorldAction来实现RunAction2这个接口,里面有两个方法:

  • onAttached(Run):called when the run is first attached to a build
  • onLoad(Run):called when the action and run are loaded from disk
(...)
import hudson.model.Run;
import jenkins.model.RunAction2;
public class HelloWorldAction implements RunAction2 { 
    private transient Run run; 
    @Override
    public void onAttached(Run<?, ?> run) {
        this.run = run; 
    }
    @Override
    public void onLoad(Run<?, ?> run) {
        this.run = run; 
    }
    public Run getRun() { 
        return run;
    }
(...)

  对于以上标注的两个个地方:

  1. 被这个关键字修饰的run,不会随着这个action序列化到硬盘上
  2. 使我们获取到的run,可以用在jelly视图中

   然后在jelly中引入run提供的侧边工具栏:

(...)
    <l:layout title="Greeting">
        <l:side-panel> 
            <st:include page="sidepanel.jelly" it="${it.run}" optional="true" /> 
        </l:side-panel>
        <l:main-panel>
          (...)
        </l:main-panel>
    </l:layout>
(...)

  类似于main-panel,side-panel代表了侧标栏。接着include标签,可以从这个标签的it属性所指向的对象中,引入page所指向的视图,效果就是从run中引入了sidepanel.jelly视图。然后将这个标签设置为可选的,这样一来,当sidepanel.jelly不存在时也不会报错了

  以上配置后,http://JENKINS/job/JOBNAME/BUILDNUMBER/greeting/就有侧边栏了。

 

以上是关于Jenkins插件开发的主要内容,如果未能解决你的问题,请参考以下文章

jenkins插件开发(一)——h5发布到CDN

Jenkins插件开发完全示例

[Jenkins 新插件] 兼容阿里开发手册 (P3C) 的火线插件安装使用教程

jenkins插件开发

Jenkins 插件开发笔记

火线教你如何开发Jenkins插件