Трубопровод Дженкинса - Как перебрать список
Мне необходимо прочитать значения из файла в моем конвейере. Я использую 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, управляемых плагином рабочего процесса")