ScreenshotNeo

BlogHow-to

How to Set Environment Variables in a Jenkins Pipeline

Set Jenkins Pipeline variables with Declarative `environment` blocks or Scripted `withEnv`. Learn scope, credentials, parameters, shell syntax, and fixes for common errors.

By the ScreenshotNeo team4 October 20267 min read

In a Declarative Jenkins Pipeline, set environment variables with an environment block. Put it directly inside pipeline for Pipeline-wide values, or inside a stage for values limited to that stage. In a Scripted Pipeline, wrap the relevant steps in withEnv(['NAME=value']). Read values in Pipeline Groovy as env.NAME; inside a shell step, use that shell’s normal variable expansion.

1. Choose the syntax and scope

Need Use Scope
Value in a Declarative Pipeline environment { NAME = 'value' } Whole Pipeline or one stage, depending on placement
Value around selected Scripted steps withEnv(['NAME=value']) { ... } Steps inside the wrapper
Value supplied when the build starts Pipeline parameter Build; available through params and as an environment variable
Secret value Configured Jenkins credential Use a credential binding with the narrowest suitable scope

Use environment variables for configuration passed to steps or external processes. Keep the value’s source in mind: a fixed setting belongs in the Pipeline definition, a per-build choice is a parameter, and a secret should come from Jenkins credentials.

2. Set a Pipeline-wide variable in Declarative Pipeline

Place environment directly under pipeline to make the value available throughout the Pipeline.

pipeline {
    agent any
    environment {
        BUILD_MODE = 'release'
    }
    stages {
        stage('Build') {
            steps {
                echo "Mode: ${env.BUILD_MODE}"
                sh 'make BUILD_MODE="$BUILD_MODE"'
            }
        }
    }
}

The echo step uses Groovy interpolation to read env.BUILD_MODE. The single-quoted sh argument passes a literal command to the shell, which expands $BUILD_MODE from its environment. The example assumes a POSIX shell on the agent and a make target that accepts this variable.

3. Limit a variable to one stage

Put the block inside the stage when other stages should not receive the setting.

pipeline {
    agent any
    stages {
        stage('Test') {
            environment {
                TEST_FLAGS = '--verbose'
            }
            steps {
                sh 'make test TEST_FLAGS="$TEST_FLAGS"'
            }
        }
        stage('Package') {
            steps {
                sh 'make package'
            }
        }
    }
}

TEST_FLAGS is configured for the Test stage. Keep the declaration close to the steps that need it so the intended scope is clear.

4. Set a variable in Scripted Pipeline

Use withEnv around the steps that need a temporary environment value.

node {
    withEnv(['BUILD_MODE=release']) {
        echo "Mode: ${env.BUILD_MODE}"
        sh 'make BUILD_MODE="$BUILD_MODE"'
    }
}

Each entry is a string in NAME=value form. The value is available to steps and external processes started within the wrapper. Outside it, the wrapper’s setting no longer applies.

Temporarily unset a variable

Give a variable an empty value in withEnv to unset it for the wrapped steps:

node {
    withEnv(['OPTIONAL_SETTING=']) {
        sh 'run-tool'
    }
}

This sets the variable to an empty value in the wrapper’s environment. Check how the program distinguishes an empty value from a variable that is absent if that difference matters.

Prepend a directory to PATH

Use the special PATH+LABEL form to prepend a directory while retaining the existing PATH:

node {
    withEnv(['PATH+TOOLS=/opt/build-tools/bin']) {
        sh 'tool --version'
    }
}

Choose a directory that exists on the agent running the step. The example uses a Unix-style path; use a path and shell appropriate to your agent.

5. Read variables in Groovy and shell steps

  • Pipeline Groovy: read a variable with env.NAME, as in echo env.BUILD_MODE.
  • POSIX shell: use $NAME or ${NAME}. Quote expansions when values may contain spaces, such as "$NAME".
  • PowerShell: use PowerShell’s environment-variable syntax, for example $env:NAME.
  • Windows cmd.exe: use its syntax, such as %NAME%.

Jenkins supplies environment variables to the process launched by a step. The shell syntax is determined by the shell actually running on the agent, not by the Groovy syntax used in the Jenkinsfile.

6. Use parameters for build-time choices

Pipeline parameters are exported as environment variables when a build starts. In Pipeline Groovy, use the read-only params map to access parameter values.

pipeline {
    agent any
    parameters {
        string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: 'Deployment target')
    }
    stages {
        stage('Show target') {
            steps {
                echo "Target from params: ${params.DEPLOY_ENV}"
                sh 'printf "Target from environment: %s\\n" "$DEPLOY_ENV"'
            }
        }
    }
}

