Jenkinsfile参数化构建中的环境和参数之间有什么关系?

时间:2018-05-17 18:34:24

标签: jenkins groovy jenkins-pipeline

我最近在与同事一起制作一些Jenkins构建时遇到了一些益智游戏。他一直在使用params.VARIABLEenv.VARIABLE,并且没有任何问题。同时,我开始通过这行代码中的环境调用参数对象的一个​​空对象错误:

if(!deploy_environments.contains(env.ENVIRONMENT_NAME.trim()) || params.INVOKE_PARAMETERS ) {

ENVIRONMENT_NAME这是一个参数。我开始收到此错误:

java.lang.NullPointerException: Cannot invoke method trim() on null object

此构建作为另一个构建的子代执行。 ENVIRONMENT_NAME参数从该父版本向下传递给子项。

他在一个不同的Jenkins大师身上根本没有看到这个错误。当我将上述参考从env.ENVIRONMENT_NAME更改为params.ENVIRONMENT_NAME时,问题就消失了。

我在Jenkins文档中找不到params == env的引用,所以我创建了一个构建来试图澄清它们之间的关系。

pipeline {
    agent {
        label 'jenkins-ecs-slave'
    }
    environment {
        ENV_VARIABLE = 'Environment'
    }
    parameters {
        string(description: 'Parameter', name: 'PARAMETER_VARIABLE', defaultValue: 'Parameter')

    }
    stages {
       stage('Output Parameters'){
          steps {
             script {
                 echo "Environment: ${env.ENV_VARIABLE}"
                 echo "Parameter: ${params.PARAMETER_VARIABLE}"
                 echo "Environment from params: ${params.ENV_VARIABLE}"
                 echo "Parameter from Env: ${env.PARAMETER_VARIABLE}"
                 echo "Inspecific reference ENV_VARIABLE: $ENV_VARIABLE"
                 echo "Inspecific reference PARAMETER_VARIABLE: $PARAMETER_VARIABLE"
                 sh 'echo "Shell environment: $ENV_VARIABLE"'
                 sh 'echo "Shell parameter: $PARAMETER_VARIABLE"'                  
             }
           }
       }
    }
}

我第一次在我的Jenkins大师上运行它时,它只包括前四行(echo env.ENVecho param.PARAMecho env.PARAMecho param.ENV)它成功了以下输出:

[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: null
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

我想,“啊哈!”问题解决了。他们不一样。

然而,那个盒子后来立即冻结了我,拒绝排队。我还没有完成它的调试,但是不知道那个主人是不是搞砸了。

所以我去了第三个Jenkins大师,我们一直闲逛。在这一点上,我添加了您在上面的脚本中看到的其他行,以进一步澄清。我第一次在那个盒子上运行这个脚本时,它在“Inspecific reference to $ PARAMETER_VARIABLE line”上输出失败,输出如下:

[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: null
[Pipeline] echo
Inspecific reference ENV_VARIABLE: Environment
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: PARAMETER_VARIABLE for class: groovy.lang.Binding

好的,到目前为止一切顺利。这是有道理的。他们不一样。您可以在没有专门引用环境对象的情况下引用回声和shell中的环境变量,但不能对参数执行相同的操作。一致,合理,我很擅长这一点。

然后我删除了执行“inspecific reference”的两行,脚本成功完成了以下输出:

[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: Parameter
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell environment: Environment'
Shell environment: Environment
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell parameter: Parameter'
Shell parameter: Parameter
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

现在我完全糊里糊涂了。我勒个去?为了确保我运行了几次,并且始终如一地获得了与上面相同的成功输出。

当然,以前没有显示env.PARAM null的构建在一个干净的环境中成功了(成功的那个环境在之后迅速崩溃的环境中)。那么也许如果Jenkins管道中出现错误,它会将参数加载到环境中或其他什么内容?我尝试将echo "$I_SHOULD_FAIL"添加到脚本中以强制出错以尝试重现我所看到的内容。没有骰子:

[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: Parameter
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell environment: Environment'
Shell environment: Environment
[Pipeline] sh
[Environment Testing] Running shell script
+ echo 'Shell parameter: Parameter'
Shell parameter: Parameter
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: I_SHOULD_FAIL for class: groovy.lang.Binding

那么这里发生了什么? Jenkins管道中environmentparameters之间的关系是什么?应该是什么关系,为什么它似乎不一致?

1 个答案:

答案 0 :(得分:6)

基本上它的工作原理如下

  • env包含所有environment variables
  • Jenkins管道自动为每个环境变量创建一个全局变量
  • params包含所有构建参数
  • Jenkins还会自动为每个构建参数创建一个环境变量(并且第二个点是全局变量的结果)。

可以覆盖或取消设置环境变量,但params是不可变的Map,无法更改。最佳做法是在需要获取构建参数时始终使用params