#jenkins #groovy #jenkins-pipeline
#дженкинс #groovy #дженкинс-конвейер
Вопрос:
У меня есть следующий заводной код:
// @NonCPS
def printList(params) {
def jobs = [:]
println params
params.split(",").each { param ->
println "Param: ${param}"
}
}
text = "Foo,Bar,Baz,Qux"
printList(text)
который работает должным образом при вызове из groovy
команды:
$ groovy test.groovy
Foo,Bar,Baz,Qux
Param: Foo
Param: Bar
Param: Baz
Param: Qux
Хотя при тестировании в рамках задания без изолированной среды в Jenkins я получаю разные результаты:
[Pipeline] echo
Foo,Bar,Baz,Qux
[Pipeline] echo
Param: Foo
[Pipeline] End of Pipeline
Проблема в том, что печатается только первый элемент, а не все.
Однако код работает так, как ожидалось в Jenkins, только при использовании @NonCPS
вспомогательного метода.
Почему @NonCPS
это необходимо для правильной итерации по списку элементов? И есть ли какой-либо обходной путь без использования @NonCPS
(особенно в изолированной среде)?
Комментарии:
1. Я не буду пытаться объяснить вам прямо сейчас, что CPS работает в конвейере, его реализация все еще немного волшебна / непредсказуема для меня и не связана с этим вопросом. Тем не менее, я могу сказать, что конвейер без изолированной среды сильно отличается от изолированной версии того же скрипта. Вероятно, это проблемы с реализацией, как мне кажется. Конвейер Дженкинса все еще находится в стадии интенсивной разработки. Кстати, опция «отключить изолированную среду» недоступна для scipts с SCM-исходным кодом по очевидным причинам
2. Я предлагаю вам сосредоточиться на режиме «изолированный», устраняя проблемы и ограничения, которые у него есть, по мере их появления. Это основной режим для конвейера
Ответ №1:
Вы также можете использовать другие методы для получения того же эффекта. Например, следующее является сериализуемым и не требует, чтобы @NonCPS выполнял итерацию по списку с именем mylist:
for(int i=0; i < mylist.size(); i ) {
println mylist[i]
}
Ответ №2:
Насколько я понимаю, как CPS работает и реализован в целом, и как он обрабатывается конвейером (пока не углублялся в его код), конвейер пытается проверить способность приостанавливать (резервное копирование / .. передача .. / восстановление) состояние выполнения (JVM) в большинстве инструкций кода через интерфейс сериализации. Учитывая, что это JVM < groovy < pipeline DSL .. разработчикам плагинов требуется много усилий для реализации.
Далее, не будучи сам гуру Groovy или Java, насколько я могу судить о его реализации, генераторы groovy (например, { f -> print f }
) очень похожи на генераторы python (yield) или C / C (объекты-функторы).
Пока они не могут быть сериализованы конвейером с легкостью, если итератор объекта итерации (например, индекс списка или состояние выражения выхода) является неявным. Таким образом, предпочтение циклов в стиле Java.
Альтернативные циклы в стиле Java (классический C) намного проще обрабатывать, если область выполнения явно содержит итератор цикла (индексную переменную ‘i’).
Пожалуйста, не считайте это авторитетным ответом, вышеупомянутое — это просто мое личное понимание CPS конвейера