Jenkins Pipeline Cookbook

Jenkins Pipeline Environment Variables - The Definitive Guide

Have you run into troubles when you started using Jenkins Environment Variables in your Jenkinsfile? In this blog post, I show you how to use environment variables, how to override them, how to work with boolean values, and how to store a result of sh step in the env variable. After reading this article, Jenkins env variables won’t surprise you anymore!

List environment variables

Let’s start by listing all available environment variables. Two different ways allow you to do so.

Using env-vars.html

You can open ${YOUR_JENKINS_HOST}/env-vars.html page on your Jenkins master server to get a list of all environment variables listed on an HTML page.

What is Jenkins Environment Variable?

Jenkins Environment Variable is a global variable exposed through the env variable and used anywhere in the Jenkinsfile. Any value stored in the env variable gets stored as a String type. Environment Variables can be set either at the pipeline top level, at the specific stage level, or inside the script block.

Using shell command

Alternatively, you can list all environment variables by executing the printenv shell command.

Listing 1. Jenkinsfile
pipeline {
    agent any

    stages {
        stage("Env Variables") {
            steps {
                sh "printenv"
            }
        }
    }
}
It might be useful to use printenv | sort command combination to get a sorted list of env variables.

Reading environment variables

You can access environment variables in pipeline steps through the env object, e.g., env.BUILD_NUMBER will return the current build number. You can also use a shorthand version BUILD_NUMBER, but in this variant may be confusing to some users - it misses the context that the BUILD_NUMBER comes from the environment variable.

Listing 2. Jenkinsfile
pipeline {
    agent any

    stages {
        stage("Env Variables") {
            steps {
                echo "The build number is ${env.BUILD_NUMBER}"
                echo "You can also use \${BUILD_NUMBER} -> ${BUILD_NUMBER}"
                sh 'echo "I can access $BUILD_NUMBER in shell command as well."'
            }
        }
    }
}

Setting environment variables

The environment variables can be set declaratively using environment { } block, imperatively using env.VARIABLE_NAME, or using withEnv(["VARIABLE_NAME=value"]) {} block.

Listing 3. Jenkinsfile
pipeline {
    agent any

    environment {
        FOO = "bar"
    }

    stages {
        stage("Env Variables") {
            environment {
                NAME = "Alan"
            }

            steps {
                echo "FOO = ${env.FOO}"
                echo "NAME = ${env.NAME}"

                script {
                    env.TEST_VARIABLE = "some test value"
                }

                echo "TEST_VARIABLE = ${env.TEST_VARIABLE}"

                withEnv(["ANOTHER_ENV_VAR=here is some value"]) {
                    echo "ANOTHER_ENV_VAR = ${env.ANOTHER_ENV_VAR}"
                }
            }
        }
    }
}

Overriding environment variables

Jenkins Pipeline supports overriding environment variables. There are a few rules you need to be aware of.

  • The withEnv(["env=value]) { } block can override any environment variable.

  • The variables set using environment {} block cannot be overridden using imperative env.VAR = "value" assignment.

  • The imperative env.VAR = "value" assignment can override only environment variables created using imperative assignment.

Here is an exemplary Jenkinsfile that shows all three different use cases.

Listing 4. Jenkinsfile
pipeline {
    agent any

    environment {
        FOO = "bar"
        NAME = "Joe"
    }

    stages {
        stage("Env Variables") {
            environment {
                NAME = "Alan" // overrides pipeline level NAME env variable
                BUILD_NUMBER = "2" // overrides the default BUILD_NUMBER
            }

            steps {
                echo "FOO = ${env.FOO}" // prints "FOO = bar"
                echo "NAME = ${env.NAME}" // prints "NAME = Alan"
                echo "BUILD_NUMBER =  ${env.BUILD_NUMBER}" // prints "BUILD_NUMBER = 2"

                script {
                    env.SOMETHING = "1" // creates env.SOMETHING variable
                }
            }
        }

        stage("Override Variables") {
            steps {
                script {
                    env.FOO = "IT DOES NOT WORK!" // it can't override env.FOO declared at the pipeline (or stage) level
                    env.SOMETHING = "2" // it can override env variable created imperatively
                }

                echo "FOO = ${env.FOO}" // prints "FOO = bar"
                echo "SOMETHING = ${env.SOMETHING}" // prints "SOMETHING = 2"

                withEnv(["FOO=foobar"]) { // it can override any env variable
                    echo "FOO = ${env.FOO}" // prints "FOO = foobar"
                }

                withEnv(["BUILD_NUMBER=1"]) {
                    echo "BUILD_NUMBER = ${env.BUILD_NUMBER}" // prints "BUILD_NUMBER = 1"
                }
            }
        }
    }
}

5 Common Jenkins Pipeline Mistakes πŸ”₯
  • YouTube
  • 5k views
  • 2.5k subscribers

In this Jenkins Pipeline tutorial video, I reveal five common Jenkins Pipeline mistakes and I explain how those mistakes can be avoided. If you're new to the Jenkins declarative pipeline and you want to take your knowledge to the next level, this video will show you some best practices and resources for further learning. Watch now »

Storing Boolean values in environment variables

There is one popular misconception when it comes to using environment variables. Every value that gets stored as an environment variable gets converted to a String. When you store boolean’s false value, it gets converted to "false". If you want to use that value in the boolean expression correctly, you need to call "false".toBoolean() method.[1]

Listing 5. Jenkinsfile
pipeline {
    agent any

    environment {
        IS_BOOLEAN = false
    }

    stages {
        stage("Env Variables") {
            steps {
                script {
                    if (env.IS_BOOLEAN) {
                        echo "You can see this message, because \"false\" String evaluates to Boolean.TRUE value"
                    }

                    if (env.IS_BOOLEAN.toBoolean() == false) {
                        echo "You can see this message, because \"false\".toBoolean() returns Boolean.FALSE value"
                    }
                }
            }
        }
    }
}

Capturing sh command output in the env variable

You can also capture output of a shell command as an environment variable. Keep in mind that you need to use sh(script: 'cmd', returnStdout:true) format to force sh step[2] to return an output so it can be captured and stored in a variable. Also, if you want to avoid capturing the new line character that is usually present in the shell command output, call trim() method to remove all whitespace from the beginning and the end of the captured output.

Listing 6. Jenkinsile
pipeline {
    agent any

    environment {
        LS = "${sh(script:'ls -lah', returnStdout: true).trim()}"
    }

    stages {
        stage("Env Variables") {
            steps {
                echo "LS = ${env.LS}"
            }
        }
    }
}

Wrapping sh step with the Groovy string is only needed when you capture command’s output in the environment block of the declarative pipeline. If you don’t do it that way, the pipeline syntax validation fails instantly, saying that it expects string value on the right side of the assignment. When you capture the output inside the script block, however, you don’t have to call sh from the inside of the Groovy string. The following code will work just fine in this case.

Listing 7. Jenkinsfile
pipeline {
    agent any

    stages {
        stage("Env Variables") {
            steps {
                script {
                    env.LS = sh(script:'ls -lah', returnStdout: true).trim()
                    echo "LS = ${env.LS}"
                    // or if you access env variable in the shell command
                    sh 'echo $LS'
                }
            }
        }
    }
}

Did you like this article?

Consider buying me a coffee

0 Comments