Трубопровод Дженкинса - Как перебрать список

Мне необходимо прочитать значения из файла в моем конвейере. Я использую split(), которая помещает их в массив. Мне нужно поместить их в Arraylist, поэтому я использую Arrays.asList (). Проблема в том, что я не могу использовать методы size() или length(), поэтому я не могу создать цикл for, такой как

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

или же

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

потому что я получаю ошибку: несекретное поле java.util.Arrays$ArrayList length

Поэтому я попытался использовать для каждого цикла, но когда я выполняю какое-то действие (например, команду ls) в моем блоке finally, оно повторяется только 1 раз. Но если я просто запускаю команду 'echo', она повторяется для каждого элемента, как и должно быть. Любой совет, как изменить мой код, чтобы заставить его повторяться для каждого элемента в списке при использовании какой-либо команды?

Работает правильно....

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
        }
    }
}

ВЫХОД (повторяется для каждого элемента):

[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

Но если я предприму какое-либо действие, такое как 'ls -l', оно будет повторяться только 1 раз

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'
        }
    }
}

ВЫХОД (только повторяется 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

3 ответа

ArrayList (и вообще Lists) не имеют поля длины или размера, они имеют size() метод. Так что используйте это для:

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

Я предпочитаю это решение:

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);
        }
    }

Согласно этому руководству: https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#serializing-local-variables

... метод, помеченный аннотацией @NonCPS... будет обработан конвейером как "нативный", а его локальные переменные никогда не сохраняются. Однако он не может делать какие-либо вызовы к этапам конвейера

В вашем случае sh вызов - это операция шага конвейера, которую вы, очевидно, не можете выполнить изнутри @NonCPS аннотированный метод.

Что касается превращения массива в List, так как мы находимся на Groovy земле, вы можете просто использовать .toList() метод на массиве.

Я не могу сказать вам ТОЧНО, почему, так как я не понял, как найти полезную информацию о Дженкинсе, не тратя часы на поиски в Google, но я могу сказать вам следующее:

На мгновение я подумал, что вы можете заставить его работать нормально, добавив 'echo line' ПОСЛЕ sh 'echo $line', но это, как оказалось, было вызвано тем, что Дженкинс запустил ПРЕДЫДУЩУЮ версию скрипта...

Я перепробовал все виды вещей, и ничего из них не сработало, потом я нашел это:

Почему каждый цикл в Jenkinsfile останавливается на первой итерации

Это известная ошибка в конвейере Jenkins!

(известной ошибкой является JENKINS-26481, которая говорит: "По крайней мере, некоторые замыкания выполняются только один раз внутри скриптов Groovy CPS DSL, управляемых плагином рабочего процесса")

Другие вопросы по тегам