Saturday, April 26, 2014

Comparison of Jenkins and Hudson: Options for sharing configuration among projects

Continuous Delivery is a practice which follows from the principles behind the agile manifesto (http://agilemanifesto.org/principles.html); 'Our highest priority is to satisfy the customer through early and continuous delivery of valuable software'. Continuous Integration is a part of the process of Continuous Delivery in which source code changes are integrated and tested frequently in an automated way. Hudson and Jenkins are two products which can be used to implement Continuous Integration. These tools provide build job management, security, integration for products providing reporting capabilities, integration with version control and numerous plugins are available to provide additional functionality.

Hudson and Jenkins share a history. Sun Microsystems was the owner of Hudson. Oracle took over Sun Microsystems. Some friction ensued between the original developers of the product and Oracle. Since Oracle applied for the trademark in 2010 but was not the most contributing party, several developers decided to rename/fork Hudson and Jenkins was born. Since then the projects have diverged.

In this blog post I will look at how job configuration can be reused among projects in Jenkins and Hudson. Since the projects have diverged, the solutions provided will differ. Jenkins provides the Inheritance Plugin (https://wiki.jenkins-ci.org/display/JENKINS/inheritance-plugin) and the Template Project Plugin (https://wiki.jenkins-ci.org/display/JENKINS/Template+Project+Plugin). Hudson provides a core feature called Cascading Projects (http://www.eclipse.org/hudson/the-hudson-book/book-hudson.chunked/ch06.html#section-cascading-project).

Hudson Cascading Job configuration

Jenkins

I've used Jenkins 1.556, Template Project Plugin 1.4.1 and Inheritance Plugin 1.5.1.

Template Project Plugin

The Template Project Plugin allows using specific configuration from another project. The plugin currently has around 1800 installations.


Configuration from builders, publishers and SCM can be inherited from another project. There is a slight disclaimer on the plugin wiki page; it has had virtually no testing and compatibility with other plugins cannot be guaranteed. For me the plugin seemed to work as expected.

Although the plugin is relatively limited in it's capabilities, it does allow re-use of the most commonly re-used properties. Also it is possible to for example have an SCM template project and a separate Build template project (multiple 'parents'). The plugin can also be used for different project types.

Inheritance Plugin

The Inheritance Plugin currently has around 225 installations. There is a bold statement on the wiki page for this plugin; 'If Jenkins is the C language, this plugin is its C++ equivalent.'. The Inheritance plugin provides a new project type. The Inheritance Project. The plugin only works for projects of this type.

This plugin provides several new options in project view. When however I wanted to open the project configuration, Jenkins gave me an error so I couldn't play much with the plugin.


 java.lang.RuntimeException: org.apache.commons.jelly.JellyTagException: jar:file:/tmp/jetty-0.0.0.0-8888-jenkins.war--any-/webapp/WEB-INF/lib/jenkins-core-1.556.jar!/lib/layout/layout.jelly:233:26: <d:invokeBody> org.apache.commons.jelly.JellyTagException: jar:file:/tmp/jetty-0.0.0.0-8888-jenkins.war--any-/webapp/WEB-INF/lib/jenkins-core-1.556.jar!/lib/layout/main-panel.jelly:36:21: <d:invokeBody> org.apache.commons.jelly.JellyTagException: jar:file:/var/lib/jenkins/plugins/project-inheritance/WEB-INF/lib/classes.jar!/form/form.jelly:58:22: <d:invokeBody> org.apache.commons.jelly.JellyTagException: jar:file:/tmp/jetty-0.0.0.0-8888-jenkins.war--any-/webapp/WEB-INF/lib/jenkins-core-1.556.jar!/lib/form/entry.jelly:73:23: <d:invokeBody> No such property: codeMirrorConfig for class: hudson.markup.EscapedMarkupFormatter  
      at org.kohsuke.stapler.jelly.groovy.JellyBuilder.doInvokeMethod(JellyBuilder.java:280)  
      at org.kohsuke.stapler.jelly.groovy.Namespace$ProxyImpl.invoke(Namespace.java:92)  
      at com.sun.proxy.$Proxy42.layout(Unknown Source)  
      at lib.LayoutTagLib$layout.call(Unknown Source)  
      at configure-version-aware.run(configure-version-aware.groovy:34)  
      at org.kohsuke.stapler.jelly.groovy.GroovierJellyScript.run(GroovierJellyScript.java:69)  
      at org.kohsuke.stapler.jelly.groovy.GroovierJellyScript.run(GroovierJellyScript.java:62)  
      at org.kohsuke.stapler.jelly.groovy.JellyBuilder._include(JellyBuilder.java:165)  
      at org.kohsuke.stapler.jelly.groovy.JellyBuilder.include(JellyBuilder.java:140)  
      at sun.reflect.GeneratedMethodAccessor61.invoke(Unknown Source)  
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
      at java.lang.reflect.Method.invoke(Method.java:606)  
      at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)  
      at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)  

The following video shows what the plugin would have made possible if it had worked; https://www.youtube.com/watch?v=DNUI7DRi6XE&feature=youtu.be

The plugin allows creation of child projects which are parameterized and  implements project versioning.


The below screenshots are taken from the before mentioned youtube video. The plugin introduces a new type of parameter for which the inheritance behavior can be specified.


Also it is possible to display inheritance trees.


Projects can have several parents and property inheritance/order can be configured per parent. 


It appears to be a nice plugin which provides several nice options. It does seem however to provide quite some functionality which I might not directly need such as project versioning and using several parent projects. Allowing more then one parent however allows efficient re-use of configuration if projects and their inheritance are well structured/configured. More options for configuration also allow more room for errors. Also I'm not sure about the compatibility of this plugin with other plugins (this could have caused my error).

Hudson

I've used Hudson 3.1.2. The versions of the Template Project Plugin which is available for Hudson is 1.3. I have not tried Hudson with the Template Project plugin. I could not find a version of the Inheritance Plugin for Hudson.

Cascading jobs

Cascading jobs in Hudson is a core feature (http://www.eclipse.org/hudson/the-hudson-book/book-hudson.chunked/ch06.html#section-cascading-project) and can be used to allow inheritance of configuration between projects.


Cyclic dependencies are prevented and a master project cannot be deleted when children are present. In child projects, configuration can be overwritten. Per project only one cascading job can be selected. If no suitable candidate is available for a cascading job, the option is not provided.

Although this feature looks limited, it provides useful functionality which will allow reuse of configuration in a relatively simple (easily implemented) and (seemingly) non-invasive way. Only allowing one parent (cascading job) provides a limitation but makes configuration easier. This limitation can be worked around with for example the Template Project Plugin or cascading configuration projects.

Conclusion

Jenkins and Hudson have diverged. Both projects have evolved and have implemented comparable functionality in different ways. Project configuration inheritance is a nice example of that. In my opinion, Hudson has the better solution. There is no limitation on what can be inherited / overwritten in children and inconsistencies are prevented. The configuration, although limited, is intuitive. The Jenkins Inheritance plugin crashed on me when I opened a job configuration thus I suspect compatibility issues with other plugins. The plugin provides quite a lot of functionality. Maybe more then you would need. The job needed to be of a special type and it appears (although I cannot confirm this) that the inheritance mechanism is specific since inheritance of certain configuration such as triggers has been added in v1.5 of the plugin. The Template Project Plugin provides a nice light-weight alternative. Only certain properties can be inherited but the configuration is relatively simple.