Jenkins流水线/Groovy脚本中的未定义变量

3

我正在尝试将我的大型多配置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

我的问题是当我尝试建立一个`build_test_configs`的字典时,到了第13行时${compilers[j]$configs[i] 是未定义的。看起来第8行的检查工作得很好。

更新

我没有明确的错误信息。脚本不会产生任何运行时错误。意外的输出是阶段的名称为:
  • Build Test node001 null null
  • Build Test node001 null null
  • Build Test node002 null null
而且`nightly.sh`脚本也会传递`null`参数。

好问题!也许在这里转储错误消息? - burnettk
抱歉!@KevinBurnett,我忘记了那个。我已经更新了问题并包含了输出。 - Wesley Bland
是的,我正在简化我的脚本,错过了那个。已经修复了。谢谢@HuguesMoreau。 - Wesley Bland
1个回答

2
我认为这是预期的行为:Jenkins Pipeline脚本是用Groovy编写的,但实际执行的是该脚本的转换(他们使用的术语是“传递风格转换”)。例如,一些部分将在主节点上运行,一些部分将在从节点上运行。
这涉及很多超出我的理解范围的魔法,但在我们这个层面上,这意味着我们必须在使用的语法和结构中遵守一些约束条件。
请参见此文章的“基础知识”段落

要理解Pipeline的行为,您必须了解关于如何执行的几点。

  1. 除了步骤本身之外,所有的管道逻辑、Groovy条件语句、循环等都在主节点上执行。无论是简单还是复杂的逻辑!即使在node块内部也是如此。
  2. 步骤可以使用执行器来适当地执行工作,但每个步骤也有一个小的主节点开销。
  3. 管道代码是用Groovy编写的,但执行模型在编译时被彻底转换为Continuation Passing Style(CPS)。
  4. 这种转换为管道提供了宝贵的安全和耐久性保证,但它也带来了一些权衡:步骤可以调用Java并快速高效地执行,但Groovy运行速度比正常情况下要慢得多。Groovy逻辑需要更多的内存,因为一个基于对象的语法/块树被保存在内存中。
  5. 管道经常将程序及其状态持久化,以便能够在主节点故障时生存。

另请参见JENKINS-41335,讨论跨脚本支持变量的问题。

编辑:啊,是的,正如评论中指出的那样,新的声明性模型允许定义一个带有变量的环境,这些变量将以你需要的方式传递... 不知道在脚本化流水线中如何做到这一点没有JENKINS-41335,但似乎进一步的发展现在将在声明性领域中发生 :/

我的问题之一是我正在使用“脚本管道”语法而不是新的“声明性管道”语法。如果我能使用后者(特别是在查找文档方面),事情似乎会更容易,但由于我需要程序生成阶段列表并并行运行它们,所以“声明性管道”语法不是一个选项。 - Wesley Bland
嗯,也许我有点混淆了?但无论如何,我认为你在stage步骤中仍然受到限制,只能使用特定的内容。 - Hugues M.
也许我需要退后一步,重新思考我正在进行的整个流程。我很难找到有关将复杂的多配置作业转换为管道的建议。 - Wesley Bland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接