Groovy/Jenkins:变量何时为null,何时为空字符串,何时缺失?

Groovy/Jenkins:变量何时为null,何时为空字符串,何时缺失?,jenkins,groovy,jenkins-pipeline,jenkins-declarative-pipeline,Jenkins,Groovy,Jenkins Pipeline,Jenkins Declarative Pipeline,我试图探索Groovy/Jenkinsfiles/declarative语法中围绕变量的规则 通用webhook触发器捕获HTTP POST内容,并将其作为变量提供给文件。例如: pipeline { agent any triggers { GenericTrigger ( genericVariables: [ [ key: "POST_actor_name", value: "\$.actor.name"

我试图探索Groovy/Jenkinsfiles/declarative语法中围绕变量的规则

通用webhook触发器捕获HTTP POST内容,并将其作为变量提供给文件。例如:

pipeline {
  agent any
  triggers {
    GenericTrigger (
      genericVariables: [
        [ key: "POST_actor_name", value: "\$.actor.name" ]
      ],

      token: "foo"
    )
  }

  stages {

    stage( "Set up" ) {
      steps {
        script {
          echo "env var ${env.actor_name}"
          echo "global var ${actor_name}"
        }
    }
  }
}
如果HTTP POST内容包含一个JSON对象,该对象的
actor\u name
字段值为“foo”,则会打印:

env var foo
global var foo
如果HTTP POST内容不包含JSON字段
actor\u name
,则打印此字段

env var null
…然后以
无此类属性的错误断言/中止

Jenkins jobs还有一个“this project is parameterized”设置,它似乎引入了另一种将变量注入Jenkins文件的方法。以下文件打印已填充的参数化生成变量、未填充的生成变量和有意不存在的变量:

pipeline {
  agent any

  stages {

    stage( "Set up" ) {
      steps {
        script {
          echo "1 [${env.populated_var}]"
          echo "2 [${env.unpopulated_var}]"
          echo "3 [${env.dontexist}]"
          echo "4 [${params.populated_var}]"
          echo "5 [${params.unpopulated_var}]"
          echo "6 [${params.dontexist}]"
          echo "7 [${populated_var}]"
          echo "8 [${unpopulated_var}]"
          echo "9 [${dontexist}]"
        }
      }
    }
  }
}
结果是:

1 [foo]
2 []
3 [null]
4 [foo]
5 []
6 [null]
7 [foo]
8 []
…然后以
无此类属性的错误断言/中止

我可以确定的模式是:

  • env.
    -如果作用域变量来自未填充的HTTP POST内容,则这些变量将为NULL
  • env.
    -如果作用域变量来自未填充的参数化生成变量,则它们将是空字符串
  • env.
    -如果参数化生成变量中不存在作用域变量,则作用域变量将为NULL
  • 如果全局作用域变量来自未填充的HTTP POST内容,则引用这些变量将进行断言
  • 如果引用的全局范围变量来自未填充的参数化生成变量,则它们将是空字符串
  • 参数。
    -如果在参数化生成变量中不存在作用域变量,则作用域变量将为NULL
  • params.
    -如果作用域变量来自未填充的参数化生成变量,则它们将是空字符串
  • 关于这一点,我有几个问题——我认为它们有一定的关联,所以我将它们包括在这篇文章中:

  • 当变量为NULL和空字符串时,其背后的基本模式/逻辑是什么?
  • 为什么变量在不同的“作用域”中可用:
    env.
    params.
    和全局,它们之间的关系是什么(为什么不总是1:1)?
  • 有没有办法使参数化构建中的未填充值成为Jenkins文件中的空值变量,而不是空字符串?


  • 上下文:在我的第一个Jenkinsfile项目中,我使用了由httppost内容填充的变量。通过这一点,我将值的缺失与相应的
    .env
    变量的空值相关联。现在,我正在处理来自参数化构建值的变量,当一个值没有填充时,相应的
    .env
    变量不是null——它是一个空字符串。因此,我想了解这些变量是null还是空的时间和原因,这样我就可以编写可靠而简单的代码来处理HTTP POST内容和参数化构建值中的值缺失/未填充。

    答案有点复杂

    对于1和2:

    首先,管道、阶段、步骤。。。是groovy类。其中的所有内容都定义为对象/变量

    env是一个几乎可以容纳所有东西的对象

    params保存所有参数;)

    它们都是映射,如果访问空值,则为空;如果访问不存在的值,则为空

    全局变量本身就是变量,如果试图访问不存在的变量,编译器会抱怨

    对于3:

    您可以定义“默认”参数:

    pipeline {
      agent any
    
      stages {
    
        stage( "Set up" ) {
          steps {
            script {
              params = setConfig(params);
            }
          }
        }
      }
    }
    
    def merge(Map lhs, Map rhs) {
        return rhs.inject(lhs.clone()) { map, entry ->
            if (map[entry.key] instanceof Map && entry.value instanceof Map) {
                map[entry.key] = merge(map[entry.key], entry.value)
            } else {
                map[entry.key] = entry.value
            }
            return map
        }
    }
    
    def setConfig(givenConfig = [:]) {
      def defaultConfig = [
        "populated_var": "",
        "unpopulated_var": "",
        "dontexist": ""
      ];
     
      effectiveConfig = merge(defaultConfig, givenConfig);
       
      return effectiveConfig
    }
    

    很好,全面的回答,谢谢。但是,您知道为什么吗:如果一个变量是从HTTP POST内容填充的,但该变量在HTTP POST中完全不存在,那么相应的
    env.
    变量为空,但是如果同一个变量是从构建参数填充的,并且构建参数为空,那么
    env.
    变量是空字符串?我试图理解为什么“变量未填充”的一个“路径”导致一个空变量,而另一个“路径”导致一个空变量。我不确定。但这可能与GenericTrigger插件有关。在这两种情况下,这都是一个设计决策。插件和参数(很可能)是由不同的人开发的,即使不是,在这两种情况下的决定都是不同的。我认为参数是用“”初始化的,而在GenericTrigger插件中不是。