В прошлую пятницу я получил ошибку при попытке использовать load в конвейере Jenkinsfile и не могу понять, почему это не работает.
В моей настройке есть мастер Дженкинс и несколько рабов. У меня есть внешний скрипт Groovy, который обрабатывает файлы JSON в зависимости от некоторых условий. Изучая документацию, вы должны загрузить Groovy-сценарий в мастер-файл перед отправкой задания агенту.
Обновлен должный запрос
Я предоставляю более реалистичный тест здесь. Я проверил это на одном локальном сервере Jenkins, версия 2.107.2.
Код для загрузки:
class Foobar {
private name = 'foobar'
private now
Foobar() {
this.now = new Date()
}
String say() {
"My name is $name and I was created at $now"
}
}
def build_foobar() {
new Foobar()
}
return this
Трубопровод:
def foobar
node() {
foobar = load '/tmp/foobar.groovy'
println "After load: $foobar"
}
node() {
stage('checkout') {
println 'checkout from scm'
}
stage('build') {
println "at build: $foobar"
testing()
}
}
def testing() {
println "at testing: $foobar"
def foo = foobar.build_foobar()
println foobar.say()
}
Когда я пытаюсь его выполнить, foobar
генерирует исключение привязки, как если бы я не объявил конвейер раньше, даже если я применил return this
к концу 'foobar.groovy':
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: foobar for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:242)
at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:288)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:292)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
at WorkflowScript.testing(WorkflowScript:22)
at WorkflowScript.run(WorkflowScript:16)
Чтобы выполнить некоторую отладку, я включил println
поверх кода и смог получить Script1@XXXXX
, что означает, что код был прочитан, проанализирован и скомпилирован, как и ожидалось. Если я передаю foobar
в качестве параметра testing()
, это работает, как и ожидалось:
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/teste
[Pipeline] {
[Pipeline] load
[Pipeline] { (/tmp/foobar.groovy)
[Pipeline] }
[Pipeline] // load
[Pipeline] echo
Script1@150cc39b
[Pipeline] }
[Pipeline] // node
[Pipeline] node
Running on Jenkins in /var/lib/jenkins/workspace/teste
[Pipeline] {
[Pipeline] stage
[Pipeline] { (checkout scm)
[Pipeline] echo
checkout
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (build)
[Pipeline] echo
at build: Script1@150cc39b
[Pipeline] echo
at testing: Script1@150cc39b
[Pipeline] echo
My name is foobar and I was created at Mon May 07 09:15:15 BRT 2018
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Теперь это другое поведение, когда у меня есть главный и подчиненный узлы. Единственный способ запустить этот код в подчиненном устройстве (после load
от ведущего устройства) - забыть о foobar()
и выполнить методы конвейера внутри подчиненного узла, все работает как положено. Конечно, это нежелательно, поскольку я просто копирую и вставляю код, а не использую его повторно.
Что мне там не хватает?