Jenkins共享库委派错误

时间:2017-05-31 23:03:15

标签: jenkins groovy jenkins-pipeline

我有一个Jenkins shared library,其中包含以下文件:

乏/ testlib.groovy

def foo() {
    echo 'foo'
}

def bar(body) {
    body.delegate = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body()
}

管道脚本如下:

Jenkinsfile

library 'testlib@master'

testlib.foo()
testlib.bar {
    testlib.foo()
}

我得到以下输出:

[Pipeline] echo
foo
[Pipeline] End of Pipeline
java.lang.NullPointerException: Cannot invoke method foo() on null object

由于某种原因,传递给testlib.bar的闭包不会再看到testlib。只有在决议战略有利于代表时才会发生这种情况;如果我使用OWNER_ONLYOWNER_FIRST则可行。如果我在代理中提供testlib,也可以通过在地图中进行设置或仅设置body.delegate = body.owner来实现,如果我通过仅提及owner.testlib.foo来避免解决方案,它也会有效关闭。此外,这只发生在库代码中;如果我只是在Jenkinsfile中创建一个测试类,它可以正常工作。

似乎解决方案策略是检查委托,并且委托不提供该属性,它立即失败而不必费心去检查所有者。我做错了吗?

1 个答案:

答案 0 :(得分:1)

我无法解释Jenkins管道中Groovy闭包委托的确切内容,但我遇到了类似的问题,我修复了这样的问题:

<强>乏/ foo.groovy:

def call() {
    echo 'foo'
}

<强>乏/ bar.groovy:

//
// 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
}

<强> Jenkinsfile:

library 'testlib@master'

def result = bar {

    script = {

        foo()

        return 'Called foo'
    }

}

echo "result from bar: ${result}"

Jenkins输出:

[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上有这个例子的代码:https://github.com/macg33zr/jenkins-pipeline-experiments。您可能还想在Jenkins之外尝试单元测试 - 我在这里使用库JenkinsPipelineUnit:https://github.com/macg33zr/pipelineUnit。如果在管道中做一些复杂的工作,我推荐这种单元测试方法,因为它会保持你的理智!