Articles on: Jenkins Service

Jenkins Shared Library Tutorial - Advanced Guide

Jenkins Shared Library - Advanced Guide

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#jenkins-shared-library---advanced-guide)

Prerequisites: Complete the main tutorial first to understand the basics.

This guide covers advanced topics for mastering Jenkins Shared Libraries.


Table of Contents

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#table-of-contents)

  1. Team-Based Architecture
  2. Testing Your Shared Library
  3. Job DSL and Seed Jobs
  4. Advanced Patterns
  5. Best Practices
  6. Enterprise Collaboration


Team-Based Architecture

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#team-based-architecture)

Modern Jenkins CI/CD has evolved from environment-based structures (development/production) to domain-specific team organization. This approach provides better scalability, team autonomy, and technology-specific optimizations.

Team Organization Model

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#team-organization-model)

jenkins-controllers/
├── common/ # Cross-team shared utilities
├── data-science/ # ML/AI workflows and experimentation
├── engineering/ # Software development and deployment
└── devops/ # Infrastructure and platform management


Seed Job Configuration

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#seed-job-configuration)

The seed job is configured to work with team-based controllers using JENKINS_TEAM_NAME instead of JENKINS_ENVIRONMENT_NAME.

Filejobs/jobSeed.groovy

// Team-based seed job pipeline
final String projectDir = 'demo-repository/jobs'
final String commonJobsDir = 'common'

// Team variables that must be set on the Jenkins controller
assert env.JENKINS_TEAM_NAME, 'JENKINS_TEAM_NAME must be set (data-science, engineering, devops)'
assert env.JENKINS_TEAM_NAME != commonJobsDir, 'JENKINS_TEAM_NAME cannot be "common"'
assert env.JENKINS_TEAM_NAME in ['data-science', 'engineering', 'devops'], 'JENKINS_TEAM_NAME must be one of: data-science, engineering, devops'

final String teamJobDslDir = "${projectDir}/jenkins-controllers/${env.JENKINS_TEAM_NAME}/src/dsl/groovy"
final String commonJobDslDir = "${projectDir}/jenkins-controllers/${commonJobsDir}/src/dsl/groovy"

node('controller-agent') {
stage('Process Job DSL') {
jobDsl(
additionalParameters: [
ROOT_FOLDER: rootFolder,
TEAM: env.JENKINS_TEAM_NAME
],
targets: "${commonJobDslDir}/**/*.groovy\n${teamJobDslDir}/**/*.groovy"
)
}
}


Team-Specific Job DSL Examples

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#team-specific-job-dsl-examples)


Data Science Team Jobs

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#data-science-team-jobs)

Filejenkins-controllers/data-science/src/dsl/groovy/dataScienceJobs.groovy

String rootFolder = ROOT_FOLDER ?: ''
String team = TEAM ?: 'data-science'

// ML Experiment folder structure
folder("${rootFolder}/ml-experiments") {
displayName('ML Experiments')
description('Machine learning model development and experimentation')
}

// Model Training Pipeline
pipelineJob("${rootFolder}/ml-experiments/model-training") {
displayName('Model Training Pipeline')

parameters {
stringParam('MODEL_NAME', 'default-model', 'Name of the model to train')
choiceParam('ALGORITHM', ['xgboost', 'random-forest', 'neural-network'], 'ML Algorithm')
stringParam('DATASET_VERSION', 'latest', 'Dataset version to use')
booleanParam('ENABLE_HYPERPARAMETER_TUNING', false, 'Enable hyperparameter optimization')
}

definition {
cpsScm {
scm {
git {
remote {
url('https://github.com/your-org/ml-models.git')
credentials('git-credentials')
}
scriptPath('jenkins-controllers/data-science/src/main/groovy/ml-experiments/model-training-pipeline.groovy')
}
}
}
}
}

// Model Deployment Pipeline
pipelineJob("${rootFolder}/model-deployment/model-serving") {
displayName('Model Serving Deployment')

parameters {
stringParam('MODEL_NAME', '', 'Model name from MLflow registry')
stringParam('MODEL_VERSION', '', 'Model version to deploy')
choiceParam('DEPLOYMENT_TARGET', ['staging', 'production', 'a-b-test'], 'Deployment target')
choiceParam('SERVING_PLATFORM', ['sagemaker', 'kubernetes', 'lambda'], 'Serving platform')
}

definition {
cpsScm {
scm {
git {
scriptPath('jenkins-controllers/data-science/src/main/groovy/model-deployment/model-serving.groovy')
}
}
}
}
}


Engineering Team Jobs

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#engineering-team-jobs)

Filejenkins-controllers/engineering/src/dsl/groovy/engineeringJobs.groovy

String rootFolder = ROOT_FOLDER ?: ''

// Application deployment with multiple strategies
pipelineJob("${rootFolder}/applications/app-deployment") {
displayName('Application Deployment Pipeline')

parameters {
stringParam('APPLICATION_NAME', '', 'Application name to deploy')
stringParam('VERSION', '', 'Version to deploy')
choiceParam('ENVIRONMENT', ['development', 'staging', 'production'], 'Target environment')
choiceParam('DEPLOYMENT_STRATEGY', ['rolling', 'blue-green', 'canary'], 'Deployment strategy')
booleanParam('RUN_SMOKE_TESTS', true, 'Run smoke tests after deployment')
}

definition {
cpsScm {
scm {
git {
scriptPath('jenkins-controllers/engineering/src/main/groovy/applications/deployment-pipeline.groovy')
}
}
}
}
}

// E2E Testing Pipeline
pipelineJob("${rootFolder}/testing/e2e-testing") {
displayName('End-to-End Testing Suite')

parameters {
choiceParam('TEST_SUITE', ['smoke', 'regression', 'full', 'performance'], 'Test suite to run')
choiceParam('ENVIRONMENT', ['development', 'staging'], 'Environment to test against')
stringParam('BROWSER', 'chrome', 'Browser for UI tests')
booleanParam('PARALLEL_EXECUTION', true, 'Run tests in parallel')
}

definition {
cpsScm {
scm {
git {
scriptPath('jenkins-controllers/engineering/src/main/groovy/testing/e2e-testing.groovy')
}
}
}
}
}


DevOps Team Jobs

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#devops-team-jobs)

Filejenkins-controllers/devops/src/dsl/groovy/devopsJobs.groovy

String rootFolder = ROOT_FOLDER ?: ''

// Infrastructure Pipeline
pipelineJob("${rootFolder}/infrastructure/terraform-deployment") {
displayName('Terraform Infrastructure Pipeline')

parameters {
choiceParam('ACTION', ['plan', 'apply', 'destroy'], 'Terraform action')
choiceParam('WORKSPACE', ['development', 'staging', 'production'], 'Terraform workspace')
stringParam('TERRAFORM_VERSION', '1.5.0', 'Terraform version to use')
booleanParam('AUTO_APPROVE', false, 'Auto-approve apply (dev only)')
}

definition {
cpsScm {
scm {
git {
scriptPath('jenkins-controllers/devops/src/main/groovy/infrastructure/terraform-pipeline.groovy')
}
}
}
}
}

// Kubernetes Management
pipelineJob("${rootFolder}/platform-engineering/k8s-deployment") {
displayName('Kubernetes Cluster Management')

parameters {
choiceParam('CLUSTER', ['dev-cluster', 'staging-cluster', 'prod-cluster'], 'Target cluster')
choiceParam('ACTION', ['deploy', 'update', 'rollback', 'scale'], 'Kubernetes action')
stringParam('NAMESPACE', 'default', 'Target namespace')
stringParam('MANIFEST_PATH', 'k8s/', 'Path to Kubernetes manifests')
}

definition {
cpsScm {
scm {
git {
scriptPath('jenkins-controllers/devops/src/main/groovy/platform-engineering/kubernetes-deployment.groovy')
}
}
}
}
}


Team Configuration Management

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#team-configuration-management)

Teams can have their own configuration while sharing common patterns:

Filesrc/com/example/jenkins/config/TeamConfig.groovy

package com.example.jenkins.config

class TeamConfig {

Map teams = [
'data-science': [
tools: ['python', 'mlflow', 'jupyter'],
platforms: ['sagemaker', 'kubernetes'],
notifications: [slack: '#ml-builds'],
docker: [registry: 'ml-registry.company.com']
],
'engineering': [
tools: ['java', 'node', 'docker'],
platforms: ['kubernetes', 'lambda'],
notifications: [slack: '#app-builds'],
docker: [registry: 'app-registry.company.com']
],
'devops': [
tools: ['terraform', 'ansible', 'kubectl'],
platforms: ['aws', 'kubernetes'],
notifications: [slack: '#infra-builds', email: 'devops@company.com'],
docker: [registry: 'infra-registry.company.com']
]
]

Map getTeamConfig(String team) {
if (!teams.containsKey(team)) {
throw new IllegalArgumentException("Unknown team: ${team}")
}
return teams[team]
}
}


Testing Your Shared Library

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#testing-your-shared-library)

Testing is crucial for maintaining reliable shared libraries. We use JenkinsPipelineUnit with Spock framework.


Unit Test Example

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#unit-test-example)

Filetest/unit/groovy/com/example/jenkins/shell/BashSpec.groovy

package com.example.jenkins.shell

import spock.lang.Specification
import spock.lang.Unroll

class BashSpec extends Specification {

Script mockSteps
Bash bash

def setup() {
mockSteps = GroovyMock()
}

def 'should throw exception when script is null'() {
given:
bash = new Bash(mockSteps)

when:
bash.formatScript(null)

then:
thrown(NullPointerException)
}

@Unroll
def 'should set fail-fast to #expected when failFast=#enabled'() {
given:
bash = new Bash(mockSteps, false, false, enabled)

when:
String formattedScript = bash.formatScript("echo 'Hello'")

then:
formattedScript.contains(expected)

where:
enabled || expected
true || 'set -e'
false || 'set +e'
}

def 'should execute script successfully'() {
given:
bash = new Bash(mockSteps, false, false, true)
String testScript = "echo 'test'"

when:
bash('Test execution', testScript)

then:
1 * mockSteps.echo('Executing: Test execution')
1 * mockSteps.sh(_) >> 0
}
}


Testing Global Variables

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#testing-global-variables)

Filetest/unit/groovy/com/example/jenkins/vars/LogSpec.groovy

package com.example.jenkins.vars

import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.Before
import org.junit.Test

class LogSpec extends BasePipelineTest {

@Override
@Before
void setUp() throws Exception {
super.setUp()

// Mock Jenkins steps
helper.registerAllowedMethod('ansiColor', [String, Closure], { String key, Closure body ->
body()
})
helper.registerAllowedMethod('echo', [String], { String message ->
println(message)
})
}

@Test
void 'test basic log call'() {
def log = loadScript('vars/log.groovy')
log.call('Test message')
assertJobStatusSuccess()
}

@Test
void 'test log info convenience method'() {
def log = loadScript('vars/log.groovy')
log.info('Info message')
assertJobStatusSuccess()
}
}


Running Tests

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#running-tests)

# Run all tests
./gradlew test

# Run specific test
./gradlew test --tests "BashSpec"

# Generate coverage report
./gradlew jacocoTestReport
# Report: build/reports/jacoco/test/html/index.html


Job DSL and Seed Jobs

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#job-dsl-and-seed-jobs)

Job DSL allows you to define Jenkins jobs as code, making your CI/CD infrastructure reproducible and version-controlled.


Seed Job Pipeline

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#seed-job-pipeline)

The seed job is a special pipeline that creates and manages other Jenkins jobs using the team-based architecture.

Filejobs/jobSeed.groovy

// Team-based seed job pipeline - runs on Jenkins controllers to create/update jobs

final String projectDir = 'demo-repository/jobs'
final String commonJobsDir = 'common'

// Team variables that must be set on the Jenkins controller
assert env.JENKINS_TEAM_NAME, 'JENKINS_TEAM_NAME must be set (data-science, engineering, devops)'
assert env.JENKINS_TEAM_NAME != commonJobsDir, 'JENKINS_TEAM_NAME cannot be "common"'
assert env.JENKINS_TEAM_NAME in ['data-science', 'engineering', 'devops'], 'JENKINS_TEAM_NAME must be one of: data-science, engineering, devops'
assert env.BRANCH_NAME, 'BRANCH_NAME must be set'

final Boolean isMainBranch = env.BRANCH_IS_PRIMARY == 'true'
final String branchFolderName = env.BRANCH_NAME.replaceAll('/', '-')
final String rootFolder = isMainBranch ? '' : "PROTOTYPE-JOBS/${branchFolderName}"

// Paths to Job DSL scripts
final String teamJobDslDir = "${projectDir}/jenkins-controllers/${env.JENKINS_TEAM_NAME}/src/dsl/groovy"
final String commonJobDslDir = "${projectDir}/jenkins-controllers/${commonJobsDir}/src/dsl/groovy"

node('controller-agent') {

stage('Checkout') {
checkout(
changelog: true,
poll: false,
scm: [
$class: 'GitSCM',
branches: [[name: "*/${env.BRANCH_NAME}"]],
userRemoteConfigs: [[
credentialsId: 'github-pat',
url: 'https://github.com/your-org/jenkins-shared-library.git'
]]
]
)
}

stage('Process Job DSL') {
echo "Processing Job DSL scripts for team: ${env.JENKINS_TEAM_NAME}"

jobDsl(
additionalParameters: [
ROOT_FOLDER: rootFolder,
TEAM: env.JENKINS_TEAM_NAME
],
sandbox: false, // Requires Script Security for Job DSL to be disabled
additionalClasspath: [
"${projectDir}/src/lib",
'src' // Include shared library classes
].join('\n'),
failOnMissingPlugin: true,
failOnSeedCollision: true,
removedConfigFilesAction: 'DELETE',
removedJobAction: isMainBranch ? 'DELETE' : 'IGNORE',
removedViewAction: isMainBranch ? 'DELETE' : 'IGNORE',
targets: "${commonJobDslDir}/**/*.groovy\n${teamJobDslDir}/**/*.groovy",
unstableOnDeprecation: true
)
}

stage('Summary') {
echo """
========================================
Job DSL Processing Complete
========================================
Team: ${env.JENKINS_TEAM_NAME}
Branch: ${env.BRANCH_NAME}
Is Main Branch: ${isMainBranch}
Root Folder: ${rootFolder ?: '(top level)'}
========================================
""".stripIndent()
}
}


Job DSL Script Example

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#job-dsl-script-example)

Filejobs/jenkins-controllers/common/src/dsl/groovy/buildJobs.groovy

// Job DSL script to create build jobs

String rootFolder = ROOT_FOLDER ?: ''
String environment = ENVIRONMENT ?: 'development'

folder("${rootFolder}/build-jobs") {
displayName('Build Jobs')
description('Automated build jobs for applications')
}

pipelineJob("${rootFolder}/build-jobs/app-build") {
displayName('Application Build')

parameters {
stringParam('GIT_BRANCH', 'main', 'Git branch to build')
choiceParam('BUILD_TYPE', ['debug', 'release'], 'Build type')
booleanParam('RUN_TESTS', true, 'Run unit tests')
}

properties {
disableConcurrentBuilds()
buildDiscarder {
strategy {
logRotator {
numToKeepStr('50')
daysToKeepStr('30')
}
}
}
}

triggers {
scm('H/5 * * * *') // Poll every 5 minutes
}

definition {
cpsScm {
scm {
git {
remote {
url('https://github.com/your-org/your-app.git')
credentials('git-credentials')
}
branches('main', 'develop')
scriptPath('Jenkinsfile')
}
}
}
}
}

// Multibranch pipeline
multibranchPipelineJob("${rootFolder}/build-jobs/app-multibranch") {
displayName('Application Multibranch Build')

branchSources {
git {
id('app-multibranch')
remote('https://github.com/your-org/your-app.git')
credentialsId('git-credentials')
includes('main develop feature/* bugfix/*')
}
}

orphanedItemStrategy {
discardOldItems {
numToKeep(10)
}
}
}


Job Templates Library

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#job-templates-library)

Filejobs/src/lib/JobTemplates.groovy

package lib

class JobTemplates {

/**
* Create a standard microservice build job.
*/
static void createMicroserviceBuildJob(def dslFactory, String rootFolder, Map config) {
String jobName = "${rootFolder}/microservices/${config.name}"

dslFactory.pipelineJob(jobName) {
displayName(config.displayName ?: config.name)
description(config.description ?: "Build job for ${config.name}")

parameters {
stringParam('GIT_BRANCH', config.defaultBranch ?: 'main', 'Branch to build')
booleanParam('DEPLOY_TO_DEV', true, 'Deploy to development')
}

properties {
disableConcurrentBuilds()
}

triggers {
githubPush()
}

definition {
cps {
script("""
@Library('my-shared-lib@main') _

pipeline {
agent any
stages {
stage('Build') {
steps {
buildApp(
language: '${config.language}',
buildTool: '${config.buildTool}'
)
}
}
stage('Docker') {
steps {
buildDockerImage(
imageName: '${config.dockerImage}'
)
}
}
}
}
""".stripIndent())
}
}
}
}

/**
* Create folder structure for a team.
*/
static void createTeamFolder(def dslFactory, String rootFolder, Map config) {
String teamFolder = "${rootFolder}/${config.teamName}"

dslFactory.folder(teamFolder) {
displayName(config.displayName ?: config.teamName)
description("Jobs for ${config.teamName} team")
}

['build', 'deploy', 'utilities'].each { subfolder ->
dslFactory.folder("${teamFolder}/${subfolder}") {
displayName(subfolder.capitalize())
}
}
}
}

Usage:

import lib.JobTemplates

String rootFolder = ROOT_FOLDER ?: ''

JobTemplates.createTeamFolder(this, rootFolder, [
teamName: 'platform-team',
displayName: 'Platform Team'
])

JobTemplates.createMicroserviceBuildJob(this, rootFolder, [
name: 'user-service',
language: 'java',
buildTool: 'gradle',
dockerImage: 'company/user-service'
])


Production Deployment Jobs

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#production-deployment-jobs)

Filejobs/jenkins-controllers/production/src/dsl/groovy/productionJobs.groovy

String rootFolder = ROOT_FOLDER ?: ''

pipelineJob("${rootFolder}/production-deployments/deploy-app") {
displayName('Deploy to Production')

parameters {
stringParam('VERSION', '', 'Version to deploy')
stringParam('GIT_TAG', '', 'Git tag to deploy')
}

properties {
disableConcurrentBuilds()
authorizationMatrix([
'hudson.model.Item.Build:production-deployers'
])
}

definition {
cps {
script('''
@Library('my-shared-lib@main') _

pipeline {
agent any
stages {
stage('Approval') {
steps {
timeout(time: 24, unit: 'HOURS') {
input(
message: 'Approve deployment?',
submitter: 'production-approvers'
)
}
}
}
stage('Deploy') {
steps {
deployToK8s(
namespace: 'production',
version: params.VERSION
)
}
}
}
}
'''.stripIndent())
}
}
}


Advanced Patterns

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#advanced-patterns)

Pattern 1: Configuration as Code

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#pattern-1-configuration-as-code)

Filesrc/com/example/jenkins/config/PipelineConfig.groovy

package com.example.jenkins.config

class PipelineConfig {

Map environments = [
development: [
kubernetes: [namespace: 'dev', cluster: 'dev-cluster'],
docker: [registry: 'registry.dev.company.com'],
notifications: [slack: '#dev-builds']
],
production: [
kubernetes: [namespace: 'production', cluster: 'prod-cluster'],
docker: [registry: 'registry.company.com'],
notifications: [slack: '#prod-deployments', email: 'team@company.com']
]
]

Map getEnvironmentConfig(String environment) {
if (!environments.containsKey(environment)) {
throw new IllegalArgumentException("Unknown environment: ${environment}")
}
return environments[environment]
}
}


Pattern 2: Plugin Wrapper

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#pattern-2-plugin-wrapper)

Filevars/withKubernetes.groovy

/**
* Wrapper for Kubernetes operations with automatic cleanup.
*/
def call(Map config, Closure body) {
String namespace = config.namespace ?: 'default'
String cluster = config.cluster
String credentialsId = config.credentialsId ?: 'k8s-credentials'

try {
withCredentials([file(credentialsId: credentialsId, variable: 'KUBECONFIG')]) {
sh """
kubectl config use-context ${cluster}
kubectl config set-context --current --namespace=${namespace}
"""
body()
}
} finally {
sh 'rm -f $KUBECONFIG'
}
}

Usage:

withKubernetes(cluster: 'production', namespace: 'apps') {
sh 'kubectl get pods'
sh 'kubectl apply -f deployment.yaml'
}


Pattern 3: Dynamic Pipeline Generation

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#pattern-3-dynamic-pipeline-generation)

Filevars/dynamicPipeline.groovy

/**
* Generates pipeline dynamically based on repository structure.
*/
def call(Map config) {
List<String> services = findServices()

pipeline {
agent any
stages {
stage('Parallel Builds') {
steps {
script {
Map parallelStages = [:]

services.each { service ->
parallelStages[service] = {
stage(service) {
dir(service) {
buildApp()
runTests()
}
}
}
}

parallel parallelStages
}
}
}
}
}
}

List<String> findServices() {
def services = []
def dirs = findFiles(glob: '**/package.json')
dirs.each { file ->
services.add(file.path.split('/')[0])
}
return services.unique()
}


Best Practices

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#best-practices)

1. Versioning and Tagging

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#1-versioning-and-tagging)

// ❌ Bad - uses latest, unpredictable
@Library('my-shared-lib') _

// ✅ Good - uses specific version
@Library('my-shared-lib@v1.2.3') _

// ✅ Good - uses branch for development
@Library('my-shared-lib@develop') _


2. Error Handling

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#2-error-handling)

def call(Map config) {
try {
validateConfig(config)
performAction(config)
} catch (Exception e) {
log.error("Failed: ${e.message}")
currentBuild.result = 'FAILURE'
throw e
} finally {
cleanup()
}
}

private void validateConfig(Map config) {
List<String> required = ['param1', 'param2']
List<String> missing = required.findAll { !config.containsKey(it) }

if (missing) {
throw new IllegalArgumentException("Missing: ${missing.join(', ')}")
}
}


3. Documentation Standards

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#3-documentation-standards)

Document all global variables with .txt files:

NAME
myStep - Does something useful

SYNOPSIS
myStep(config)

PARAMETERS
config (Map):
- param1 (String, required): Description
- param2 (Integer, optional, default: 10): Description

EXAMPLES
myStep(param1: 'value')


4. Keep Functions Small

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#4-keep-functions-small)

// ❌ Bad - doing too much
def deployApplication(config) {
buildApp()
runTests()
buildDockerImage()
deployToK8s()
}

// ✅ Good - focused steps
def buildAndTest(config) {
buildApp(config)
runTests(config)
}

def deployApp(config) {
buildDockerImage(config)
deployToK8s(config)
}


5. Use @NonCPS for Non-Serializable Code

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#5-use-noncps-for-non-serializable-code)

import groovy.transform.Field
import com.cloudbees.groovy.cps.NonCPS

@Field static final Map CONFIG = [:]

@NonCPS
def processData(List data) {
return data.collect { it * 2 }.sum()
}

def call(data) {
def result = processData(data)
echo "Result: ${result}"
}


6. Credential Management

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#6-credential-management)

def call(Map config) {
withCredentials([
usernamePassword(
credentialsId: config.credentialsId,
usernameVariable: 'USER',
passwordVariable: 'PASS'
)
]) {
// Never echo credentials
sh 'docker login -u $USER -p $PASS registry.company.com'
}
}


7. Code Quality with CodeNarc

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#7-code-quality-with-codenarc)

Fileconfig/codenarc/codenarcMain.groovy

ruleset {
description 'CodeNarc rules for Jenkins shared library'

ruleset('rulesets/basic.xml')
ruleset('rulesets/braces.xml')
ruleset('rulesets/naming.xml')

LineLength {
length = 120
}

MethodSize {
maxLines = 50
}
}


Enterprise Collaboration

Advanced Guide

Central Platform Team Model

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#central-platform-team-model)

In larger organizations, platform teams create common Jenkins libraries for all teams.

Benefits:

  • ✅ Standardization: Consistent deployment practices
  • ✅ Reduced duplication: No redundant pipeline code
  • ✅ Faster onboarding: New projects use battle-tested pipelines
  • ✅ Centralized improvements: Updates benefit all teams


Contribution Model

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#contribution-model)

Application teams contribute back to central libraries:

// Platform team: base functionality
// vars/deployToKubernetes.groovy
def call(Map config) {
// Standard Kubernetes deployment
}

// App team: specialized deployment
// vars/deployToOpenShift.groovy
def call(Map config) {
deployToKubernetes(config + [platform: 'openshift'])
}


Team-Specific Customization

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#team-specific-customization)

Teams can use central + custom libraries:

// Use central library
@Library('central-platform-library@v2.1.0') _
// Add team-specific library
@Library('team-payments-library@main') __

pipeline {
agent any
stages {
stage('Build') {
steps {
standardBuild(language: 'java') // Central
}
}
stage('Deploy') {
steps {
deployPaymentService(env: 'staging') // Team-specific
}
}
}
}


Unit Testing Importance

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#unit-testing-importance)

Unit testing shared libraries is critical:

  • Code Reliability: Catch bugs before they hit production
  • Safe Refactoring: Change code confidently
  • Prevent Widespread Issues: Bugs in shared libraries affect many pipelines

Investment Worth Making: While testing requires time, it's an investment in stability and maintainability of your entire CI/CD ecosystem.


Next Steps

[](https://github.com/Servana/jenkins-shared-library-tutorial/blob/main/docs/advanced-guide.md#next-steps)

Updated on: 02/11/2025

Was this article helpful?

Share your feedback

Cancel

Thank you!