I recently started to write my first Jenkins plugin and I thought I share the experience with you. For that reason I started a new series of tutorials.
Today we are building a simple Jenkins plugin using Eclipse. The basic steps of this tutorial are extracted from the
Jenkins Plugin Tutorial.
Jenkins Tutorials
For a list of all jenkins related tutorials see
Jenkins Tutorials Overview.
Source code for this tutorial is available on github as a
single zip archive, as a
Team Project Set or you can
browse the files online.
Prerequisites
As you are interested in writing a plugin for
Jenkins I expect that you have a rough idea what Jenkins is used for and how to administer it.
While our build environment allows to run a test instance of Jenkins with our plugin enabled I also liked to have a 'real' Jenkins instance available to test my plugins. Therefore I use
docker to quickly get started with a woking Jenkins installation.
Once
you have installed docker (
extended tutorial for debian), you can download the latest Jenkins container by using
docker pull jenkins/jenkins:lts
Now run your container using
docker run -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts
After the startup process your server is reachable via
http://localhost:8080/.
To manage containers use commands
docker container ls
docker container stop <container name>
Step 1: Maven configuration
We will need
maven installed and ready for creating the project, building and testing it, so make sure you have set it up correctly.
Maven needs some configuration ready to learn about jenkins plugins, therefore you need to adapt the configuration file slightly. On linux change
~/.m2/settings.xml, on windows modify/create
%USERPROFILE%\.m2\settings.xml and set following content:
<settings>
<pluginGroups>
<pluginGroup>org.jenkins-ci.tools</pluginGroup>
</pluginGroups>
<profiles>
<!-- Give access to Jenkins plugins -->
<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>
<mirrors>
<mirror>
<id>repo.jenkins-ci.org</id>
<url>https://repo.jenkins-ci.org/public/</url>
<mirrorOf>m.g.o-public</mirrorOf>
</mirror>
</mirrors>
</settings>
Hint: On windows I had to remove the settings file
<maven install folder>\conf\settings.xml as it was used in favor of my profile settings.
Step 2: Create the plugin skeleton
To create the initial project open a shell and execute:
mvn archetype:generate -Dfilter=io.jenkins.archetypes:empty-plugin
You will be asked some questions how your plugin should be configurated:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: remote -> io.jenkins.archetypes:empty-plugin (Skeleton of a Jenkins plugin with a POM and an empty source tree.)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1
Choose io.jenkins.archetypes:empty-plugin version:
1: 1.0
2: 1.1
3: 1.2
4: 1.3
5: 1.4
Choose a number: 5:
[INFO] Using property: groupId = unused
Define value for property 'artifactId': builder.hello
Define value for property 'version' 1.0-SNAPSHOT: :
[INFO] Using property: package = unused
Confirm properties configuration:
groupId: unused
artifactId: builder.hello
version: 1.0-SNAPSHOT
package: unused
Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: empty-plugin:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: unused
[INFO] Parameter: artifactId, Value: builder.hello
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: unused
[INFO] Parameter: packageInPathFormat, Value: unused
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: unused
[INFO] Parameter: groupId, Value: unused
[INFO] Parameter: artifactId, Value: builder.hello
[INFO] Project created from Archetype in dir: ~/Eclipse/codeandme.blogspot.com/ws/builder.hello
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 36.202 s
[INFO] Finished at: 2018-11-27T20:34:15+01:00
[INFO] Final Memory: 16M/169M
[INFO] ------------------------------------------------------------------------
We just created the basic skeleton files and could start working right away. But as we want to do it the eclipse way we need to convert the project to a proper eclipse project. Therefore change into the created project directory and execute:
mvn -DdownloadSources=true -DdownloadJavadocs=true -DoutputDirectory=target/eclipse-classes eclipse:eclipse
The first run might take some time as maven has to fetch tons of dependencies. So sit back and enjoy the show...
Once this step is done we can import our project using the Eclipse import wizard using
File / Import... and then select
General/Existing Projects into Workspace. On the following page select the project folder that was created by maven.
Step 3: Update configuration files
The created
pom.xml file for our plugin provides a good starting point for development. Typically you might want to update it a little before you actually start coding. Fields like
name,
description,
license should be pretty clear. More interesting is
<properties>
<jenkins.version>2.7.3</jenkins.version>
<java.level>7</java.level>
</properties>
Upgrading the java level to 8 should be pretty safe these days. Further Jenkins 2.7.3 is really outdated. To check out which versions are available you may browse the
jenkins artifactory server. Open the
jenkins-war node and search for a version you would like to use.
I further adapt the
.project file and remove the
groovyNature as this would trigger install requests for groovy support in eclipse. As we are going to write java code, we do not need groovy.
Step 4: Build & Deploy the Plugin
To build your plugin simply run
mvn package
This will build and test your package. Further it creates an installable *.hpi package in the
com.codeandme.jenkins.helloworld/target folder.
Step 5: Test the plugin in a test instance
To see your plugin in action you might want to execute it in a test instance of Jenkins. Maven will help us to set this up:
mvn hpi:run -Djetty.port=8090
After the boot phase, open up your browser and point to
http://localhost:8090/jenkins to access your test instance.
Debugging is also quite simple, just add environment settings to setup your remote debugger. On Windows this would be:
set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n
On Linux use
export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n"
Then you should be able to setup a
Remote Java Application debug configuration in Eclipse.
Writing a simple builder will be our next step, stay tuned for the next tutorial.