Centralising Jenkins Pipelines with Shared Libraries: A Practical Guide
Tired of copy-and-pasting pipeline code across projects? Learn how Jenkins Shared Libraries let you keep reusable logic in one place, version it, and keep your jobs lean.
13 Jan 2026, 03:23 UTC

Problem: Duplicate Pipeline Code Across Projects
In many teams, several Jenkins jobs share identical or very similar steps: building a Docker image, running unit tests, or deploying to a staging environment. Copy-and-paste quickly turns into a maintenance nightmare. A change in one job’s build step often requires a ripple-effect of edits in dozens of other jobs, increasing the risk of human error and breaking pipelines.
Thesis: Use Jenkins Shared Libraries to Centralise Reusable Pipeline Logic
Jenkins Shared Libraries let you store Groovy or Java classes, global variables, and resources in a Git repository that any pipeline can import. By pinning pipelines to a specific library version, you isolate changes, avoid accidental breakage, and keep job definitions small and focused.
1. Setting Up a Minimal Shared Library
Before you can use a library, you need a Git repo with a specific folder layout:
my-lib/
├─ src/
│ └─ org/
│ └─ example/
│ └─ Hello.java
├─ vars/
│ └─ hello.groovy
└─ resources/
└─ config.yml
- src/ – Java classes that can be referenced in pipelines. The file above defines a simple
Helloclass with asayHello()method. - vars/ – Groovy scripts that become global variables. The
hello.groovyfile exposes asayHello()function that pipelines can call directly. - resources/ – Static files (YAML, JSON, etc.) that pipelines can read.
Example Java Class (src/org/example/Hello.java)
package org.example;
public class Hello {
public static String sayHello() {
return "Hello from the shared library!";
}
}
Example Groovy Variable (vars/hello.groovy)
def call() {
echo "Hello from the shared library variable!"
}
2. Registering the Library in Jenkins
Navigate to Manage Jenkins → Configure System → Global Pipeline Libraries. Add a new library:
- Name:
my-lib - Default version:
master(or a tag likev1.0) - Retrieval method: Git
- Repository URL:
https://github.com/yourorg/my-lib.git - Credentials: If the repo is private, add a Jenkins credential that holds an SSH key or a personal access token.
- Check
Use default versionif you want all pipelines to use the default branch unless they specify otherwise.
3. Using the Library in a Declarative Pipeline
Below is a minimal Jenkinsfile that imports the library and calls both the Java class and the Groovy variable:
pipeline {
agent any
stages {
stage('Example') {
steps {
// Import the library – the underscore is required for global libraries
@Library('my-lib') _
// Call Groovy variable – behaves like a function
hello()
// Call Java class method
script {
echo org.example.Hello.sayHello()
}
}
}
}
}
Run this job and the console should show:
[Pipeline] echo Hello from the shared library variable!
[Pipeline] echo Hello from the shared library!
Because the library is in a separate repo, you can change Hello.java or hello.groovy without touching the Jenkinsfile. To test version pinning, create a tag v1.0 on the library, pin the pipeline to that tag, modify the library, and confirm the job still uses the old version.
4. Trade-Offs and Limitations
- Security: Shared libraries are not sandboxed by default. If you import code from an untrusted repository, it could execute arbitrary Groovy code. Restrict the source to trusted repos and enable the Jenkins
Groovy Sandboxif needed. - Version Management: Without explicit version pinning, a change in the default branch can break downstream jobs. Always use tags or branch names in
@Library('my-lib@v1.0')and document the version strategy. - Library Size: A monolithic library can grow large, leading to longer job startup times as Jenkins loads the entire repo. Consider splitting responsibilities into smaller, focused libraries.
- Plugin Conflicts: Some plugins (e.g., Pipeline Utility Steps) may override or conflict with library steps. Verify compatibility after plugin upgrades.
- Learning Curve: New team members must understand the folder structure and the difference between
vars/andsrc/. Provide documentation or a README in the library repo.
Actionable Closing
Start small: pick a single reusable step (e.g., a Docker build) and move it into a shared library. Pin the pipeline to a tag, test, and iterate. Over time, you’ll build a catalog of library modules that can be shared across teams, reducing duplication and speeding up onboarding. Remember to keep the library repo under strict access control and to document version pinning practices in your team’s CI/CD guidelines.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.