【Pipeline】Jenkins流水线中如何使用全局变量

发布时间 2023-10-31 20:10:15作者: 爱啦啦

例如我们在 stage1中 利用 script 代码块 设置赋值了一个 变量,然后想在 stage2中使用。应该怎么操作呢?

https://stackoverflow.com/questions/53541489/updating-environment-global-variable-in-jenkins-pipeline-from-the-stage-level/53541813

https://www.youtube.com/watch?v=KwQDxwZRZiE

你不能重写在environment{}块中定义的环境变量。不过,有一个技巧你可能想用。可以参考ACC环境变量
有两种方式: 

    explicitly by env.ACC  显示定义,明确地定义,更推荐使用这种 带 env. 的方式来定义
    implicitly by ACC      隐式定义。

The value of env.ACC cannot be changed once set inside environment {} block,
 but ACC behaves in the following way: when the variable ACC is not set then
 the value of env.ACC gets accessed (if exists of course). But when ACC variable
 gets initialized in any stage, ACC refers to this newly set value in any stage.
 Consider the following example:



pipeline {
    agent any

    environment {
        FOO = "initial FOO env value"
    }

    stages {
        stage("Stage 1") {
            steps {
                script {
                    echo "FOO is '${FOO}'" // prints: FOO is 'initial FOO env value'

                    env.BAR = "bar"
                }
            }
        }

        stage("Stage 2") {
            steps {
                echo "env.BAR is '${BAR}'" // prints: env.BAR is 'bar'
                echo "FOO is '${FOO}'" // prints: FOO is 'initial FOO env value'
                echo "env.FOO is '${env.FOO}'" // prints: env.FOO is 'initial FOO env value'
                script {
                    FOO = "test2"
                    env.BAR = "bar2"
                }
            }
        }

        stage("Stage 3") {
            steps {
                echo "FOO is '${FOO}'" // prints: FOO is 'test2'
                echo "env.FOO is '${env.FOO}'" // prints: env.FOO is 'initial FOO env value'
                echo "env.BAR is '${BAR}'" // prints: env.BAR is 'bar2'

                script {
                    FOO = "test3"
                }

                echo "FOO is '${FOO}'" // prints: FOO is 'test3'
            }
        }
    }
}

And as you can see in the above example, the only exception to the rule is if the environment variable gets initialized outside the environment {} block. 
For instance, env.BAR in this example was initialized in Stage 1, but the value of env.BAR could be changed in Stage 2 and Stage 3 sees changed value. 

通过上面的例子,可以看到 如果在 environment {} 块中定义并初始化变量 FOO = "initial FOO env value" 的话
后续在任何 satege 中 这样 使用 env.FOO 的话 这个值一直都是 "initial FOO env value", 不会被后面的赋值语句给覆盖了。

如果后续的 stage 中 这样隐式定义 一个变量FOO,并设置了另外的值 FOO = "test2" 那么后续 的stage 访问 FOO 的话 就会是 test2,
访问 env.FOO 的话 值 还是 "initial FOO env value" 。  注意 一个是这样 FOO 访问的, 一个是 env.FOO 访问的。


如果 在 environment {} 块中 没有定义 变量 BAR, 而是 在后续的stage中定义并初始化这个变量了(env.BAR = "bar2")。
那么后续stage 还可以重新赋值 覆盖 env.BAR 这个变量。

总结一下:
1. 在 environment {} 块中 不定义任何变量, 后续在 stage 这样使用 env.BAR 这样显示的使用。如果显示的使用就一直显示的使用,不要混用。
2. 在 environment {} 块中 定义了变量, 那么后续在 stage 也一直  env.BAR 这样显示的使用,并且不要在做赋值的操作,就当成 env.BAR 是一个只读的全局变量了。 显示的使用就一直显示的使用,不要混用。 
3. 在 environment {} 块中 不定义任何变量, 后续在 stage 这样使用  BAR 这样使用,隐式的定义,赋值来使用。后续就一直隐式的使用,不要混用。
4. 如果 这样 初始化 FOO = "" 赋值一个空字符串,这在groovy中是unset一个变量的。并不是赋值一个空字符串的。

UPDATE 2019-12-18

There is one way to override the environment variable defined in the environment {} block - you can 
use withEnv() block that will allow you to override the existing env variable. It won't change the 
value of the environment defined, but it will override it inside the withEnv() block. Take a look at the following example:

pipeline {
  agent any 

  stages {
    stage("Test") {
      environment {
        FOO = "bar"
      }

      steps {
        script {
          withEnv(["FOO=newbar"]) {
            echo "FOO = ${env.FOO}" // prints: FOO = newbar  这里利用 withEnv 重新 赋值影响的也只是 withEnv 块的代码。
          }
        }
      }
    }
  }
}