Every so often we have a customer that cannot risk the big jump of moving to a newer Jenkins, but they are currently in need of some specific patch or other.
As a rule, CloudBees do not provide custom builds of Jenkins to customers (Note: we do support customers who wish to run their own custom builds of Jenkins, e.g. see the support terms for such customers)
But suppose you are under the clock… your Jenkins instance is suffering from a critical issue… the issue is fixed in a newer version of Jenkins… but you are on the final sprint before your next release goes GA and there is no time to upgrade Jenkins but the critical issue means that Jenkins is not working for you.
The only answer is to create a custom build of Jenkins with the fix cherry-picked onto the version you were running.
Here is Stephen’s cheat-sheet for creating just such a build:
You will need a machine to compile Jenkins on. It can be Mac OS-X, Linux or Windows (but build speed on Windows is significantly impaired due to anti-virus software… also GIT on windows is not as nice as on other operating systems)
You will need to install a recent Java JDK (6 or 7)
You will need to install Apache Maven (3.0.5 or 3.0.4 are recommended at present and certainly for building any Jenkins version prior to 1.520ish as 3.1.0 was only recently released and any plugin compatibility issues with Maven 3.1.0 and the Maven plugins used in Jenkins’ pom.xml files may not have been resolved prior to the release of Maven 3.1.0)
You will need to install GIT
Check that everything needed is on the path
$ java -version $ mvn -version $ git --version
On my machine I get the following
$ java -version java version "1.7.0_25" Java(TM) SE Runtime Environment (build 1.7.0_25-b15) Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode) $ mvn -version Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 13:51:28+0000) Maven home: /usr/share/java/maven-3.0.5 Java version: 1.7.0_25, vendor: Oracle Corporation Java home: /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre Default locale: en_US, platform encoding: UTF-8 OS name: "mac os x", version: "10.8.4", arch: "x86_64", family: "mac" $ git --version git version 188.8.131.52
$ git clone email@example.com:jenkinsci/jenkins.git
Switch to the tag you want to base off
$ cd jenkins $ git checkout jenkins-1.480.3
Verify that you have Maven and the Java JDK set up correctly (i.e. just do a quick build)
$ mvn package -DskipTests
Cherry pick the commits you want
$ git cherry-pick _________
Give it a version number to indicate that it is your build
$ mvn versions:set versions:commit -DnewVersion=1.480.3-yourcompany-01-SNAPSHOT
Use a version number that ends in
-SNAPSHOTuntil you are happy that you have the build you will put into production. For builds that you will put into production, remove the
-SNAPSHOT. Once you have built a version number without a
-SNAPSHOTuse a higher version number for all subsequent builds.
Build Jenkins with your commits
$ mvn clean package -DskipTests
Note: Ideally you would not skip the tests, but getting the test suite to work the first time building Jenkins can be tricky
The results of the build are
Extra Brownie Points
If this is something you expect to be doing on a regular basis, you will likely want to do the following
Fork the Jenkins repository on GitHub into your own GitHub account
Change the origin of your GIT checkout to be your fork
Push your patch-set to a named branch, e.g. jenkins-1.480.3-patchset
When you want to move the baseline of your patchset to a new version of jenkins, you would then rebase the patchset onto the newer version of Jenkins, e.g.
$ git checkout jenkins-1.480.3-patchset $ git rebase jenkins-1.509.2 $ git checkout -b jenkins-1.509.2-patchset $ git push -u origin jenkins-1.509.2-patchset
If you intend on including fixes that you wrote yourself and which are not cherry-picks from upstream, ensure that your patchset has all the cherry-picks first before the custom patches. That will make rebasing the patchset onto a newer version of Jenkins easiest.
Do not add the version number changes (i.e. from the
mvn versions:setcommand) to your patchset, e.g. your release process would probably be something like this
$ git checkout jenkins-1.480.3-patchset -b jenkins-1.480.3-yourcompany $ mvn clean versions:set versions:commit -DnewVersion=1.480.3-yourcompany-01 $ git commit -a -m "Update version to 1.480.3-yourcompany-01" $ git tag jenkins-1.480.3-yourcompany-01 $ git checkout jenkins-1.480.3-yourcompany-01 $ git branch -d jenkins-1.480.3-yourcompany $ mvn package -DskipTests
That will keep the version number changes out of your patch set but also keep a tag of what you built.
Note: power GIT users will probably cringe at my creation and destruction of the
jenkins-1.480.3-yourcompanybranch, but they should know the “correct” way to do it and the commands to use also. The above is aimed for novice GIT users and will work for them
I hope you found this useful. And I also hope that if you have to travel this road, you find the cherry-picks easy to merge. Merging cherry-picks from a very new Jenkins (anything within the last month) onto a very old Jenkins (anything more than a year old) can be painful/fun…
Stephen Connolly has over 20 years experience in software development. He is involved in a number of open source projects, including Jenkins. Stephen was one of the first non-Sun committers to the Jenkins project and developed the weather icons. Stephen lives in Dublin, Ireland - where the weather icons are particularly useful. Follow Stephen on Twitter and on his blog.