Using Shared Libraries in a Jenkins Pipeline
By: Tate Galbraith
Tags: Jenkins, Technology, Software Development, Programming, Code

Extending code libraries across Jenkins pipelines can seem like a daunting task. There are many different ways to accomplish the same thing in a Jenkins pipeline. Deciding between declarative or scripted pipelines. Choosing where and how to import libraries. There’s a laundry list of tasks for the Jenkins developer to work through. Not to mention keeping track of the environment and state of a pipeline as it evolves. So what’s the best way to share common functionality in different pipelines?

Using shared libraries (or Global Pipeline Libraries) we can easily and automatically pull reusable functionality into pipelines. Configuration is handled by Jenkins and there’s no messing about with manual path entries or environment variables. Shared libraries save implementation time, allow for easier code reuse and are simpler to manage in the long run.

Let’s take a look at how to setup a simple shared library and implement it in one of our pipelines.

Build the library

In order to use shared libraries, we must first layout the proper directory structure in the repository and write some Groovy code. For this example, we’ll use a basic Groovy class file that simply runs echo and outputs a message in the Jenkins console. Let’s setup a new directory for this inside our existing Git repository (this can be wherever you store your Jenkinsfiles and any accompanying Groovy files):

src/org/mytools/

Inside this directory you’ll create a new Groovy file called:

Tools.groovy

You should now have the following structure:

src/org/mytools/Tools.groovy

Now open up the Tools.groovy file and place the following code inside:

package org.mytools class Tools implements Serializable { private static final long serialVersionUID

def steps Tools(steps) {

this.steps = steps

} void myEcho(String msg) {

steps.echo msg

} }

Let’s break down what is happening here. In the first line we’re defining the package that this will be part of. This is a Java package declaration which let’s us group code together as one unit (most of the files inside this directory should be in the same package).

In the next line we’re defining our class Tools which is an implementation of the Serializable class. This enables us to save state on our classes during a Jenkins pipeline. The serialVersionUID provides the variable for saving a unique state ID on the object.

The next few lines inside the Tools class handle pulling in the steps variable from the calling pipeline. We have to accept the steps as a parameter because classes in shared libraries have no knowledge of pipeline step functions like echo or sh . This tells our class that we expect this to be passed in as a parameter when instantiated.

Finally, we setup our myEcho function which simply accepts a string and then uses the pipeline echo step to print it to the console. This wraps up the class and will be where we place the bulk of our functionality.

That’s it for our directory structure and Groovy configuration. If at any point you get stuck setting up your library, you can reference the official Jenkins documentation on shared libraries.

Next, let’s look at how we pull this new package into Jenkins.

Configure the library in Jenkins

In order to use shared libraries inside of a pipeline in Jenkins we need to configure the library. Open up the Jenkins instance and navigate to Manage Jenkins -> Configure System. Scroll down until you locate the Global Pipeline Libraries section. Enter the relevant information as it pertains to your Git repository and checkout details:

Configuring a Global Shared Library in Jenkins.

You can leave the defaults checked/unchecked, but make one consideration regarding the Load Implicitly box. If you wish to have your libraries available automatically in every pipeline you may check this box, otherwise leave it blank and we’ll cover importing them manually. In the beginning I would advise leaving this unchecked so you are explicit about what libraries get used.

Once the setup of the library and associated repository is complete, let’s move on to actually utilizing it in a pipeline.

Import the library in a pipeline

Using shared libraries in a pipeline is incredibly simple and you’ll wonder why you hadn’t done it sooner. After building and configuring the shared library in Jenkins it is now available to pipelines and only needs to be declared. Let’s look at a sample pipeline that uses our new library:

@Library('mytools') import org.mytools.Utils Tools tools = new Tools(this) pipeline {

agent any

stages {

stage('test') {

steps {

script {

tools.myEcho('test')

}

}

}

}

}

In the example pipeline above we add several items before declaring the pipeline itself. The most important element is the @Library entry. This tells the pipeline to use our new shared mytools library. However, this alone is not sufficient, we need to tell the pipeline which classes to use and then instantiate them.

First we’ll need to import the Utils class and then create a new object for it by calling new Tools(this) . Remember earlier when we said we’d have to pass in our steps? By providing the this keyword as a parameter to our class we provide the necessary pipeline context for things like echo .

Now that our object has been imported and created we can use it just like any other object. Inside any script blocks within a declarative pipeline we can simply call tools.myEcho and observe the output.

Shared libraries are straightforward and efficient. They save time and allow more of the focus to be on the core functionality of the pipeline, instead of where resources are and how they get imported. With shared libraries we can easily add more classes, modules and other Groovy objects without having to jump through hoops.