声明性詹金斯管道上不同节点上的并行步骤无法访问在全局范围内定义的变量

parallel steps on different nodes on declarative jenkins pipeline cannot access variables defined in global scope

首先让我说我还没有完全理解 jenkins DSL / groovy 是如何处理名称空间、作用域、变量等的

为了让我的代码保持干燥,我将重复的命令序列放入变量中。 事实证明,doParallelStuff 中的代码无法读取下面的变量 script。这是为什么?有没有办法在主要的管道步骤和 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

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

要解决这个问题,您可以定义不带 def 关键字的变量,这将影响创建该变量的范围,就像没有 def 一样(在 groovy 脚本中, 而不是 class) 变量被添加到脚本的全局变量中 (Binding) which makes it accessible from any function or code within the groovy script. You can read more on the following question:

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

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