简体   繁体   English

Jenkins 共享库,CpsCallableInvocation

[英]Jenkins shared library, CpsCallableInvocation

I am trying to create a shared library for Jenkins.我正在尝试为 Jenkins 创建一个共享库。

I tried to create a script to send notifications through Teams, this is the code:我试图创建一个脚本来通过团队发送通知,这是代码:

def call(String buildStatus = null, String webook) {
    def status
    def color

    switch(buildStatus) {
        case { null || "SUCCESS" }:
            status = "Success"
            color = "Green"
            break
        case "FAILED":
            status = "Failed"
            color = "Red"
            break
        default:
            status = null
            color = null
    }

    println(status + " " + color)
}

The problem is that if I try to run it in my pipeline I get this exception:问题是,如果我尝试在我的管道中运行它,我会得到这个异常:

Error when executing always post condition:
CpsCallableInvocation{methodName=call, call=com.cloudbees.groovy.cps.impl.CpsClosureDef@1ba818f1, receiver=org.jenkinsci.plugins.workflow.cps.CpsClosure2@22438c5c, arguments=[SUCCESS]}

This is the pipeline I am testing:这是我正在测试的管道:

pipeline{
    agent{
        label 'linux'
    } 

    stages{
        stage('Build') {   
            steps{    
                ...snip...
            }
        }

    }
    post {
        always {
            notifyTeams(currentBuild.result, "XXXXX")
        }
    }    

}

What am I doing wrong?我究竟做错了什么? Thanks!谢谢!

The problem is caused by the closure used in the switch statement.该问题是由 switch 语句中使用的闭包引起的。 Jenkins transforms every closure into CPS-transformed closures, which are different than the regular Groovy closures. Jenkins 将每个闭包转换为 CPS 转换的闭包,这与常规的 Groovy 闭包不同。 There are multiple use cases where using CPS-transformed closures causes unexpected errors.有多个用例使用 CPS 转换的闭包会导致意外错误。 I guess this use case was not documented yet, and the closest one to yours is using closure inside the GString one .我猜这个用例还没有记录,最接近你的是GString one 中使用闭包

There are two ways to solve it.有两种方法可以解决它。 Firstly, you can replace a closure in the switch statement with regular values, eg:首先,您可以将 switch 语句中的闭包替换为常规值,例如:

def call(String buildStatus = null, String webook) {
    def status
    def color

    switch(buildStatus) {
        case null:
            status = "Success"
            color = "Green"
            break
        case "SUCCESS":
            status = "Success"
            color = "Green"
            break
        case "FAILED":
            status = "Failed"
            color = "Red"
            break
        default:
            status = null
            color = null
    }

    println(status + " " + color)
}

Alternatively, if you want to use closure inside the switch statement, you will need to extract the switch block to a separate method annotated with @NonCPS .或者,如果您想在 switch 语句中使用闭包,则需要将switch块提取到使用@NonCPS注释的单独方法中。 This is the instruction for the groovy-cps to not transform the code inside this method.这是groovy-cps不转换此方法内的代码的指令。 (You could annotate the call method with @NonCPS , however, if you plan to use pipeline steps in it, it won't work. Pipeline steps have to be executed in the cps mode.) (您可以使用@NonCPS注释call方法,但是,如果您打算在其中使用管道步骤,它将不起作用。管道步骤必须在 cps 模式下执行。)

def call(String buildStatus = null, String webook) {
    def (status, color) = switchBuildStatusAndColor(buildStatus)

    println(status + " " + color)
}

@NonCPS
private static switchBuildStatusAndColor(String buildStatus) {
    switch (buildStatus) {
        case { null || "SUCCESS" }:
            return ["Success", "Green"]

        case "FAILED":
            return ["Failed", "Red"]
    }

    return [null, null]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM