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

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

问题描述

这是我的 Jenkinsfile 的内容:

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

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

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

有人可以解释一下这种奇怪的行为吗?它是一个错误吗?还是只是我不懂 Groovy 语法?

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

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

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.

尽管解决了 JENKINS-26481 (相当新,截至目前写作)许多人可能会被旧版本的 Jenkins 卡住,而该修复程序不可用.对文字列表的 for 循环迭代有时可能会起作用,但相关问题如 JENKINS-46749JENKINS-46747 似乎继续困扰着许多用户.此外,根据 Jenkinsfile 中的确切上下文,echo 可能会起作用,而 sh 会失败,并且事情可能会默默地失败,或者它们可能会因序列化失败而使构建崩溃.

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.

如果你不喜欢意外(跳过循环和静默失败),并且如果你希望你的 Jenkinsfiles 是跨多个 Jenkins 版本的最便携的,那么主要的想法似乎是你应该总是在你的 for-loops 并忽略其他 groovy 功能​​.

这个要点是我见过的最好的参考资料,并详细说明了你的许多案例d 认为应该工作相同,但具有令人惊讶的不同行为.这是建立健全性检查和调试设置的良好起点,无论您正在查看哪种迭代,也无论您是否尝试使用 @NonCPS,直接在内部进行迭代node{},或调用单独的函数.

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天全站免登陆