首页 > 解决方案 > 声明式詹金斯管道上不同节点上的并行步骤无法访问在全局范围内定义的变量

问题描述

让我先说我还不完全理解 jenkins DSL / groovy 如何处理命名空间、范围、变量等。

为了保持我的代码干燥,我将重复的命令序列放入变量中。事实证明,script下面的变量不能被doParallelStuff. 这是为什么?有没有办法在主要管道步骤和doParallelStuff代码之间共享脚本(或其他地方)中定义的全局变量?

def script = """\
#/bin/bash
python xyz.py
"""

def doParallelStuff() {
  tests["1"] = {
    node {
      stage('ps1') {
        sh script
      }
    }
  }

  tests["2"] = {
    node {
      stage('ps2') {
        sh script
      }
    }
  }
  parallel tests

}

pipeline {
  stages {
    stage("myStage") {
      steps {
        script {
          sh script
          doParallelStuff()
        }
      }
    }
  }
}

实际步骤要复杂一些,但这会导致抛出如下错误:

hudson.remoting.ProxyException: groovy.lang.MissingPropertyException: No such property: script for class: WorkflowScript

标签: jenkinsjenkins-declarative-pipeline

解决方案


pipeline当您使用关键字定义指令范围之外的变量时,def您是在主脚本的本地范围内定义它,因为pipeline关键字实际上是在主脚本中执行的方法,它可以访问变量,如果它们被定义并且在同一范围内执行(它们实际上被转换为一个单独的类)。
当您在指令之外定义函数时pipeline,该函数具有自己的变量范围,该范围与主脚本的范围分开,因此它无法访问顶层定义的变量。

要解决它,您可以定义不带def关键字的变量,这将影响创建此变量的范围,因为没有def(在 groovy 脚本中,而不是类)变量被添加到脚本的全局变量(绑定)这使得它可以从 groovy 脚本中的任何函数或代码访问。您可以阅读以下问题的更多信息:使用 def 和不使用定义变量有什么区别?

因此,在您的情况下,您需要一个可用于管道代码本身和已定义函数的变量 - 因此它需要在脚本中的任何位置作为全局变量可用,因此只需在没有def关键字的情况下定义它,它应该这样做诀窍:

 script = """\
 #/bin/bash
 python xyz.py
 """

推荐阅读