Mastering Jenkins Environment Variables: A Comprehensive Guide
In modern CI/CD pipelines, automation must be dynamic. Hardcoding values like server URLs, database credentials, or build numbers directly into your deployment scripts makes your pipelines fragile and difficult to maintain. To solve this, Jenkins provides Environment Variables.
Environment variables act as global key-value pairs that store configuration data, build metadata, and system information. They are accessible throughout your Jenkins jobs, pipelines, and shell scripts, enabling you to build highly reusable and flexible automation workflows.
Understanding Jenkins Environment Variables
Jenkins environment variables can be broadly categorized into three types:
- Built-in Variables: Automatically provided by Jenkins for every build (e.g., build number, job name, workspace path).
- Custom Global Variables: Defined by Jenkins administrators and accessible across all jobs on the controller.
- Pipeline-Local Variables: Defined within a specific Jenkinsfile or pipeline script, scoped to that specific run or stage.
+-------------------------------------------------------------+
| Jenkins Controller |
| +-------------------------------------------------------+ |
| | Global Environment Variables | |
| | (Accessible to all pipelines) | |
| +-------------------------------------------------------+ |
| | |
| v |
| +-------------------------------------------------------+ |
| | Pipeline Execution | |
| | +-------------------------------------------------+ | |
| | | Pipeline-Local Variables | | |
| | +-------------------------------------------------+ | |
| | +-------------------------------------------------+ | |
| | | Built-in Variables (metadata) | | |
| | +-------------------------------------------------+ | |
| +-------------------------------------------------------+ |
+-------------------------------------------------------------+
Common Built-in Environment Variables
Jenkins exposes a set of default environment variables that capture metadata about the running build. Here are some of the most frequently used built-in variables:
BUILD_NUMBER: The current build number (e.g., "42").BUILD_ID: The unique ID of the current build, usually identical to the build number in newer Jenkins versions.JOB_NAME: The name of the project or pipeline (e.g., "production-deployment").WORKSPACE: The absolute path of the directory allocated for the build workspace.GIT_BRANCH: The name of the Git branch being processed (available when using Git integration).GIT_COMMIT: The SHA-1 hash of the Git commit being built.JENKINS_URL: The URL of the Jenkins controller (e.g., "http://localhost:8080/").
How to Access Environment Variables
Depending on whether you are writing a Declarative Pipeline, Scripted Pipeline, or executing a shell script, the syntax for accessing environment variables differs slightly.
1. Accessing in Declarative Pipelines
In Jenkins Declarative Pipelines, you access environment variables using the env prefix. You can reference them directly or interpolate them inside double-quoted strings.
pipeline {
agent any
stages {
stage('Print Metadata') {
steps {
// Direct reference
echo "Running Job: ${env.JOB_NAME}"
echo "Build Number: ${env.BUILD_NUMBER}"
// Shorthand reference (works in most steps)
echo "Workspace Path: ${WORKSPACE}"
}
}
}
}
2. Accessing in Shell Scripts (Linux/macOS)
When running shell commands inside a sh step, Jenkins environment variables are injected directly into the shell session. You can access them using standard shell syntax.
pipeline {
agent any
stages {
stage('Shell Execution') {
steps {
sh 'echo "The current build is $BUILD_NUMBER"'
sh 'echo "Working directory is $WORKSPACE"'
}
}
}
}
3. Accessing in Batch Scripts (Windows)
If your build agent runs on Windows, use the standard Windows Command Prompt syntax to read environment variables inside a bat step.
pipeline {
agent { label 'windows-agent' }
stages {
stage('Windows Execution') {
steps {
bat 'echo The current build is %BUILD_NUMBER%'
}
}
}
}
Defining Custom Environment Variables
You can define your own custom environment variables to store configuration values like target environments, API endpoints, or tool versions.
1. Pipeline-Level Variables
Use the environment directive at the top level of your Declarative Pipeline to make variables accessible to all stages.
pipeline {
agent any
environment {
DEPLOY_ENV = 'staging'
APP_PORT = '8080'
}
stages {
stage('Deploy') {
steps {
echo "Deploying to ${env.DEPLOY_ENV} on port ${env.APP_PORT}"
}
}
}
}
2. Stage-Level Variables
If a variable is only needed for a specific stage, declare the environment block within that stage. This limits its scope and prevents other stages from accessing or modifying it.
pipeline {
agent any
stages {
stage('Build') {
environment {
COMPILER_OPTIMIZATION = 'O3'
}
steps {
echo "Compiling with optimization level: ${env.COMPILER_OPTIMIZATION}"
}
}
stage('Test') {
steps {
// COMPILER_OPTIMIZATION is not accessible here
echo "Running unit tests..."
}
}
}
}
3. Dynamic Variable Assignment
Sometimes you need to set an environment variable based on the output of a shell command. You can achieve this using the returnStdout parameter.
pipeline {
agent any
environment {
// Dynamically fetch the current system date
CURRENT_DATE = sh(script: 'date +%Y-%m-%d', returnStdout: true).trim()
}
stages {
stage('Log Date') {
steps {
echo "Build executed on date: ${env.CURRENT_DATE}"
}
}
}
}
Handling Credentials Safely
Never hardcode API keys, passwords, or SSH tokens as plain text environment variables. Jenkins provides a secure credentials store. You can inject these credentials safely into your environment using the credentials() helper helper.
pipeline {
agent any
environment {
// Safe injection of credentials
DATABASE_PASSWORD = credentials('db-prod-password')
}
stages {
stage('Database Migration') {
steps {
// Jenkins will automatically mask the password in console logs
sh 'run-migration.sh --password $DATABASE_PASSWORD'
}
}
}
}
Common Mistakes and How to Avoid Them
-
Mistake 1: Using Single Quotes for Groovy Interpolation
In Groovy (the language behind Jenkinsfiles), single-quoted strings (
'string') are literal and do not support variable interpolation. Double-quoted strings ("string") are required to resolve variables.Incorrect:
echo 'Building branch: ${env.GIT_BRANCH}'(Prints literal text)Correct:
echo "Building branch: ${env.GIT_BRANCH}"(Prints actual branch name) -
Mistake 2: Forgetting to Trim Dynamic Outputs
When capturing shell output using
returnStdout, the output often contains a trailing newline character (\n). This can break downstream commands or string comparisons. Always append.trim()to clean the output. -
Mistake 3: Overwriting Read-Only Built-in Variables
Do not attempt to manually assign values to read-only built-in variables like
BUILD_NUMBERorWORKSPACE. Doing so can cause unpredictable behavior or pipeline failures.
Real-World Use Cases
Use Case 1: Tagging Docker Images Dynamically
During a build pipeline, you want to build a Docker image and tag it with the unique Jenkins build number, then push it to a registry.
pipeline {
agent any
environment {
REGISTRY_URL = 'myregistry.azurecr.io'
IMAGE_NAME = 'payment-service'
}
stages {
stage('Docker Build & Tag') {
steps {
sh "docker build -t ${env.REGISTRY_URL}/${env.IMAGE_NAME}:${env.BUILD_NUMBER} ."
}
}
}
}
Use Case 2: Conditional Execution Based on Branch Name
You may want to run deployment steps only when code is merged into the main branch.
pipeline {
agent any
stages {
stage('Deploy to Production') {
when {
environment name: 'BRANCH_NAME', value: 'main'
}
steps {
echo "Deploying production release..."
}
}
}
}
Interview Preparation Notes
- How do you access the list of all available environment variables in Jenkins? You can navigate to
${JENKINS_URL}/env-vars.htmlon your running Jenkins controller instance to view a comprehensive list of all default variables available to your jobs. - What is the difference between env.VAR and local variables in a Jenkinsfile? Variables declared inside the
environment {}block or accessed viaenv.VARare automatically injected into the environment of any child processes (like shell commands or batch scripts). Local Groovy variables declared withdef varName = valueare only accessible within the Groovy script execution context and are not passed down to shell steps unless explicitly injected. - How does Jenkins handle sensitive data in environment variables? When credentials are bound to environment variables, Jenkins intercepts console output and replaces sensitive values with asterisks (
****) to prevent accidental exposure in build logs.
Summary
Jenkins environment variables are indispensable tools for creating dynamic, secure, and reusable pipelines. By leveraging built-in metadata, defining custom variables at the appropriate scope, handling credentials securely, and avoiding common syntax pitfalls, you can build clean and robust CI/CD workflows that scale with your infrastructure.