Jenkins管道 - 如何遍历列表

时间:2016-07-07 23:59:36

标签: jenkins groovy jenkins-pipeline delivery-pipeline

我需要从管道中的文件中读取值。我使用 split()将它们放入数组。我需要将它们放入 Arraylist 中,所以我使用 Arrays.asList()。我遇到的问题是我无法使用 size() length()方法,因此我无法进行for循环,例如< / p>

for (ii = 0; ii < var.length; ii++)

for (ii = 0; ii < var.size; ii++)

因为我收到错误:未分类字段java.util.Arrays $ ArrayList length

所以我尝试在每个循环中使用a,但是当我在finally块中执行某些操作(例如ls命令)时,它只迭代1次。但是,如果我只是运行命令&#39; echo&#39;它迭代每个元素,就像它应该的那样。有关如何修改我的代码以使其在使用任何命令时对列表中的每个元素进行迭代的任何建议吗?

正常工作....

node{
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) {
        HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n"))
        deploy(HOST)
    }
}

@NonCPS
def deploy(host){
    for (String target : host){
        try {
            echo target
        }
        finally {
           echo target
        }
    }
}

OUTPUT(为每个元素迭代):

[Pipeline] node
Running on <obfuscated>
[Pipeline] {
[Pipeline] wrap
provisoning config files...
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated>
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
www.testhost.com
[Pipeline] echo
www.testhost.com
[Pipeline] echo
www.testhost2.com
[Pipeline] echo
www.testhost2.com
[Pipeline] }
Deleting 1 temporary files
[Pipeline] // wrap
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

但如果我采取一些行动,例如&#39; ls -l&#39; ,它只会迭代一次

node{
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) {
        HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n"))
        deploy(HOST)
    }
}

@NonCPS
def deploy(host){
    for (String target : host){
        try {
            echo target
        }
        finally {
           sh 'ls -l'
        }
    }
}

OUTPUT(仅迭代1次):

[Pipeline] node
Running on <obfuscated>
[Pipeline] {
[Pipeline] wrap
provisoning config files...
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated>
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
www.testhost.com
[Pipeline] sh
[sandbox%2Fpipeline-test-new1] Running shell script
+ ls -l
total 8
-rw-r--r-- 1 jenkins jenkins 10 Jun 17 16:07 someFile
[Pipeline] }
Deleting 1 temporary files
[Pipeline] // wrap
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

4 个答案:

答案 0 :(得分:7)

ArrayList(通常Lists)没有长度或大小字段,他们有size()方法。所以在for:

中使用它
for (ii = 0; ii < var.size(); ii++)

答案 1 :(得分:4)

根据本教程:https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#serializing-local-variables

  

...标注注释select (sum(b.amount) - sum(a.amount)) as result, idm from table a join table b on a.idm = b.idm where a.date = date('2017-08-23') and b.date = date('2017-08-24') group by idm 的方法将被Pipeline引擎视为“本机”,其局部变量从未保存。但是它可能对Pipeline步骤进行任何调用

在您的情况下,@NonCPS调用是一个管道步骤操作,您显然无法在sh带注释的方法中执行此操作。

关于将数组转换为@NonCPS,然后因为我们在Groovy的土地上你可以在数组上使用List方法。

答案 2 :(得分:1)

我无法告诉你为什么,因为我还没有想出如何在不花费数小时谷歌搜索的情况下找到关于詹金斯的有用信息,但我可以告诉你:

我认为你可以通过添加回声线来使它运行良好&#39;在sh&#39; echo $ line&#39;之后,但结果是Jenkins运行了一个PREVIOUS版本的脚本......

我尝试了各种各样的事情,但没有一个能够奏效,然后我发现了这个:

Why an each loop in a Jenkinsfile stops at first iteration

它是Jenkins管道中的已知错误!

(已知的错误是JENKINS-26481,其中表示&#34;至少一些闭包仅在由工作流插件管理的Groovy CPS DSL脚本内执行一次&#34;)

答案 3 :(得分:1)

我更喜欢this solution

node('master') {
    stage('Test 1: loop of echo statements') {
        echo_all(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}"
    }
}

如果使用声明性管道,则必须将调用包装在脚本语句中

stage('master') {
    steps {
        script {
            echo_all(abcs);
        }
    }