插件开发入门 #
本节介绍Jenkins插件开发的基本概念,帮助了解如何创建自定义插件。
开发环境准备 #
前提条件 #
- JDK 11或更高版本
- Maven 3.6+
- IDE(推荐IntelliJ IDEA)
Maven配置 #
xml
<!-- ~/.m2/settings.xml -->
<settings>
<pluginGroups>
<pluginGroup>org.jenkins-ci.tools</pluginGroup>
</pluginGroups>
<profiles>
<profile>
<id>jenkins</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>
创建插件项目 #
使用原型 #
bash
mvn archetype:generate \
-Dfilter=io.jenkins.archetypes:
选择原型类型:
text
1. empty-plugin - 空插件模板
2. global-configuration-plugin - 全局配置插件
3. hello-world-plugin - Hello World示例
项目结构 #
text
my-plugin/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── io/jenkins/plugins/sample/
│ │ │ ├── SamplePlugin.java
│ │ │ └── SampleBuilder.java
│ │ └── resources/
│ │ ├── io/jenkins/plugins/sample/
│ │ │ └── SampleBuilder/
│ │ │ ├── config.jelly
│ │ │ └── help.html
│ │ └── index.jelly
│ └── test/
│ └── java/
├── pom.xml
└── README.md
pom.xml配置 #
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>4.x</version>
</parent>
<groupId>io.jenkins.plugins</groupId>
<artifactId>my-plugin</artifactId>
<version>1.0.0</version>
<packaging>hpi</packaging>
<name>My Plugin</name>
<description>A sample Jenkins plugin</description>
<properties>
<jenkins.version>2.400</jenkins.version>
<java.level>11</java.level>
</properties>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>324.va_f5d6774f3a_d</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
</project>
创建构建步骤 #
Builder类 #
java
package io.jenkins.plugins.sample;
import hudson.Extension;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import hudson.util.FormValidation;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import java.io.IOException;
public class SampleBuilder extends Builder {
private final String name;
@DataBoundConstructor
public SampleBuilder(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
listener.getLogger().println("Hello, " + name + "!");
return true;
}
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
public FormValidation doCheckName(@QueryParameter String value) {
if (value.isEmpty()) {
return FormValidation.error("Name is required");
}
return FormValidation.ok();
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
@Override
public String getDisplayName() {
return "Sample Builder";
}
}
}
Jelly配置页面 #
xml
<!-- src/main/resources/io/jenkins/plugins/sample/SampleBuilder/config.jelly -->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:entry title="Name" field="name">
<f:textbox />
</f:entry>
</j:jelly>
帮助文档 #
html
<!-- src/main/resources/io/jenkins/plugins/sample/SampleBuilder/help-name.html -->
<div>
Enter the name to greet.
</div>
创建全局配置 #
GlobalConfiguration类 #
java
package io.jenkins.plugins.sample;
import hudson.Extension;
import jenkins.model.GlobalConfiguration;
import org.kohsuke.stapler.DataBoundSetter;
@Extension
public class SampleGlobalConfiguration extends GlobalConfiguration {
private String defaultName;
public SampleGlobalConfiguration() {
load();
}
public String getDefaultName() {
return defaultName;
}
@DataBoundSetter
public void setDefaultName(String defaultName) {
this.defaultName = defaultName;
save();
}
}
全局配置Jelly #
xml
<!-- src/main/resources/io/jenkins/plugins/sample/SampleGlobalConfiguration/config.jelly -->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
<f:section title="Sample Plugin">
<f:entry title="Default Name" field="defaultName">
<f:textbox />
</f:entry>
</f:section>
</j:jelly>
构建和测试 #
本地运行 #
bash
mvn hpi:run
访问 http://localhost:8080/jenkins
打包插件 #
bash
mvn clean package
生成的 .hpi 文件在 target/ 目录。
安装测试 #
text
Manage Jenkins → Plugins → Advanced → Deploy Plugin
上传 .hpi 文件
编写测试 #
单元测试 #
java
package io.jenkins.plugins.sample;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Result;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
public class SampleBuilderTest {
@Rule
public JenkinsRule jenkins = new JenkinsRule();
@Test
public void testBuilder() throws Exception {
FreeStyleProject project = jenkins.createFreeStyleProject();
project.getBuildersList().add(new SampleBuilder("World"));
FreeStyleBuild build = project.scheduleBuild2(0).get();
jenkins.assertBuildStatus(Result.SUCCESS, build);
}
}
插件发布 #
准备发布 #
- 在Jenkins Wiki创建插件页面
- 配置pom.xml中的scm信息
- 准备README.md
发布到Jenkins仓库 #
bash
mvn release:prepare release:perform
开发最佳实践 #
1. 遵循命名规范 #
text
类名: PascalCase
方法名: camelCase
常量: UPPER_SNAKE_CASE
2. 使用@DataBoundConstructor #
java
@DataBoundConstructor
public MyBuilder(String param1, boolean param2) {
this.param1 = param1;
this.param2 = param2;
}
3. 实现Descriptor #
java
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
// 配置验证和显示名称
}
4. 编写测试 #
text
单元测试覆盖主要功能
集成测试验证完整流程
下一步学习 #
小结 #
- 使用Maven原型创建插件项目
- Builder类实现构建步骤
- Jelly定义配置界面
- 使用@DataBoundConstructor绑定参数
- 编写单元测试验证功能
- 发布到Jenkins插件仓库
最后更新:2026-03-28