Use a parameter when the person starting a build should choose a non-secret input. Validate inputs before using them in commands, file paths, or deployment decisions.

7. Bind credentials for secrets

Do not put passwords, tokens, or other secrets directly in a Jenkinsfile. For supported credential types, Declarative Pipeline can bind a configured credential by ID through credentials('credential-id') in an environment block. Jenkins also provides withCredentials for credential bindings and scoped access.

pipeline {
    agent any
    environment {
        API_TOKEN = credentials('api-token')
    }
    stages {
        stage('Call service') {
            steps {
                // Keep the command literal so the shell expands the secret.
                sh 'curl -H "Authorization: Bearer $API_TOKEN" https://service.example/api'
            }
        }
    }
}

Replace the example credential ID and service URL with values configured for your Jenkins instance. The exact variables exposed depend on credential type. For a username/password binding, Jenkins can expose the combined value and variables ending in _USR and _PSW.

Secret masking can reduce accidental disclosure in logs, but it does not prevent a Pipeline from revealing a credential. Do not allow untrusted Pipeline jobs to use trusted credentials. Avoid Groovy-interpolated shell strings such as sh "curl -H 'Authorization: Bearer ${env.API_TOKEN}' ...": interpolation can place secret material in process arguments. Pass a literal command string and let the shell read the variable from its environment. Jenkins documents the risk plainly: “A Pipeline that uses credentials can also disclose those credentials.”

8. Troubleshoot common problems

Symptom Likely cause Fix
Variable is empty or missing in a step The declaration is outside the step’s scope, misspelled, or set in a different stage or wrapper. Check the variable name and move the Declarative block to the Pipeline or stage scope that needs it; for Scripted code, include the step inside withEnv.
Groovy prints null or the wrong value The code reads a different name, or expects an environment variable that was never defined. Check spelling and scope; read Pipeline environment values with env.NAME. For parameters, inspect params.NAME.
Shell reports “command not found” or treats a value as literal text The command uses syntax for another shell, or quoting prevented the intended shell expansion. Confirm which shell the agent runs, use its variable syntax, and quote expansions in a way that preserves the intended arguments.
Value works in Groovy but not in an external command The command is not running inside the environment scope, or the code assumes Groovy interpolation inside a single-quoted shell command. Keep the shell step within the declaration or withEnv scope. Use env.NAME in Groovy and $NAME in a POSIX shell.
Secret appears in logs or process details It may have been interpolated by Groovy, printed, or exposed by the Pipeline. Use Jenkins credentials, avoid Groovy interpolation for shell commands that use secrets, remove diagnostic output of secret values, and restrict who can run the job.
PATH loses existing entries A plain assignment replaced the prior path. Use withEnv(['PATH+TOOLS=/directory']) when you need to prepend a directory within a Scripted wrapper.

9. Reliability and maintenance

  • Keep each variable’s scope as narrow as its use allows; this makes stage behavior easier to understand.
  • Use parameters for intentional build-time input, and credentials for secrets. Avoid duplicating secret values in Jenkinsfiles or build arguments.
  • Use stable, descriptive names and document non-obvious values near their declaration.
  • Test assumptions about empty values, spaces, and special characters with the actual shell and command used by your agent.
  • Do not print secrets while debugging. Check variable presence or a non-sensitive property instead.

10. Performance and cost

Setting an environment variable is configuration passed to Pipeline steps; it does not itself require an additional build stage or external service. Performance and cost depend on the work your steps launch, such as builds, tests, deployments, or API calls. Keep values small, avoid placing large payloads in environment variables, and use the storage mechanism intended for larger files or secret material.

11. FAQ

Can I use an environment variable in a Jenkinsfile condition?

Pipeline Groovy can read it through env.NAME. For build parameters, use params.NAME. Ensure the value is available at the point where the condition is evaluated.

Does a stage-level variable apply to later stages?

Declare it at the scope where it is needed. A stage-level environment block is for that stage; use a top-level block for Pipeline-wide configuration.

Can I change an environment value for just one command?

In Scripted Pipeline, put that command inside a withEnv wrapper. The wrapper also supports an empty assignment to set a variable to an empty value for its duration.

Or skip the browser setup

If a Jenkins job needs a website screenshot, you can call ScreenshotNeo, a website screenshot API and MCP server for developers, with one GET request. See the API documentation for request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers say which page verdict applied and whether it was billed.
  • An MCP server gives AI agents, including Claude and Cursor, the tools take_screenshot, get_page_info, and capture_pdf.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000. Every feature is on every plan.

Sign up free for 1,000 screenshots a month, with no card required.