Jenkins Groovy how to call methods from @NonCPS method without ending pipeline
Asked Answered
P

2

9

I need to parse some JSON in a Jenkins Pipeline and call some regular methods in a loop, however the script always exits after the first function call. How to do this?

import groovy.json.JsonSlurper
import com.cloudbees.groovy.cps.NonCPS

@NonCPS
def myMethod(String json) {
    def jsonSlurper = new JsonSlurper()
    def jsonObject = jsonSlurper(json)
    jsonObject.each {
        obj ->
            switch(obj.name) {
                case "foo":
                    doAThing(obj)
                    break
                case "bar":
                    doAnotherThing(obj)
                    break
            }
    }
}

In the above example, even with a json object like:

[{
    "name": "foo"
}, {
    "name": "bar"
}]

...the pipeline always exits after the first iteration. This is presumably due to mixing sync and async functions. Is there any way to do this?

Polarity answered 14/4, 2016 at 23:53 Comment(4)
Have you noticed the typo: def jsonObject = jsonSurper(json) (missing "l" in the right part)?Granvillegranvillebarker
It's just a typo in the post, not the actual script... But good eye @GranvillegranvillebarkerPolarity
You might have faced this: issues.jenkins-ci.org/browse/JENKINS-31314 or this: issues.jenkins-ci.org/browse/JENKINS-26481Granvillegranvillebarker
Yes, issue 26481 looks likely to be the same.Polarity
P
11

I've resolved this issue essentially by doing the following:

import groovy.json.JsonSlurper

def myMethod(String json) {
    def jsonSlurper = new JsonSlurper()
    def jsonObject = jsonSlurper(json)
    jsonSlurper = null
    for(int i = 0; i < jsonObject.size(); i++) {
        switch(jsonObject[i].name) {
            case "foo":
                doAThing(jsonObject[i])
                break
            case "bar":
                doAnotherThing(jsonObject[i])
                break
        }
    }
}

Immediately destroy the JsonSlurper instance after it's used, remove @NonCPS annotation, switch to a c-style for loop instead of each.

Polarity answered 19/4, 2016 at 23:59 Comment(1)
maybe you also have an idea on how to solve this #44629538 -- what should we do to this to make it work in Jenkins?Aglimmer
A
4

Just to clarify, this is documented as an unsupported feature - https://github.com/jenkinsci/workflow-cps-plugin/#technical-design

You may not call regular (CPS-transformed) methods, or Pipeline steps, from a @NonCPS method, so they are best used for performing some calculations before passing a summary back to the main script.

Aplomb answered 17/12, 2016 at 7:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.