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

24,525

Solution 1

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.

Solution 2

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.

Share:
24,525
Fo.
Author by

Fo.

Updated on July 19, 2022

Comments

  • Fo.
    Fo. almost 2 years

    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?

  • sorin
    sorin almost 7 years
    maybe you also have an idea on how to solve this stackoverflow.com/questions/44629038/… -- what should we do to this to make it work in Jenkins?