Jenkins共享库委派错误
我有一个Jenkins,文件如下: vars/testlib.groovy 和管道脚本,如下所示: 詹金斯档案 我得到以下输出:Jenkins共享库委派错误,jenkins,groovy,jenkins-pipeline,Jenkins,Groovy,Jenkins Pipeline,我有一个Jenkins,文件如下: vars/testlib.groovy 和管道脚本,如下所示: 詹金斯档案 我得到以下输出: [Pipeline] echo foo [Pipeline] End of Pipeline java.lang.NullPointerException: Cannot invoke method foo() on null object 由于某种原因,传递给testlib.bar的闭包不再看到testlib。只有当解决策略有利于代表时,才会发生这种情况;如果我只
[Pipeline] echo
foo
[Pipeline] End of Pipeline
java.lang.NullPointerException: Cannot invoke method foo() on null object
由于某种原因,传递给testlib.bar
的闭包不再看到testlib
。只有当解决策略有利于代表时,才会发生这种情况;如果我只使用OWNER\u
或先使用OWNER\u
它会工作。如果我在委托中提供testlib
,它也可以工作,方法是在映射中设置它,或者只设置body.delegate=body.owner
,如果我只引用闭包中的owner.testlib.foo
来避免解析,它也可以工作。此外,这只发生在库代码中;如果我只是在Jenkins文件中创建一个测试类,它就可以正常工作
似乎如果解决策略是检查委托,而委托没有提供该属性,那么它会立即失败,而不必检查下一个所有者。我做错了什么吗?我无法确切解释Jenkins管道中Groovy闭包委托的情况,但我遇到了类似的问题,我这样修复了它: vars/foo.groovy:
def call() {
echo 'foo'
}
//
// Something like:
//
// bar {
// script = {
// foo()
// return 'Called foo'
// }
// }
//
def call(body) {
def config = [:]
body.delegate = config
body.resolveStrategy = Closure.DELEGATE_FIRST
body()
// In the bar DSL element
echo 'I am bar'
// Expecting a script element as a closure. The insanceof needs script approvals
//assert config.script != null, 'A script element was not supplied'
//assert config.script instanceof Closure, 'The script element supplied must be a closure'
// Call the script closure
config.script.delegate = this
config.script.resolveStrategy = Closure.DELEGATE_FIRST
def result = config.script.call()
// Returning the script result
return result
}
library 'testlib@master'
def result = bar {
script = {
foo()
return 'Called foo'
}
}
echo "result from bar: ${result}"
[Pipeline] echo
I am bar
[Pipeline] echo
foo
[Pipeline] echo
result from bar: Called foo
[Pipeline] End of Pipeline
Finished: SUCCESS
vars/bar.groovy:
def call() {
echo 'foo'
}
//
// Something like:
//
// bar {
// script = {
// foo()
// return 'Called foo'
// }
// }
//
def call(body) {
def config = [:]
body.delegate = config
body.resolveStrategy = Closure.DELEGATE_FIRST
body()
// In the bar DSL element
echo 'I am bar'
// Expecting a script element as a closure. The insanceof needs script approvals
//assert config.script != null, 'A script element was not supplied'
//assert config.script instanceof Closure, 'The script element supplied must be a closure'
// Call the script closure
config.script.delegate = this
config.script.resolveStrategy = Closure.DELEGATE_FIRST
def result = config.script.call()
// Returning the script result
return result
}
library 'testlib@master'
def result = bar {
script = {
foo()
return 'Called foo'
}
}
echo "result from bar: ${result}"
[Pipeline] echo
I am bar
[Pipeline] echo
foo
[Pipeline] echo
result from bar: Called foo
[Pipeline] End of Pipeline
Finished: SUCCESS
Jenkinsfile:
def call() {
echo 'foo'
}
//
// Something like:
//
// bar {
// script = {
// foo()
// return 'Called foo'
// }
// }
//
def call(body) {
def config = [:]
body.delegate = config
body.resolveStrategy = Closure.DELEGATE_FIRST
body()
// In the bar DSL element
echo 'I am bar'
// Expecting a script element as a closure. The insanceof needs script approvals
//assert config.script != null, 'A script element was not supplied'
//assert config.script instanceof Closure, 'The script element supplied must be a closure'
// Call the script closure
config.script.delegate = this
config.script.resolveStrategy = Closure.DELEGATE_FIRST
def result = config.script.call()
// Returning the script result
return result
}
library 'testlib@master'
def result = bar {
script = {
foo()
return 'Called foo'
}
}
echo "result from bar: ${result}"
[Pipeline] echo
I am bar
[Pipeline] echo
foo
[Pipeline] echo
result from bar: Called foo
[Pipeline] End of Pipeline
Finished: SUCCESS
詹金斯输出:
def call() {
echo 'foo'
}
//
// Something like:
//
// bar {
// script = {
// foo()
// return 'Called foo'
// }
// }
//
def call(body) {
def config = [:]
body.delegate = config
body.resolveStrategy = Closure.DELEGATE_FIRST
body()
// In the bar DSL element
echo 'I am bar'
// Expecting a script element as a closure. The insanceof needs script approvals
//assert config.script != null, 'A script element was not supplied'
//assert config.script instanceof Closure, 'The script element supplied must be a closure'
// Call the script closure
config.script.delegate = this
config.script.resolveStrategy = Closure.DELEGATE_FIRST
def result = config.script.call()
// Returning the script result
return result
}
library 'testlib@master'
def result = bar {
script = {
foo()
return 'Called foo'
}
}
echo "result from bar: ${result}"
[Pipeline] echo
I am bar
[Pipeline] echo
foo
[Pipeline] echo
result from bar: Called foo
[Pipeline] End of Pipeline
Finished: SUCCESS
只考虑“Bar”DSL闭包体通过某些配置,如“x= y”之类的赋值形式传递。因此,将其中一个元素设置为由bar()实现执行的闭包元素,然后可以调用其他已定义的库元素。我的Github上有此示例的代码:。您可能还想尝试在Jenkins之外进行单元测试-我这里有一个使用库JenkinsPipelineUnit的示例:。如果在管道中做一些复杂的工作,我建议使用这种单元测试方法,因为它将保持您的理智
我已经注意到,一般来说,带有函数的var文件会使您在Jenkins管道及其单元测试中陷入一些黑暗的角落(无法解释和错误的行为)。我也必须使用显式的this
引用来解决其中一些问题(这与owner
相同,但是this.foo()
看起来比owner.foo()更干净)。