While working on my talk Writing a Hudson / Jenkins plugin (for EclipseCon NA 2014), I wanted to publish blog posts about the ideas mentioned in the talk; in this post I explain what are the differences between Hudson and Jenkins and how you can make your plugin compatible with both of them.
Since the project split in November 2010, Hudson (now under the Eclipse foundation umbrella) and Jenkins (community driven) APIs have followed their own path… What does that mean for plugin development ?
Contents
Jenkins and Hudson differences on February 2014
Hudson and Jenkins governance are quite different, and so are their release rhythm (frequent and LTS releases for Jenkins, major /minor / bug fix releases for Hudson)
Let’s have a look at these 2 projects activities (please keep in mind that I just compared the core projects, not the plugins activity, and also that I only selected some axis of comparisons – this is not the most complete comparison you would imagine !) :
Jenkins activity between 2011 and 2014
On February 2nd 2011, was published the first Jenkins release (1.396, latest is 1.550), since then , if you clone https://github.com/jenkinsci/jenkins.git and run few commands, you can find out :
- How many commits were pushed since February 2011 :
1git whatchanged --since="February 12 2011" --until="now" | grep "commit " | wc -l
returns 6785 - How many commits were pushed since September 2011 :
1git whatchanged --since="September 15 2011" --until="now" | grep "commit " | wc -l
return 5001 - How many contributors committed code since February 2011 :
1git log --since="February 12 2011" --until="now" --format='%aN' | sort -u | wc -l
returns 325
Most important features added to Jenkins since February 2011 : (from http://jenkins-ci.org/changelog, I just picked the major enhancements)
- 1.416 : Added a mechanism to write views in Groovy
- 1.433 : Use of guice for loading extensions
- 1.442 : Plugins can now be installed without taking Jenkins offline
- 1.446 : Jenkins now acts as an SSH daemon
- 1.463 : Publishers can be now reordered by the user
- 1.509 : Performance improvement in master/slave communication throughput
- 1.519 : Remoting classloader performance improvement upon reconnection to the same slave
- 1.520 : Core started relying on Java 1.6
- 1.532 : Added a new extension point to control where archived artifacts get stored.
- 1.535 : « java -jar jenkins.war » now runs on Jetty8. Command line options are still compatible.
- 1.536 : Executor threads are now created only on demand and Upgrade bundled iplugin versions: ssh-slaves to 1.4, ssh-credentials to 1.5.3 and credentials to 1.8.3
- 1.542 : Allow build queue and executor status panes to be collapsed.
- 1.548 : Added infrastructure for moving items into or out of folders.
Hudson activity between 2011 and 2014
We can run the same commands on the Hudson git repository : http://git.eclipse.org/gitroot/hudson/org.eclipse.hudson.core.git/ , except that the history anterior to September 2011 is absent.
- How many commits were pushed since February 2011 :
1git whatchanged --since="September 15 2011" --until="now" | grep "commit " | wc -l
returns 1230 - How many contributors committed code since February 2011 :
1git log --since="February 12 2011" --until="now" --format='%aN' | sort -u | wc -l
returns 15
Most important features added to Hudson since February 2011 : (from http://hudson-ci.org/changelog.html and http://www.eclipse.org/hudson/changelog.php)
- 2.1.0 : Maven 3 plugin, GWT support for plugins
- 2.2.0 : Cascading project settings (inheritance of Job settings)
- 3.0.0 : Dependencies clean up (IP clean to join the Eclipse foundation)
- 3.1.0 : Team Concept (team based authentication and authorization model within Hudson)
It’s interesting to note that the Hudson teams provides their coming priorities on their project page.
What about the usage then ?
- Jenkins had 70 000 installs in September 2013 http://stats.jenkins-ci.org/jenkins-stats/)
- Hudson had 65 000 downloads (not installs) in September 2013 since 2.0.0 (according to http://hudsoncentral.wordpress.com/2013/09/05/whats-running-under-your-desk/ )
And the plugins ?
- Jenkins had 889 available plugins in 2014 (see updated data)
- Hudson had 379 available plugins in 2014 (see PluginCentral3 or updated data)
If you can’t choose which tool to develop plugins for, then read on, you may be writing the same plugin for both, with only few modifications.
Developing the same plugin for both Hudson and Jenkins
Since both tools have the same origin API, and avoid making disruptive API changes (to stay compatible with most plugins), there’s a good chance you can keep the same code for your plugin and make it compatible with both.
Let’s see in practice what it looks like : let’s create a new Hudson plugin :
1 |
$ mvn org.eclipse.hudson.tools:maven-hpi-plugin:create |
Once it’s created we can see it in action :
1 |
$ export HUDSON_HOME=work-hudson && mvn package org.eclipse.hudson.tools:maven-hpi-plugin:run |
(Hudson requires you to go through an initial setup at http://localhost:8080 the first time you run hpi:run on your new plugin, click finish and you’re done)
You may wonder why I override the HUDSON_HOME environment variable : it’s because I’ll want jenkins and hudson to use separate work directories; we could also avoid setting the environment variable on the command line and specify hudsonHome in the pom :
1 2 3 4 5 6 7 8 9 10 11 |
<build> <plugins> <plugin> <groupId>org.eclipse.hudson.tools</groupId> <artifactId>maven-hpi-plugin</artifactId> <configuration> <hudsonHome>hudson-home</hudsonHome> </configuration> </plugin> </plugins> </build> |
By now, you should be able to see the sample plugin adding a build option after creating a new job : http://localhost:8080/view/All/newJob
Now we know that this plugin is working fine with the latest version of Hudson, what about Jenkins ?
First, make sure you edit your ~/.m2/settings.xml maven configuration file to be able to pull jenkins maven plugins (we didn’t need to do that with Hudson since the Hudson team pushes their plugins to maven central)
Then, in the pom.xml, just replace the parent with :
1 2 3 4 5 |
<parent> <groupId>org.jenkins-ci.plugins</groupId> <artifactId>plugin</artifactId> <version>1.550</version> </parent> |
and build and run with :
1 |
$ export HUDSON_HOME=work-jenkins && mvn clean package org.jenkins-ci.tools:maven-hpi-plugin:run |
and head your browser to : http://localhost:8080/jenkins/view/All/newJob and create new job, you should see your plugin deployed :
What this demonstrates is that chances are the plugin you’re currently working on does not rely on Hudson specific or Jenkins specific API, and it should be just a matter of creating a branch and maintaining it to widen your audience.
A real life example : porting the Accelerated Build Now plugin from Jenkins to Hudson
I successfully ported this plugin from Jenkins (targeting 1.523) to Hudson (3.1.2). Here are the main changes between APIs I had to deal with :
- of course, jenkins.model.Jenkins had to be replaced by hudson.model.Hudson
- in 2012 Jenkins added the use if QueueTaskFuture instead of java.util.concurrent.Future
- in 2012 Jenkins added getStartTimeInMillis to the Run class
There still aren’t a lot changes between the 2 code bases, if you’re curious, you can see the details of the changes between the 2 branches, Jenkins (master) and Hudson : https://github.com/Terracotta-OSS/accelerated-build-now-plugin/compare/hudson
Une réflexion sur « Developing a plugin for both Jenkins and Hudson »