I am trying to create a shared library for 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. Jenkins transforms every closure into CPS-transformed closures, which are different than the regular Groovy closures. There are multiple use cases where using CPS-transformed closures causes unexpected errors. I guess this use case was not documented yet, and the closest one to yours is using closure inside the GString one.
There are two ways to solve it. Firstly, you can replace a closure in the switch statement with regular values, e.g.:
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. This is the instruction for the groovy-cps to not transform the code inside this method. (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.)
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]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With