Using Shared Libraries in a Jenkins Pipeline

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.mytoolsclass 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:

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.UtilsTools 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.
Thank you for reading! By using shared libraries in Jenkins you can simplify reusable code and make it accessible to multiple pipeline jobs. For more details on shared libraries check out the official Jenkins documentation here.