Zsy's Blog


  • 首页

  • 归档

Jenkins插件编写(二)

发表于 2018-05-04 | 分类于 Java

重要概念

上一节我们讨论了Jenkins的插件项目的创建和运行,而这一节,我们将会讨论Jenkins插件编写的几个重要概念。

@Extension 和 ExtensionPoint

Jenkins的插件之所以这么丰富和强大,很大原因上是因为Extension和ExtensionPoint的设计。

ExtensionPoint定义了一系列的切入点,它可以表示项目构建的不同的阶段,可以是表示某个事件,可以表示某个特定类型,可以表示某个位置。

通过实现不同的ExtensionPoint,我们可以灵活控制插件的执行。ExtensionPoint不仅是只能有Jenkins提供,不同的插件也提供了自己的ExtensionPoint。我们自己也可以定义一个ExtensionPoint然后找到其它人在其它插件对我们的ExtensionPoint的实现。

ExnteionPoint 列表

@Extension则是让我们的类被Jenkins自动登记(类似于Spring中的@Bean),Jenkins依据ExtensionPoint为我们控制插件的执行。

下面是上一节中的项目原型的代码。

1
2
3
public class HelloWorldBuilder extends Builder implements SimpleBuildStep {
//...
}
1
2
3
4
5
6
7
8
9
10
:::表示继承,---表示实现

HelloWorldBuilder
::: Builder(Class)
::: BuildStepCompatibilityLayer(Class, Abstract, Deprecated)
--- BuildStep
--- ExtensionPoint(Interface) <====================
--- Describable(Interface)
--- SimpleBuildStep(Interface)
::: BuildStep(Interface)

从上面的类关系图中,我们看到HelloWorldBuild实现了BuildStep这个ExtensionPoint,表示这个类的可能会在项目的构建,运行和完成期间被一次或多次调用。

Jenkins会找到这个类,依据它的ExtensionPoint在合适的时间帮我们调用代码。

1
2
3
4
5
6
7
8
@Override
public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException {
if (useFrench) {
listener.getLogger().println("Bonjour, " + name + "!");
} else {
listener.getLogger().println("Hello, " + name + "!");
}
}

上面这段就是这个ExtensionPoint中会被Jenkins执行的代码,在我们配置好name后会在Console Output中输出Hello, [name]。

但是有个问题,之前我们说过,Jenkins要自动登记我们的类,类必须有@Extension这个注解。但是这个类上并没有这个注解。

这里又有一个重要的概念。

Descriptor和Describable

Descriptor包含一个Describable对象的元数据,同时充当这个Describable对象的工厂类。

在Jenkins依据我们的代码创建一个实现了ExtensionPoint的Extension时候,要对这个对象进行配置(就像上一节填入name那样)和其它操作。Descriptor可以对我们的配置进行检验,依据我们的配置创建出对象,为我们的对象设置各种元属性。

1
2
3
4
5
6
7
8
9
10
11
12
@Symbol("greet")
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
public FormValidation doCheckName(@QueryParameter String value, @QueryParameter boolean useFrench) {
//...
}

@Override
public String getDisplayName() {
return Messages.HelloWorldBuilder_DescriptorImpl_DisplayName();
}
}

如上面代码所示,在这个类上使用@Extension后,Jenkins就会通过这个Descriptor工厂类创建HelloWorldBuild(如上面类图所示我们的HelloWorldBuild实现了Describable),并且可以为这个BuildStep检验参数,设置Display Name(上一节中的Say hello world)和其它属性。

但是上一节中我们看到的配置的表单在哪呢?它又是如何映射到我们的对象的字段呢?

Config

在src\main\resources\org\jenkinsci\plugins\sample\HelloWorldBuilder\中我们可以看到一个名字是config.jelly的文件。
通过在resources中的和类对应的目录下创建config.jelly文件,就可以为我们的类提供配置的表单。(在同级目录下我们可以看到一些properties文件,这些是用来做本地化用的)

