I need to pass environment variables to my executable and my unit tests. This works locally but not on Jenkins. On Jenkins, my environment variable gets reset in between gradle tasks
task setupEnv(type: Exec) {
commandLine 'export', "ABC=def"
}
test {
dependsOn 'setupEnv'
scanForTestClasses = false
include '**/*Test.*'
}
Note: I'm simplifying here for SO (I'm aware of the environment command in Gradle) but even with this simple example it works locally but not on Jenkins, meaning *Test.java files see nothing for System.getEnv("ABC"). I'm looking at how to not have Jenkins reset environment variables
There are two options to set dynamical env in pipeline. As a result these envs will be available globally (to all stages in the pipeline):
set it in a stage
stage('set date') {
steps {
script {
env.ANY_NAME_OF_THE_SCRIPT=sh(returnStdout: true, script: "date +%Y-%m-%d").trim()
}
}
}
set it in environment
pipeline {
agent {
label 'some_label'
}
environment {
HELLO = """${sh(
returnStdout: true,
script: 'echo hello'
).trim()}"""
}
}
Hello Trying to update jenkins Env variables from Powershell script written in stage
pipeline {
agent { label 'master' }
environment {
def var1 = "default_value"
def var2 = "default var 2"
}
stages {
stage ('step-1') {
steps {
script {
powershell (returnStdout: true, script: '''
${env:var1} = "changed from powershell"
${env:var2} = "var2 changed from powershell"
''').trim()
}
}
}
stage ("step-2"){
steps {
echo var1
echo var2
}
}
}
}
I can access values but cannot change the same, Does Scope is limited to Powershell only?
By design, a subshell cannot modify the environment of its parent shell. Every powershell, sh, or bat step called within a Jenkinsfile spawns a new subshell to run the child processes. Therefore, any environment variable declared inside these steps are lost as soon as the child processes end and are not available to the pipeline Groovy script.
One way to do this currently in a Jenkinsfile is to assign the stdout of your subshell to a variable in the Groovy script itself.
script {
env.var1 = powershell(returnStdout: true, script: '<single command>').trim()
}
Evidently, this approach has serious limitations as you can run only one command at a time and that too, only if it would return an appropriate output to be used as a variable.
Another way is to write the values to a file and then read these values using Groovy script to set the environment variables downstream in your pipeline.
Edit
Based on your comment, if your stdout returns two distinct values as a string, you can try parsing them into separate values. For example:
script {
def output = powershell(returnStdout: true, script: '''
<command1>
<command2>
''')
println(output)
/*Prints:
value1
value2
*/
env.var1 = output.tokenize('\n')[0].trim() \\value1
env.var2 = output.tokenize('\n')[1].trim() \\value2
}
Given a jenkins build pipeline, jenkins injects a variable env into the node{}. Variable env holds environment variables and values.
I want to print all env properties within the jenkins pipeline. However, I do no not know all env properties ahead of time.
For example, environment variable BRANCH_NAME can be printed with code
node {
echo ${env.BRANCH_NAME}
...
But again, I don't know all variables ahead of time. I want code that handles that, something like
node {
for(e in env){
echo e + " is " + ${e}
}
...
which would echo something like
BRANCH_NAME is myBranch2
CHANGE_ID is 44
...
I used Jenkins 2.1 for this example.
According to Jenkins documentation for declarative pipeline:
sh 'printenv'
For Jenkins scripted pipeline:
echo sh(script: 'env|sort', returnStdout: true)
The above also sorts your env vars for convenience.
Another, more concise way:
node {
echo sh(returnStdout: true, script: 'env')
// ...
}
cf. https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#code-sh-code-shell-script
The following works:
#NonCPS
def printParams() {
env.getEnvironment().each { name, value -> println "Name: $name -> Value $value" }
}
printParams()
Note that it will most probably fail on first execution and require you approve various groovy methods to run in jenkins sandbox. This is done in "manage jenkins/in-process script approval"
The list I got included:
BUILD_DISPLAY_NAME
BUILD_ID
BUILD_NUMBER
BUILD_TAG
BUILD_URL
CLASSPATH
HUDSON_HOME
HUDSON_SERVER_COOKIE
HUDSON_URL
JENKINS_HOME
JENKINS_SERVER_COOKIE
JENKINS_URL
JOB_BASE_NAME
JOB_NAME
JOB_URL
You can accomplish the result using sh/bat step and readFile:
node {
sh 'env > env.txt'
readFile('env.txt').split("\r?\n").each {
println it
}
}
Unfortunately env.getEnvironment() returns very limited map of environment variables.
Why all this complicatedness?
sh 'env'
does what you need (under *nix)
Cross-platform way of listing all environment variables:
if (isUnix()) {
sh env
}
else {
bat set
}
Here's a quick script you can add as a pipeline job to list all environment variables:
node {
echo(env.getEnvironment().collect({environmentVariable -> "${environmentVariable.key} = ${environmentVariable.value}"}).join("\n"))
echo(System.getenv().collect({environmentVariable -> "${environmentVariable.key} = ${environmentVariable.value}"}).join("\n"))
}
This will list both system and Jenkins variables.
I use Blue Ocean plugin and did not like each environment entry getting its own block. I want one block with all the lines.
Prints poorly:
sh 'echo `env`'
Prints poorly:
sh 'env > env.txt'
for (String i : readFile('env.txt').split("\r?\n")) {
println i
}
Prints well:
sh 'env > env.txt'
sh 'cat env.txt'
Prints well: (as mentioned by #mjfroehlich)
echo sh(script: 'env', returnStdout: true)
The pure Groovy solutions that read the global env variable don't print all environment variables (e. g. they are missing variables from the environment block, from withEnv context and most of the machine-specific variables from the OS). Using shell steps it is possible to get a more complete set, but that requires a node context, which is not always wanted.
Here is a solution that uses the getContext step to retrieve and print the complete set of environment variables, including pipeline parameters, for the current context.
Caveat: Doesn't work in Groovy sandbox. You can use it from a trusted shared library though.
def envAll = getContext( hudson.EnvVars )
echo envAll.collect{ k, v -> "$k = $v" }.join('\n')
Show all variable in Windows system and Unix system is different, you can define a function to call it every time.
def showSystemVariables(){
if(isUnix()){
sh 'env'
} else {
bat 'set'
}
}
I will call this function first to show all variables in all pipline script
stage('1. Show all variables'){
steps {
script{
showSystemVariables()
}
}
}
The easiest and quickest way is to use following url to print all environment variables
http://localhost:8080/env-vars.html/
The answers above, are now antiquated due to new pipeline syntax. Below prints out the environment variables.
script {
sh 'env > env.txt'
String[] envs = readFile('env.txt').split("\r?\n")
for(String vars: envs){
println(vars)
}
}
Includes both system and build environment vars:
sh script: "printenv", label: 'print environment variables'
if you really want to loop over the env list just do:
def envs = sh(returnStdout: true, script: 'env').split('\n')
envs.each { name ->
println "Name: $name"
}
I found this is the most easiest way:
pipeline {
agent {
node {
label 'master'
}
}
stages {
stage('hello world') {
steps {
sh 'env'
}
}
}
}
You can get all variables from your jenkins instance. Just visit:
${jenkins_host}/env-vars.html
${jenkins_host}/pipeline-syntax/globals
ref: https://www.jenkins.io/doc/pipeline/tour/environment/
node {
sh 'printenv'
}
You can use sh 'printenv'
stage('1') {
sh "printenv"
}
another way to get exactly the output mentioned in the question:
envtext= "printenv".execute().text
envtext.split('\n').each
{ envvar=it.split("=")
println envvar[0]+" is "+envvar[1]
}
This can easily be extended to build a map with a subset of env vars matching a criteria:
envdict=[:]
envtext= "printenv".execute().text
envtext.split('\n').each
{ envvar=it.split("=")
if (envvar[0].startsWith("GERRIT_"))
envdict.put(envvar[0],envvar[1])
}
envdict.each{println it.key+" is "+it.value}
I suppose that you needed that in form of a script, but if someone else just want to have a look through the Jenkins GUI, that list can be found by selecting the "Environment Variables" section in contextual left menu of every build
Select project => Select build => Environment Variables
How do I invoke Global environment variables in Jenkinsfile?
For example, if I have a variable -
name:credentialsId
value:xxxx-xxxx-xxxxx-xxxxxxxxx
How do I use it in the groovy script?
I tried ${credentialsId}, but it didn't work. It will just give error:
java.lang.NoSuchMethodError: No such DSL method '$' found among steps [ArtifactoryGradleBuild, ........
In a Jenkinsfile, you have the "Working with the Environment" which mentions:
The full list of environment variables accessible from within Jenkins Pipeline is documented at localhost:8080/pipeline-syntax/globals#env,
The syntax is ${env.xxx} as in:
node {
echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}"
}
See also "Managing the Environment".
How can I pass the Global variables to the Jenkinsfile?
When I say Global variables - I mean in
Jenkins -> Manage Jenkins -> Configure System -> Global properties -> Environment variables
See "Setting environment variables"
Setting an environment variable within a Jenkins Pipeline can be done with the withEnv step, which allows overriding specified environment variables for a given block of Pipeline Script, for example:
Jenkinsfile (Pipeline Script)
node {
/* .. snip .. */
withEnv(["NAME=value"]) {
... your job
}
}
When referring to env in Groovy scope, simply use env.VARIABLE_NAME, for example to pass on BUILD_NUMBER of upstream job to a triggered job:
stage ('Starting job') {
build job: 'TriggerTest', parameters: [
[$class: 'StringParameterValue', name: 'upstream_build_number', value: env.BUILD_NUMBER]
]
}
Scripted pipeline
To read an environment variable whose name you know, use env.NAME
To read an environment variable whose name is not known until runtime use env.getProperty(name).
For example, a value from a YAML config file represents an environment variable name:
config.yaml (in workspace)
myconfig:
key: JOB_DISPLAY_URL
Jenkinsfile
node {
println("Running job ${env.JOB_NAME}")
def config = readYaml(file:'config.yaml')
def value = env.getProperty(config.myconfig.key)
println("Value of property ${config.myconfig.key} is ${value}")
}
For getting values all env.VAR, env['VAR'], env.getProperty('VAR') are fine.
For setting values the only safe way at the moment is withEnv. If you try to assign values to env.VAR it may not work in some cases like for parallel pipelines (like in JENKINS-59871).
Another syntax is $ENV:xxxx
node {
echo "Running $ENV.BUILD_ID on $ENV.JENKINS_URL" }
This worked for me
I would like to use EnvInject plugin within my pipeline job. So, I have a possibility to set checkbox "Prepare an environment for the run", but there is no action "Inject environment variables", like in freestyle job.
I declared my variables in "Properties Content" block:
How to inject environment variables in pipeline job using EnvInject?
If you declared following variables in "Properties Content" block:
param1=value1
param2=value2
Then you can get them into pipeline here so:
//do something
def par1 = env.param1
def par2 = env.param2
Pipeline doesn't support it now, please refer to below ticket, and there are some good and alternative ways:
https://issues.jenkins-ci.org/browse/JENKINS-42614
The Environment Injector plugin is of limited use in Jenkins pipelines. I suggest using the built-in 'environment' Jenkins pipeline feature instead. Here a complete declarative Jenkins pipeline script example:
pipeline {
agent any
// Inject environment variable for whole pipeline script
environment {
param1 = 'value1'
}
stages {
stage('Some stage in my pipeline') {
// Inject environment variable only for this step
environment {
param2 = 'value2'
}
steps {
// Use inherited environment variable
echo "My 'PATH' environment variable: '${env.PATH}'"
// Use injected environment variables
echo "My 'param1' environment variable: '${env.param1}'"
echo "My 'param2' environment variable: '${env.param2}'"
// Use injected environment variables in a Groovy script block
script {
def value = env.param1
println "par1 value: '${value}'"
value = env.param2
println "par2 value: '${value}'"
}
}
}
}
}