Takeaways from DevOps World 2018 — Part II

Shared pipeline libraries in Jenkins

This is my second post that is inspired by my visit to DevOps World 2018. My first post was about continuous deployment (CD) using Jenkins and Kubernetes.

Photo by Crystal Kwok on Unsplash

One of the recurring topics on DevOps World was the use of shared pipeline libraries. A Jenkins pipeline is a groovy script that defines your Jenkins job. If you don’t know it, read about it! It is awesome and an extremely powerful way to define your CI/CD process. Jenkins pipelines have been the preferred way for defining your jobs since the release of Jenkins 2 in 2016.

Although we used pipelines already, I did not get proper hands-on experience until earlier this year when we started a couple new projects. It didn’t take long until I found myself repeating most of the pipeline code (with minor differences of course) in different projects. For instance, I wrote a 80+ lines snippet of Groovy code to determine the new version number which we copy-pasted in all our pipelines. We, obviously, created a ticket on the backlog to create a ‘Jenkins plugin’ that would make this functionality available and shareable.

I learned that a pipeline library consists of one or more reusable functions and or classes that you can access from your Jenkins pipelines. You can share them by putting them in a Git repository (or something similar). Pipeline libraries were actually exactly what we needed. We can write functions and use them in all our pipelines. Which has many benefits like:

  • We have only one place to maintain the code (keeping it DRY)
  • We can share useful functions with other projects, teams and organisations
  • Our Jenkins pipelines become shorter and more readable

This last point was also subject of a talk called “Concise Pipelines with Shared Libraries” by Liam Newman. He pointed out that pipelines should be readable by anyone, they should not contain complex Groovy code but only consist of simple steps. He recommended that you put most of your Groovy code into shared libraries even if you don’t need it for sharing, just to simplify your Jenkins pipelines.

So how do we create a pipeline library? We create a repository first and in this empty repository we create a folder named vars. Say we want to create a function getLatestTag to get the latest tag on the repository. We will create two files in our vars directory:

  1. getLatestTag.groovy (the groovy file that contains our logic)
  2. getLatestTag.txt (the documentation on our function)

By convention, the filename is what the function name will be. Now, let’s write the logic. In our getLatestTag.groovy we have to define a function named call which is the function that is called when calling getLatestTag from our Jenkinsfile. Let’s look at the definition:

def call() {
def cmd = 'git tag --sort=v:refname | tail -n 1'
return sh(returnStdout: true, script: cmd).trim()

It is a very simple shell script that calls git tag and sorts based on version number and it picks the last line. We capture the output by setting returnStdout to true and return whatever the output is.

In our getLatestTag.txt we write our documentation:

Function that will get the latest tag from git. Requires tags to be fetched during checkout (this is not Jenkins standard git checkout behaviour).

That should clear things up (this documentation will become available in the Pipeline Syntax reference inside your Jenkins instance). Now we commit our code and push our commit to the remote repository. To make this function available to our Jenkins pipelines we will have to configure Jenkins to use our repository as shared library. Make sure to tick the Load implicitly box so we don’t have to do anything special to use our library.

Now that we have it all configured we can call getLatestTag from anywhere in our Jenkins pipeline:

// defined outside the stage so we can use it in other stages
def latestTag
node {
stage('Prepare') {
checkout scm
latestTag = getLatestTag()

See also the official documentation on Shared libraries where they share more possibilities of writing and using shared libraries.

If you need some inspiration for your library have a look at these public libraries: