Global Variables
Global Variables
Overview
Global variables are a powerful feature of Jenkins shared libraries that allow you to create reusable pipeline components accessible across all Jenkins pipelines. This lesson covers the implementation, best practices, and advanced patterns for global variables.
Global Variable Fundamentals
Basic Structure
// vars/globalConfig.groovy
class GlobalConfig implements Serializable {
private Map config
GlobalConfig() {
this.config = [
defaultBranch: 'main',
timeoutMinutes: 60,
credentialsId: 'jenkins-deploy-key',
environments: ['dev', 'staging', 'prod']
]
}
def getConfig() { return config }
def getEnvironments() { return config.environments }
def getTimeoutMinutes() { return config.timeoutMinutes }
}
def call() {
return new GlobalConfig()
}
Implementation Patterns
1. Environment Configuration
// vars/environmentConfig.groovy
def call(String environment) {
def configs = [
dev: [
url: 'https://dev-api.example.com',
namespace: 'development',
replicas: 1,
resources: [
requests: [cpu: '100m', memory: '256Mi'],
limits: [cpu: '200m', memory: '512Mi']
]
],
staging: [
url: 'https://staging-api.example.com',
namespace: 'staging',
replicas: 2,
resources: [
requests: [cpu: '200m', memory: '512Mi'],
limits: [cpu: '400m', memory: '1Gi']
]
],
prod: [
url: 'https://api.example.com',
namespace: 'production',
replicas: 3,
resources: [
requests: [cpu: '500m', memory: '1Gi'],
limits: [cpu: '1', memory: '2Gi']
]
]
]
return configs[environment] ?: error("Invalid environment: ${environment}")
}
2. Utility Functions
// vars/utils.groovy
def getGitCommit() {
return sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
}
def getGitBranch() {
return sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
}
def getTimestamp() {
return new Date().format('yyyyMMdd-HHmmss')
}
def getBuildTag() {
def commit = getGitCommit()[0..7]
def timestamp = getTimestamp()
return "${timestamp}-${commit}"
}
def validateEnvironment(String env) {
def validEnvs = globalConfig().environments
if (!(env in validEnvs)) {
error "Invalid environment '${env}'. Must be one of: ${validEnvs}"
}
}
3. Notification Helpers
// vars/notify.groovy
def call(Map config = [:]) {
def defaultConfig = [
channel: '#builds',
color: 'good',
message: null,
details: [:]
]
config = defaultConfig + config
if (!config.message) {
config.message = generateDefaultMessage()
}
sendNotification(config)
}
def success(String message) {
call(color: 'good', message: message)
}
def warning(String message) {
call(color: 'warning', message: message)
}
def error(String message) {
call(color: 'danger', message: message)
}
def generateDefaultMessage() {
def status = currentBuild.result ?: 'SUCCESS'
def duration = currentBuild.durationString
return """
Build ${env.JOB_NAME} #${env.BUILD_NUMBER}
Status: ${status}
Duration: ${duration}
URL: ${env.BUILD_URL}
""".stripIndent()
}
def sendNotification(Map config) {
// Implementation for different notification channels
if (config.channel.startsWith('#')) {
// Slack notification
slackSend channel: config.channel,
color: config.color,
message: config.message
} else if (config.channel.contains('@')) {
// Email notification
emailext body: config.message,
subject: "Build ${currentBuild.result}: ${env.JOB_NAME}",
to: config.channel
}
}
Advanced Patterns
1. Dynamic Configuration Loading
// vars/configLoader.groovy
def call(String configPath = 'pipeline-config.yaml') {
def config = readYaml file: configPath
// Validate required fields
validateConfig(config)
// Add computed fields
enrichConfig(config)
return config
}
def validateConfig(Map config) {
def requiredFields = ['app', 'version', 'environments']
requiredFields.each { field ->
if (!config.containsKey(field)) {
error "Missing required field: ${field}"
}
}
}
def enrichConfig(Map config) {
// Add build-time information
config.buildNumber = env.BUILD_NUMBER
config.buildUrl = env.BUILD_URL
config.gitCommit = utils.getGitCommit()
config.buildTag = utils.getBuildTag()
// Add environment-specific configurations
config.environments.each { env ->
def envConfig = environmentConfig(env)
config.environments[env] = envConfig
}
}
2. Pipeline Templates
// vars/standardPipeline.groovy
def call(Map config) {
pipeline {
agent any
options {
timeout(time: globalConfig().timeoutMinutes, unit: 'MINUTES')
timestamps()
buildDiscarder(logRotator(numToKeepStr: '10'))
}
environment {
APP_NAME = config.appName
VERSION = config.version
BUILD_TAG = utils.getBuildTag()
}
stages {
stage('Validate') {
steps {
script {
validatePipelineConfig(config)
}
}
}
stage('Build') {
steps {
script {
buildApplication(config)
}
}
}
stage('Test') {
parallel {
stage('Unit Tests') {
steps {
runTests('unit')
}
}
stage('Integration Tests') {
steps {
runTests('integration')
}
}
}
}
stage('Deploy') {
steps {
script {
deployApplication(config)
}
}
}
}
post {
success {
notify.success("Pipeline completed successfully")
}
failure {
notify.error("Pipeline failed")
}
}
}
}
Best Practices
- Encapsulation
// Good: Encapsulated configuration def getConfig() { return config.clone() } // Bad: Exposed internal state def config = [:]
- Documentation
```groovy
/**
- Loads and validates pipeline configuration *
- @param configPath Path to the YAML configuration file
- @return Map of validated and enriched configuration
- @throws Exception if configuration is invalid */ def call(String configPath) { // Implementation } ```
- Error Handling
def validateConfig(Map config) { try { // Validation logic } catch (Exception e) { error "Configuration validation failed: ${e.message}" } }
Hands-on Exercise
Exercise 1: Configuration Management
- Create a global configuration system
- Implement environment-specific settings
- Add validation logic
- Create helper methods
- Write tests
Exercise 2: Pipeline Templates
- Design a reusable pipeline template
- Add configuration options
- Implement notification system
- Add parallel execution support
- Create documentation
Additional Resources
- Jenkins Shared Libraries Documentation
- Groovy Documentation
- Pipeline Steps Reference
- Jenkins Configuration as Code
Next Steps
- Learn about library management
- Explore advanced pipeline patterns
- Practice with real-world scenarios