I have a Jenkins shared library with the following file:
vars/testlib.groovy
def foo() {
echo 'foo'
}
def bar(body) {
body.delegate = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body()
}
And a Pipeline script as follows:
Jenkinsfile
library 'testlib@master'
testlib.foo()
testlib.bar {
testlib.foo()
}
I get the following output:
[Pipeline] echo
foo
[Pipeline] End of Pipeline
java.lang.NullPointerException: Cannot invoke method foo() on null object
For some reason, the closure being passed to testlib.bar doesn't see testlib anymore. This only happens if the resolution strategy favors the delegate; if I use OWNER_ONLY or OWNER_FIRST it works. It also works if I provide testlib in the delegate, either by setting it in the map or by just setting body.delegate = body.owner, and it works if I avoid the resolution by just referring to owner.testlib.foo in the closure. Furthermore, this only happens with library code; if I just make a test class in the Jenkinsfile it works fine.
It seems as though if the resolution strategy is to check the delegate, and the delegate doesn't provide that property, it immediately fails without bothering to check the owner next. Am I doing something wrong?