jenkins
Jenkins Shared Libraries: Reusable Pipeline Code
Intermediate
14 minutes
October 2026
CloudOpsGuide Team
Jenkins Shared Libraries: Reusable Pipeline Code
Create shared libraries to standardise pipeline code across teams — vars, src, resources, and best practices.
Table of Contents
- What Is a Shared Library
- Library Structure
- Setting Up the Library
- Writing Shared Functions
- Using in Pipelines
- Versioning
- Best Practices
What Is a Shared Library
A Jenkins Shared Library is a Git repository containing reusable pipeline code that can be loaded into any Jenkinsfile. Instead of copying the same deploy.sh wrapper into 50 pipelines, you define it once and call it everywhere.
vars/ — global functions callable from pipelines
src/ — Groovy classes (imported like normal Groovy)
resources/ — non-code files (YAML templates, scripts)
Library Structure
jenkins-shared-library/
├── vars/
│ ├── buildApp.groovy # call with buildApp()
│ ├── deployToK8s.groovy # call with deployToK8s()
│ ├── notifySlack.groovy
│ └── logUtils.groovy
├── src/
│ └── com/
│ └── company/
│ ├── Kubernetes.groovy # class for complex logic
│ └── PipelineConfig.groovy
└── resources/
├── k8s/
│ └── deployment.yaml # reusable K8s manifest template
└── scripts/
└── smoke-test.sh # shared shell script
Setting Up the Library
1. Create the Git Repo
mkdir jenkins-shared-library
cd jenkins-shared-library
mkdir -p vars src/com/company resources/{k8s,scripts}
git init && git add . && git commit -m "Initial library"
2. Configure in Jenkins
Manage Jenkins → System → Global Pipeline Libraries:
- Name:
shared-lib(this is what pipelines reference) - Default version:
mainor a git tag - Retrieval method: Modern SCM → Git
- Repo URL:
https://github.com/myorg/jenkins-shared-library.git
Writing Shared Functions
Simple Function — vars/logUtils.groovy
def info(String message) {
echo "[INFO] ${message}"
}
def error(String message) {
echo "[ERROR] ${message}"
error(message)
}
def success(String message) {
echo "[SUCCESS] ${message}"
}
Function with Arguments — vars/deployToK8s.groovy
def call(Map config) {
def image = config.image ?: error("image is required")
def namespace = config.namespace ?: "default"
def replicas = config.replicas ?: 1
logUtils.info "Deploying ${image} to ${namespace} with ${replicas} replicas"
sh """
kubectl set image deployment/app app=${image} -n ${namespace} || \
kubectl create deployment app --image=${image} -n ${namespace}
kubectl scale deployment/app --replicas=${replicas} -n ${namespace}
kubectl rollout status deployment/app -n ${namespace} --timeout=300s
"""
}
Loading Resources — vars/renderK8sManifest.groovy
def call(Map config) {
// Load a YAML template from resources/
def template = libraryResource('k8s/deployment.yaml')
// Replace placeholders
template = template.replace('{{IMAGE}}', config.image)
template = template.replace('{{NAMESPACE}}', config.namespace)
template = template.replace('{{REPLICAS}}', config.replicas.toString())
writeFile file: 'rendered-deployment.yaml', text: template
sh 'kubectl apply -f rendered-deployment.yaml'
}
Groovy Class — src/com/company/Kubernetes.groovy
package com.company
class Kubernetes implements Serializable {
def steps
Kubernetes(steps) {
this.steps = steps
}
def deploy(String image, String namespace) {
steps.sh "kubectl apply -f deployment.yaml -n ${namespace}"
}
def rollback(String deployment, String namespace) {
steps.sh "kubectl rollout undo deployment/${deployment} -n ${namespace}"
}
def scale(String deployment, int replicas, String namespace) {
steps.sh "kubectl scale deployment/${deployment} --replicas=${replicas} -n ${namespace}"
}
}
Using in Pipelines
Load at the Top
@Library('shared-lib') _
// or pinned version:
// @Library('shared-lib@v1.2.0') _
pipeline {
agent any
stages {
stage('Deploy') {
steps {
deployToK8s(
image: 'myapp:1.2.0',
namespace: 'staging',
replicas: 3
)
}
}
}
}
Using Classes
@Library('shared-lib') _
def k8s = new com.company.Kubernetes(this)
pipeline {
agent any
stages {
stage('Deploy') {
steps {
script {
k8s.deploy('myapp:1.0', 'staging')
}
}
}
}
}
Library-Specific Methods in Pipelines
// In Jenkinsfile — call any var/ function directly
deployToK8s image: 'app:v2', namespace: 'prod', replicas: 5
renderK8sManifest image: 'app:v2', namespace: 'prod'
notifySlack channel: '#deploys', message: 'Deployed app:v2 to prod'
Versioning
Tag Releases
git tag v1.0.0
git push origin v1.0.0
Pin in Pipelines
@Library('shared-lib@v1.0.0') _ // pinned — stable
@Library('shared-lib@main') _ // latest — risky for prod
Global Default Version
In Global Pipeline Libraries, set default version to a tag (v1.0.0), not main. Override per-pipeline for testing.
Best Practices
1. Keep Functions Small and Focused
// Bad — one function does everything
def call(Map config) {
// 200 lines of build + test + deploy + notify
}
// Good — compose small functions
buildApp(image: config.image)
testApp(image: config.image)
deployToK8s(image: config.image, namespace: config.namespace)
notifySlack(channel: '#deploys', message: "Deployed ${config.image}")
2. Return Values for Data
// vars/getVersion.groovy
def call() {
return sh(script: 'git describe --tags', returnStdout: true).trim()
}
// In Jenkinsfile
def version = getVersion()
echo "Deploying version ${version}"
3. Validate Inputs Early
def call(Map config) {
if (!config.image) error("image is required")
if (!config.namespace) error("namespace is required")
if (config.replicas && config.replicas < 0) error("replicas must be positive")
// ...
}
4. Don't Expose Secrets
// Bad — hardcoded
def call(Map config) {
sh "docker login -u admin -p secret123"
}
// Good — pass credentials ID
def call(Map config) {
steps.withCredentials([usernamePassword(
credentialsId: config.credentialsId ?: 'default-creds',
usernameVariable: 'USER',
passwordVariable: 'PASS'
)]) {
sh 'echo $PASS | docker login -u $USER --password-stdin'
}
}
5. Document Your API
Each vars/*.groovy should have a README or comments showing usage:
/**
* Deploy to Kubernetes
*
* @param config.image Docker image tag (required)
* @param config.namespace K8s namespace (default: "default")
* @param config.replicas Replica count (default: 1)
* @param config.timeout Rollout timeout in seconds (default: 300)
*/
def call(Map config) { ... }
Common Patterns
Pipeline Wrapper
// vars/standardPipeline.groovy — defines the whole pipeline
def call(Map config) {
pipeline {
agent any
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Build') {
steps { buildApp(image: config.image) }
}
stage('Test') {
steps { testApp() }
}
stage('Deploy') {
when { branch 'main' }
steps {
deployToK8s(
image: config.image,
namespace: config.namespace
)
}
}
}
post {
always { notifySlack(channel: '#builds') }
}
}
}
Then every Jenkinsfile becomes:
@Library('shared-lib') _
standardPipeline(image: 'myapp', namespace: 'production')
Related Articles
Last Updated: October 2026
Author: CloudOpsGuide Team
Difficulty: Intermediate
Estimated Reading Time: 14 minutes