Answer
Jenkins Shared Libraries
Shared Libraries are reusable Groovy code stored in a separate Git repository and imported into any Jenkinsfile. They are the DRY principle applied to pipelines.
Shared Library Repository Structure
CODE
jenkins-shared-library/
├── vars/
│ ├── buildMaven.groovy ← Global variable (call as buildMaven())
│ ├── runTests.groovy ← Call as runTests()
│ └── deployApp.groovy ← Call as deployApp()
├── src/
│ └── com/company/
│ ├── Utils.groovy ← Groovy class
│ └── Notifier.groovy ← Groovy class
└── resources/
└── templates/
└── email-template.html
Creating Shared Library Functions
GROOVY
// vars/buildMaven.groovy
def call(String goals = 'clean package') {
sh "mvn ${goals} -q"
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
GROOVY
// vars/runTests.groovy
def call(Map config = [:]) {
def browser = config.browser ?: 'chrome'
def env = config.env ?: 'staging'
def suite = config.suite ?: 'testng.xml'
sh """
mvn test \
-Dbrowser=${browser} \
-Denv=${env} \
-Dsurefire.suiteXmlFiles=${suite}
"""
junit testResults: 'target/surefire-reports/*.xml', allowEmptyResults: true
}
GROOVY
// vars/deployApp.groovy
def call(String environment, String version) {
withCredentials([string(credentialsId: "deploy-key-${environment}", variable: 'DEPLOY_KEY')]) {
sh """
./scripts/deploy.sh \
--env=${environment} \
--version=${version} \
--key=${DEPLOY_KEY}
"""
}
echo "Deployed version ${version} to ${environment}"
}
GROOVY
// vars/sendNotification.groovy
def call(String status) {
def color = status == 'SUCCESS' ? 'good' : 'danger'
def msg = "${status}: ${env.JOB_NAME} #${env.BUILD_NUMBER} - ${env.BUILD_URL}"
slackSend(
channel: '#ci-alerts',
color: color,
message: msg,
)
}
Registering the Shared Library in Jenkins
- ✓Jenkins → Manage Jenkins → Configure System
- ✓Scroll to Global Pipeline Libraries
- ✓Add:
- ✓Name:
my-shared-lib - ✓Default version:
main - ✓SCM: Git → URL:
https://github.com/org/jenkins-shared-library.git
- ✓Name:
Using the Shared Library in a Jenkinsfile
GROOVY
// Jenkinsfile in your project repository
// Import shared library (implicit — if registered as global)
@Library('my-shared-lib') _
// Or specify a version/branch
@Library('my-shared-lib@v2.1') _
pipeline {
agent any
stages {
stage('Build') {
steps {
// Call the shared library function
buildMaven('clean package -DskipTests')
}
}
stage('Test') {
steps {
runTests(
browser: 'chrome',
env: 'staging',
suite: 'smoke-testng.xml'
)
}
}
stage('Deploy') {
when { branch 'main' }
steps {
deployApp('production', '1.5.0')
}
}
}
post {
always {
sendNotification(currentBuild.currentResult)
}
}
}
Benefits
- ✓DRY: Write pipeline logic once, reuse across 100+ projects
- ✓Standardization: All teams use the same build/deploy pattern
- ✓Easy updates: Fix a bug in the library → all pipelines get the fix
- ✓Testing: Library code can be unit-tested (JenkinsPipelineUnit)