1
2
3
4
5
6
7
8
9
10
11
12
<?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="${%Name}" field="name">
<f:textbox />
</f:entry>
<f:advanced>
<f:entry title="${%French}" field="useFrench"
description="${%FrenchDescr}">
<f:checkbox />
</f:entry>
</f:advanced>
</j:jelly>

Jenkins使用Apache Jelly编写UI。从上面我们可以看出,通过目录对应一个类,通过field属性对应一个字段,这样对一个对象进行配置。

后面我们将会从头创建一个简单的记录code coverage结果并显示出来的插件。

Jenkins插件编写(一)

发表于 2018-05-02 | 分类于 Java

介绍

今年我参加了GSoC的Jenkins的项目 —— 为Jenkins编写一个Code Coverage API Pluin,整合现存的所有Code Coverage插件并为此类插件提供一个泛用的API。借此机会我把期间学习的内容都记录下来,希望能给他人帮助,也让自己能养成一个写博客的习惯。

Jenkins是目前最流行的CI(持续集成,Continuous Integration)软件。数以百计的插件,为Jenkins提供了多种多样的功能和强大的扩展性。而通过Jenkins提供的接口,可以轻易的编写出自己的定制化的插件。这一系列博客将会讨论从插件的编写到在Update Center公布的全过程。

准备

开发环境

最新的Jenkins所需要的JDK版本是JDK8,编写插件过程中需要大量使用到Maven,其版本推荐为3.3.9以上。配置好这两个环境后就可以开始进行Jenkins插件的开发了。

创建项目骨架

通过使用maven,我们可以很方便的创建出插件项目的骨架,免去繁琐的配置。

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

在期间Maven会自动下载所需的依赖,然后便会进入交互模式,让我们配置要创建的骨架。

我目前的版本会让我们选择三个原型,分别是:

  • empty-plugin 只包含POM文件
  • global-configuration-plugin 包含POM文件和创建Global Configuration代码示例(这个以后会解释)
  • hello-world-plugin 包含POM文件和一个build step的示例(之后会解释)

在这里我选择了hello-world-plugin。之后交互界面会让我们选择原型的版本,这里我们选择最新的,然后根据提示输入我们的artifcatID和version等信息,最后在当前目录成功生成出项目骨架。

项目的结构

我们可以看到生成的项目的目录结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- src
- main
- java
- io/jenkins/plugins/sample
- HelloWorldBuilder.java
- resources
- io/jenkins/plugins/sample
- HelloWorldBuild
- config.jelly
...
- Messages.properties
...
- index.jelly
- test
- java
- io/jenkins/plugins/sample
- HelloWorldBuilderTest.java
- pom.xml

其中pom.xml包含了构建Jenkins插件所需要的配置信息,test目录下是单元测试相关的内容,main目录下就是我们后面要重点谈论的地方。

插件的运行和生成

在创建完项目骨架后,我们可以通过在项目目录使用mvn hpi:run来启动一个包含这个插件的Jenkins Server。

我们新建一个Freestyle的项目。在设置页面,选择增加构建步骤,我们可以看到这里有一个Say hello world选项,这就是我们的插件的配置(我们插件的原型是hello-wolrd-plugin)。

点击选项填入name,之后构建项目,在Console Output中我们可以看到一句Hello, [name]的输出。这说明我们的插件运行成功了。

生成插件文件

我们可以通过mvn package创建出一个*.hpi文件,这就是我们的插件文件。可以在我们自己的Jnekins Server的管理插件 - 高级中的上传插件中,将插件部署到我们自己的Jenkins Server上。

这一节主要讲了如何生成项目的骨架,以及测试运行。但是最重要的部分 —— 怎么编写插件却没有涉及,这是我们之后几节的重点讨论内容。

cizezsy

2 日志
1 分类
3 标签
© 2018 cizezsy
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4