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

标签 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 master 上根本没有看到这个错误。当我将上面的引用从 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 master 上运行它时,它只包含前四行(echo env.ENVecho param.PARAMecho env.PARAM, echo 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 master 上运行了它。此时,我添加了您在上面的脚本中看到的附加行以进一步澄清。我第一次在该盒子上运行此脚本时,它在“对 $PARAMETER_VARIABLE 行的特定引用”上失败,并显示以下输出:

[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

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

然后我删除了执行“非特定引用”的两行,脚本成功并输出以下输出:

[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 管道中的环境参数 之间有什么关系?这种关系应该是什么?为什么它看起来不一致?

最佳答案

基本上工作原理如下

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

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

参见Global Variable Reference有关变量的更多详细信息。

关于jenkins - Jenkinsfile 参数化构建中的环境和参数之间有什么关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50398334/

相关文章:

jenkins - 当LDAP服务器不可用时如何登录jenkins?

java - 运行 Jenkins 构建抛出 : java. lang.reflect.InaccessibleObjectException

templates - Groovy/Grails SimpleTemplateEngine卡住

java - 通过反射从java执行编译的groovy脚本

jenkins - Linux : Unable to find fallback package folder 'C:\Program Files\dotnet\sdk\NuGetFallbackFolder'

Jenkins Pipeline sleep(10) 阻止功能完成

jenkins - 如何在 Jenkins 声明式管道中为后期操作指定代理

windows - Jenkins + Windows + CMake + 多种构建类型(调试、发布)

ajax - 继续对表数据进行Ajax调用,直到找不到文本为止

Jenkins 管道代码通过 GitHub 组织文件夹插件自动触发多个存储库