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

Groovy/Jenkins: when are variables null, when are they empty strings, and when are they missing?

我正在尝试理解 Groovy/Jenkinsfiles/declarative 语法中变量的规则。

通用 webhook 触发器捕获 HTTP POST 内容,并将它们作为可用变量提供给您的 Jenkinsfile。例如:

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_name 字段值为“foo”,则打印:

env var foo
global var foo

如果 HTTP POST 内容不包含 JSON 字段 actor_name,则打印

env var null

...然后 asserts/aborts 出现 No such property 错误。

Jenkins 作业也有一个“此项目已参数化”设置,这似乎引入了另一种将变量注入 Jenkinsfile 的方法。以下 Jenkinsfile 打印一个已填充的参数化构建变量、一个未填充的变量和一个故意不存在的变量:

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 []

...然后 asserts/aborts 出现 No such property 错误。

我可以确定的模式是:

    如果
  1. env. 范围内的变量来自未填充的 HTTP POST 内容,则它们将为 NULL。
  2. 如果
  3. env.-scoped 变量来自未填充的参数化构建变量,则它们将为空字符串。
  4. env. 如果在参数化构建变量中不存在,范围变量将为 NULL。
  5. 如果引用全局范围的变量来自未填充的 HTTP POST 内容,则它们将断言。
  6. 如果引用全局范围的变量来自未填充的参数化构建变量,则它们将是空字符串。
  7. params.-scoped 变量如果在参数化构建变量中不存在,则它们将为 NULL。
  8. 如果
  9. params.-scoped 变量来自未填充的参数化构建变量,则它们将为空字符串。

关于这个我有几个问题 - 我相信它们是合理相关的,所以我将它们包括在这个问题中 post:

  1. 变量为NULL和空字符串时pattern/logic背后的底层是什么?
  2. 为什么变量在不同的“范围”可用:env.params.和全局,它们之间的关系是什么(为什么它们不总是1:1)?
  3. 有没有办法让参数化构建中未填充的值成为 Jenkinsfile 中的空值变量而不是空字符串?

上下文:在我的第一个 Jenkinsfile 项目中,我使用了由 HTTP POST 内容填充的变量。通过这个,我开始将值的缺失与相应的 .env 变量的空性相关联。现在,我正在处理来自参数化构建值的变量,当未填充值时,相应的 .env 变量不为空——它是一个空字符串。因此,我想了解这些变量何时以及为何为空与空背后的模式,以便我可以编写可靠而简单的代码来处理来自 HTTP POST 内容和参数化构建值的 absence/non-population 值.

答案有点复杂

对于 1 和 2:

首先管道、阶段、步骤...是groovy类。那里的一切都被定义为 object/variable.

env 是一个包含几乎所有内容的对象,

params 包含所有参数 ;)

它们都是一个Map,如果你访问一个空值它就是空的,如果你访问一个不存在的它就是null。

全局变量本身就是变量,如果您尝试访问不存在的变量,编译器会报错。

对于 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
}