Jenkins 为什么在遍历列表时需要@NonCPS?

Jenkins 为什么在遍历列表时需要@NonCPS?,jenkins,groovy,jenkins-pipeline,Jenkins,Groovy,Jenkins Pipeline,我有以下Groovy代码: // @NonCPS def printList(params) { def jobs = [:] println params params.split(",").each { param -> println "Param: ${param}" } } text = "Foo,Bar,Baz,Qux" printList(text) 当从groovy命令调用时,它会按预期工作: $ groovy test.g

我有以下Groovy代码:

// @NonCPS
def printList(params) {
    def jobs = [:]
    println params
    params.split(",").each { param ->
        println "Param: ${param}"
    }
}
text = "Foo,Bar,Baz,Qux"
printList(text)
当从
groovy
命令调用时,它会按预期工作:

$ groovy test.groovy 
Foo,Bar,Baz,Qux
Param: Foo
Param: Bar
Param: Baz
Param: Qux
虽然在Jenkins的非沙盒工作中进行测试时,我得到了不同的结果:

[Pipeline] echo
Foo,Bar,Baz,Qux
[Pipeline] echo
Param: Foo
[Pipeline] End of Pipeline
问题是只打印第一项,而不是全部

但是,只有在使用
@NonCPS
helper方法时,Jenkins中的代码才能按预期工作

为什么需要
@NonCPS
才能正确遍历项目列表?如果不使用
@NonCPS
(特别是在沙盒环境中),还有什么解决方法吗?

我了解一般情况下是如何工作和实现的,以及管道如何处理它(到目前为止还没有深入到它的代码中),管道尝试测试暂停(备份/.transfer../restore)执行(JVM)的能力通过序列化接口声明大多数代码指令。考虑到它是JVM 其次,我本人并不是Groovy或Java大师,就其实现而言,Groovy生成器(例如,
{f->print f}
)与python(yield)或C/C++生成器(functor对象)非常相似

到目前为止,只要iterable主题迭代器(例如列表索引或屈服表达式状态)是隐式的,就无法通过管道轻松地序列化这些对象。 因此,Java风格的循环是首选的

只要执行范围显式地包含循环迭代器('i'索引变量),可选Java风格(经典C)循环就更易于处理


请不要认为这是一个权威的答案,以上只是我个人对管道CPS

< P>的理解,你也可以使用其他方法来获得同样的效果。例如,以下内容是可序列化的,不需要@NonCPS遍历名为mylist的列表:

for(int i=0; i < mylist.size(); i++) {
  println mylist[i]
}
for(int i=0;i
我现在不想解释CPS在管道中工作,它的实现对我来说仍然有点神奇/不可预测,与这个问题无关。但我可以说,非沙盒管道的行为与同一脚本的沙盒版本大不相同。在我看来,可能是实施问题。詹金斯管道目前仍在大力开发中。顺便说一句,“禁用沙盒”选项不适用于源于SCM的SCIPT,出于明显的原因,我建议您将重点放在“沙盒”模式上,解决出现的问题和限制。这是管道的主要模式