为什么Jenkinsfile中的每个循环在第一次迭代时停止 [英] Why an each loop in a Jenkinsfile stops at first iteration

查看:158
本文介绍了为什么Jenkinsfile中的每个循环在第一次迭代时停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我的 Jenkinsfile 的内容:

  node { 
//只打印第一个元素'a'
['a','b','c'] .each {
echo it
}
}

在Jenkins中执行作业时(使用管道插件),只打印列表中的第一项。



<有人能解释我这种奇怪的行为吗?这是一个错误吗?或者它只是我不理解Groovy语法?


$ b

编辑 for(i in items)按预期工作:

 节点{
//打印'a','b'和'c'
(['a','b','c']){
echo i
}
}


解决方案

这里接受的答案表明这是一个已知的错误,并且使用了一种解决方法为我工作,所以我会提供我最近发现的更新。

尽管 JENKINS -26481 (相对来说,截至撰写本文时)很多人可能会遇到Jenkins的老版本,在那里修补程序不可用。对文字列表进行循环迭代可能有时会起作用,但相关问题如 JENKINS-46749 < a>和 JENKINS-46747 似乎继续困扰着许多用户。另外,根据Jenkinsfile中的确切上下文,可能 echo 可以工作,而 sh 会失败,并且事情可能会失败或者他们可能会崩溃编译序列化失败。 b
$ b

如果你不喜欢惊喜(跳过循环和无声失败),并且如果你想让Jenkinsfiles成为Jenkins多个版本中最容易移植的,因为你应该总是在你的for循环中使用经典的计数器,并忽略其他的常规功能。



这份要求是我见过的最好的参考资料,详细列出了许多你认为应该工作的案例,但行为有着惊人的不同。无论您在寻找什么类型的迭代,并且无论您是否尝试使用 @NonCPS ,它都是建立理智检查和调试设置的好起点。 ,直接在 node {} 中进行迭代,或者调用一个单独的函数。

再一次,我对这项工作本身毫不留情,但我将后面的迭代测试案例的要点嵌入了后代:

  abcs = ['a','b','c'] 

节点('master'){
stage '测试1:循环的echo语句'){
echo_all(abcs)
}
stage('测试2:循环的sh命令'){
loop_of_sh(abcs)$ ('Test 3:loop with the SH'){
loop_with_preceding_sh(abcs)
}
stage('Test 4:traditional for loop'){b $ b}
stage
traditional_int_for_loop(abcs)
}
}

@NonCPS //必须是NonCPS或者每次调用.each
时的构建中断。def echo_all (list){
list.each {item - >
echoHello $ {item}
}
}
//输出预期的所有项目

@NonCPS
def loop_of_sh(列表){
list.each {item - >
shecho hello $ {item}
}
}
//输出第一项

@NonCPS
def loop_with_preceding_sh (列表){
shecho回显列表
list.each {item - >
shecho $ Hello $ {item}
}
}
//只输出要回显列表位

//没有NonCPS需要
def traditional_int_for_loop(list){
shecho回显列表
for(int i = 0; i< list.size(); i ++){
shecho $ Hello $ {list [i]}
}
}
//将所有内容按照预期反映出来


Here is the content of my Jenkinsfile :

node {
    // prints only the first element 'a'
    [ 'a', 'b', 'c' ].each {
        echo it
    }
}

When executing the job in Jenkins (with the Pipeline plugin), only the first item in the list is printed.

Can someone explain me this strange behavior? Is it a bug? or is it just me not understanding the Groovy syntax?

Edit : the for (i in items) works as expected :

node {
    // prints 'a', 'b' and 'c'
    for (i in [ 'a', 'b', 'c' ]) {
        echo i
    }
}

解决方案

The accepted answer here states that it's a known bug, and uses a workaround that didn't work for me, so I'll offer an update with what I've found lately.

Despite the resolution of JENKINS-26481 (fairly recent, as of this writing) many people may be stuck with an older version of Jenkins where the fix is not available. For-loop iteration over a literal list might work sometimes but related issues like JENKINS-46749 and JENKINS-46747 seem to continue to bedevil many users. Also, depending on the exact context in your Jenkinsfile, possibly echo will work whereas sh fails, and things might fail silently or they might crash the build with serialization failures.

If you dislike surprises (skipped loops and silent failures) and if you want your Jenkinsfiles to be the most portable across multiple versions of Jenkins, the main idea seems to be that you should always use classic counters in your for-loops and ignore other groovy features.

This gist is the best reference I've seen and spells out many cases that you'd think should work the same but have surprisingly different behaviour. It's a good starting place to establish sanity checks and debug your setup, regardless of what kind of iteration you're looking at and regardless of whether you're trying to use @NonCPS, do your iteration directly inside node{}, or call a separate function.

Again, I take no credit for the work itself but I'm embedding the gist of iteration test cases below for posterity:

abcs = ['a', 'b', 'c']

node('master') {
    stage('Test 1: loop of echo statements') {
        echo_all(abcs)
    }
    stage('Test 2: loop of sh commands') {
        loop_of_sh(abcs)
    }
    stage('Test 3: loop with preceding SH') {
        loop_with_preceding_sh(abcs)
    }
    stage('Test 4: traditional for loop') {
        traditional_int_for_loop(abcs)
    }
}

@NonCPS // has to be NonCPS or the build breaks on the call to .each
def echo_all(list) {
    list.each { item ->
        echo "Hello ${item}"
    }
}
// outputs all items as expected

@NonCPS
def loop_of_sh(list) {
    list.each { item ->
        sh "echo Hello ${item}"
    }
}
// outputs only the first item

@NonCPS
def loop_with_preceding_sh(list) {
    sh "echo Going to echo a list"
    list.each { item ->
        sh "echo Hello ${item}"
    }
}
// outputs only the "Going to echo a list" bit

//No NonCPS required
def traditional_int_for_loop(list) {
    sh "echo Going to echo a list"
    for (int i = 0; i < list.size(); i++) {
        sh "echo Hello ${list[i]}"
    }
}
// echoes everything as expected

这篇关于为什么Jenkinsfile中的每个循环在第一次迭代时停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