Jenkins插件开发——HelloWorld
编辑前言
工作安排,需要编写两个Jenkins插件,最近开始查找资料了解了下Jenkins的插件开发,自己编写了简单的HelloWorld入门程序,这边打算做一下总结。
环境配置
- 开发环境
需要maven和Java的环境,这个是我本地开发环境的版本。IDE使用的是Intellij IDEA。
- Maven配置
maven需要做如下配置,需要在maven的setting.xml文件加上下面的配置,这边复制一下就好了。
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<!-- 下面的东西都不用管知道不,只需要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>
创建Jenkins插件项目
选择一个目录,打开cmd,输入下面的命令,这个命令会生成与Jenkins有关的几个项目原型中的一个,我这边就先创建一个hello-world的插件项目。
mvn -U archetype:generate -Dfilter=io.jenkins.archetypes:
主要是几个步骤,根据引导创建出一个插件项目。
- 选择创建的原型编号,我这边选择3创建一个hello-world-plugin。
- 选择创建的版本,这边选择的是最新的版本。
- 添加插件对应的artifactId。
- 添加版本号,可以不填默认是1.0-SNAPSHOT。
- 选择Y去创建骨架项目。
导入以及运行Jenkins插件项目
通过IDE导入刚才生成的插件项目,等待maven下载完成依赖之后,可以通过mvn hpi:run命令来启动项目,这个命令会在本地启动一个jenkins的实例,可以通过localhost:8080/jenkins访问。等控制台有如下输出,说明启动完成。
之后就可以在Jenkins上面创建一个自由风格的项目,起一个任意的任务名称,接着就可以添加"Say hello world" 构建步骤。
像下面这样:
触发构建,可以在控制台看到对应的日志输出内容:
当然,这边也可以指定端口和上下文路径,使用mvn hpi:run -Djetty.port=8090 -Dhpi.prefix=/jenkins指定运行时的端口以及上下文路径。
插件的结构与开发调试
- 插件的目录结构
主要分为两部分,一部分是src源代码目录,还有一部分是resources资源目录,下面的资源目录只要是jenkins插件页面上对应的一些信息和配置的信息,注意,源码的目录和resources的目录要一一对应,不然会出错,之前开发有遇到过这个坑,找了很久。这边对应关系也很简单,大家可以开发插件的时候具体看下,还是比较容易上手的,我这边先不总结了,我下面会贴几个我参考的链接,如果要进行开发,可以参考一下。 - 项目的开发调试
开发的话,插件的运行主要是一个主类,通过在构造方法上面添加一个DataBoundConstructor注解实现接收页面上传递的参数,之后触发的时候会去调用perform进行对应的业务逻辑。内部类DescriptorImpl中实现的方法主要是插件的显示名称以及插件是否可见还有一个校验配置以及全局参数配置之类,我们主要的逻辑都是写在perform方法里面的。
package org.jenkinsci.plugins.sample;
import hudson.Launcher;
import hudson.Extension;
import hudson.FilePath;
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 jenkins.tasks.SimpleBuildStep;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundSetter;
public class HelloWorldBuilder extends Builder implements SimpleBuildStep {
private final String name;
private boolean useFrench;
@DataBoundConstructor
public HelloWorldBuilder(String name) {
this.name = name;
}
public String getName() {
return name;
}
public boolean isUseFrench() {
return useFrench;
}
@DataBoundSetter
public void setUseFrench(boolean useFrench) {
this.useFrench = useFrench;
}
@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 + "!");
}
}
@Symbol("greet")
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
public FormValidation doCheckName(@QueryParameter String value, @QueryParameter boolean useFrench)
throws IOException, ServletException {
if (value.length() == 0)
return FormValidation.error(Messages.HelloWorldBuilder_DescriptorImpl_errors_missingName());
if (value.length() < 4)
return FormValidation.warning(Messages.HelloWorldBuilder_DescriptorImpl_warnings_tooShort());
if (!useFrench && value.matches(".*[éáàç].*")) {
return FormValidation.warning(Messages.HelloWorldBuilder_DescriptorImpl_warnings_reallyFrench());
}
return FormValidation.ok();
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> aClass) {
return true;
}
@Override
public String getDisplayName() {
return Messages.HelloWorldBuilder_DescriptorImpl_DisplayName();
}
}
}
这里如果要在本地IDE上面进行debug调试的话,首先在命令行执行如下的命令用于监听debug的端口。
set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n
之后在IDE里面配置下remote并且设置端口为上面设置的debug端口。
这样本地启动插件之后,再运行remote的debug就可以进行插件的调试,断点之类。
总结与参考链接
这边jenkins的插件入门程序helloworld就写完了,可能写的比较乱,这边只是对自己最近工作的一个总结,有什么意见想法欢迎交流。
贴一下参考的链接