【问题标题】:Jenkins Pipeline / Groovy Script with undefined variables具有未定义变量的 Jenkins Pipeline / Groovy 脚本
【发布时间】:2017-10-03 23:12:41
【问题描述】:

我正在尝试将我的大型多配置 Jenkins 作业转换为管道语法,以便除其他外,我可以将其拆分到多个节点并将多个阶段合并为一项作业。这是我遇到问题的部分:

def build_test_configs = [:]
def compilers = ['gnu', 'icc']
def configs = ['debug', 'default', 'opt']

for (int i = 0; i < configs.size(); i++) {
    for (int j = 0; j < compilers.size(); j++) {
        def node_name = ""
        if ("${compilers[j]}" == "gnu") {
            node_name = "node001"
        } else {
            node_name = "node002"
        }
        build_test_configs["${node_name} ${configs[i]}"] = {
            node ("${node_name}") {
                stage("Build Test ${node_name} ${compilers[j]} ${configs[i]}") {
                    unstash "${node_name}-tarball"
                    sh "$HOME/software/jenkins_scripts/nightly.sh ${configs[i]} ${compilers[j]} yes $WORKSPACE"
                }
            }
        }
    }
}

parallel build_test_configs

我的问题是 ${compilers[j]$configs[i] 在第 13 行尝试建立 build_test_configs 字典的部分时未定义。看来第 8 行的检查是工作得很好。

更新

我本身没有错误消息。该脚本不会产生任何运行时错误。出乎意料的输出是阶段的名称是:

  • 构建测试 node001 null null
  • 构建测试 node001 null null
  • 构建测试 node002 null null

nightly.sh 脚本也正在传递null 参数。

【问题讨论】:

  • 好问题!也许在这里转储错误消息?
  • 噢!很抱歉忽略了@KevinBurnett。我已更新问题以包含输出。
  • 是的。我正在简化我的脚本并错过了那个。它已被修复。谢谢@HuguesMoreau。

标签: jenkins groovy jenkins-pipeline


【解决方案1】:

我认为这是预期的行为:Jenkins Pipeline 脚本是用 Groovy 编写的,但实际执行的是对其的转换(他们使用的术语是“连续传递样式转换”)。例如,有些部分会在主节点上运行,有些会在从节点上运行。

这涉及到很多不可思议的魔法,但在我们的水平上,这意味着我们必须处理我们使用的语法和结构中的约束。

"fundamentals" paragraph of this article

要了解 Pipeline 行为,您必须了解有关其执行方式的几点。

  1. 除了步骤本身,所有流水线逻辑, Groovy 条件、循环等在 master 上执行。无论 简单或复杂!甚至在节点块内!
  2. 步骤可以在适当的情况下使用执行器来完成工作,但每个步骤也有少量的主控开销。
  3. 管道代码是用 Groovy 编写的,但执行 模型在编译时被彻底转换为 Continuation 传球风格 (CPS)。
  4. 这种转换提供了宝贵的安全性 和管道的持久性保证,但它附带 权衡:步骤可以调用 Java 并快速高效地执行, 但是 Groovy 的运行速度比正常情况要慢得多。 Groovy 逻辑需要 更多内存,因为保留了基于对象的语法/块树 在记忆中。
  5. 管道经常保持程序及其状态以 能够在主人的失败中幸存下来。

另请参阅 JENKINS-41335 讨论脚本中对变量的支持。

编辑:啊,是的,正如 cmets 中所指出的那样,新的声明性模型允许定义一个 environment 变量,这些变量将以您需要的方式传递......不知道如何在脚本化管道中做到这一点没有 JENKINS-41335,但现在似乎在声明性土地上会发生进一步的演变:/

【讨论】:

  • 所以我的部分问题是我使用的是“脚本化管道”语法而不是新的“声明性管道”语法。如果我可以使用后者(尤其是在查找文档方面),似乎事情会容易得多,但是因为我需要以程序方式生成我的阶段列表并并行运行它们,所以“声明性管道”语法不是一个选项.
  • 嗯,也许我有点搞混了?但在所有情况下,我认为您仍然受限于在 stage 步骤中可以使用的内容。
  • 也许我需要退后一步,重新思考我正在经历的整个过程。我很难找到关于将复杂的多配置作业转换为管道的建议。