【问题标题】:Simple parallel execution in Jenkins for an arrayJenkins 中数组的简单并行执行
【发布时间】:2017-04-26 22:18:31
【问题描述】:

我在使用 Groovy 运行 Jenkins 作业时遇到问题,这看起来超级简单,但我是 1)Java/Groovy 的菜鸟和 2)我能找到的所有示例都不是这正是我需要做的。

我发现了以下类似的问题: Jenkins Groovy Parallel Variable not working,但是那个exact代码会导致错误:

java.lang.UnsupportedOperationException:调用公共静态 java.util.List org.codehaus.groovy.runtime.DefaultGroovyMethods.collect(java.lang.Object,groovy.lang.Closure) 尚不支持 CPS 转换的闭包 (JENKINS-26481); 封装在 @NonCPS 方法中,或使用 Java 样式的循环

这是我想要做的伪代码:

String[] arr = [ "one","two","three",'four','five' ]
echo "Running commands: ${arr}"
int top = arr.size()
echo "top is ${top}"
parallel arr.each {
    echo "${it}"
}

我尝试过闭包,但它们会抛出错误,老实说,我几乎不知道如何使用它们。 以下代码

String[] arr = [ "one","two","three",'four','five' ]
echo "Running commands: ${arr}"

parallel arr.collect { item ->
    { -> 
        echo "${item}"
    }
}

抛出与上述相关问题相同的“java.lang.UnsupportedOperationException”。

我正在尝试学习如何在 Jenkins 中正确使用 Groovy,但它很粗糙。只是在寻找我能得到的任何帮助。

谢谢。

【问题讨论】:

    标签: jenkins groovy


    【解决方案1】:

    这是一个非常烦人的限制,但目前您不能在管道脚本中使用 .each(如此处所述:https://issues.jenkins-ci.org/browse/JENKINS-26481

    你需要做一个实际的循环,比如

    String[] arr = [ "one","two","three",'four','five' ]
    echo "Running commands: ${arr}"
    int top = arr.size()
    echo "top is ${top}"
    for (it in arr) {
        echo "${it}"
    }
    

    如果确实需要并行执行,代码看起来更像:

    String[] arr = [ "one","two","three",'four','five' ]
    echo "Running commands: ${arr}"
    int top = arr.size()
    echo "top is ${top}"
    def stepsForParallel = [:]
    
    for (int i = 0; i < arr.size(); i++) {
        def it = arr[i]
        def stepName = "running ${it}"
        stepsForParallel[stepName] = { ->           
            echo "${it}"
        }
    }
    
    parallel stepsForParallel
    

    您链接到的另一个 stackoverflow 使用 Build Flow 插件,它是您正在使用的 Pipeline 插件的前身。这就是为什么相同的代码不起作用的原因。

    编辑:在现代 Jenkins(在 2.150.1 中测试)中,上面列出的原始错误已修复,.each 有效。您可以为并行执行执行以下操作:

    String[] arr = [ "one","two","three",'four','five' ]
    
    def stepsForParallel = [:]
    arr.each {
        def stepName = "running ${it}"
        stepsForParallel[stepName] = { ->           
            echo "${it}"
        }
    }
    parallel stepsForParallel
    

    【讨论】:

    • 嗨,这里需要关闭什么?我不能分配:stepsForParallel[stepName] = echo "${it}"
    • 我认为这是一个脚本管道,而不是声明性管道,是吗?如果是这样,对于 Jenkins 流水线工作流程的新手来说,可能值得指出这一点。
    • @AdilSadik 正确,尽管将任何脚本化语法插入声明式管道很简单,方法是将其包装在 script { ... } 块中或将脚本放入 .groovy 文件并 loading 它。 (或将其放在库中的vars/ 目录中并将其作为一个步骤调用,但这更高级。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 2017-01-30
    • 1970-01-01
    • 2021-04-22
    • 2021-03-19
    • 1970-01-01
    相关资源
    最近更新 更多