8

I've Pipeline job in Jenkins (v2.7.1) where I'd like to print each element of Multi-line String parameter (Params) with 3 strings in each line: Foo, Bar, Baz as an input.

So I've tried the following syntax (using split and each):

Params.split("\\r?\\n").each { param ->
    println "Param: ${param}"
}

but it fails with:

java.lang.UnsupportedOperationException: Calling public static java.lang.Object org.codehaus.groovy.runtime.DefaultGroovyMethods.each(java.lang.Object,groovy.lang.Closure) on a CPS-transformed closure is not yet supported (JENKINS-26481); encapsulate in a @NonCPS method, or use Java-style loops at org.jenkinsci.plugins.workflow.cps.GroovyClassLoaderWhitelist.checkJenkins26481(GroovyClassLoaderWhitelist.java:90)

which suggest to encapsulate in a @NonCPS method, or use Java-style loops.


So I've tried to encapsulate in a @NonCPS method like:

@NonCPS
def printParams() {
    Params.split("\\r?\\n").each { param ->
        println "Param: ${param}"
    }
}
printParams()

but it fails with:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods println groovy.lang.Closure java.lang.Object

Without the function (as per first example), adding @NonCPS at the beginning it complains about unexpected token.


I also tried Java-style syntax as suggested by using for operator (similar as here):

String[] params = Params.split("\\r?\\n")
for (String param: params) {
    println "Param: ${param}"
}

which seems to work in plain Groovy, but it fails in Jenkins with:

java.io.NotSerializableException: java.util.AbstractList$Itr at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)


Which syntax I should use to make it work?

Community
  • 1
  • 1
kenorb
  • 155,785
  • 88
  • 678
  • 743
  • have you tried to wrap it into @NonCPS ? – agg3l Oct 22 '16 at 18:53
  • I'm not sure how to use it, I've added `@NonCPS` at the beginning, but it complains about *unexpected token*. – kenorb Oct 22 '16 at 19:02
  • in a way like in this question http://stackoverflow.com/questions/36636017/jenkins-groovy-how-to-call-methods-from-noncps-method-without-ending-pipeline . The question itself, not the answer. @NonCPS is smth. like python decorator – agg3l Oct 22 '16 at 19:05
  • I've updated question showing code with @NonCPS which also fails. – kenorb Oct 22 '16 at 19:11
  • 1
    Now you are hitting sandbox security with it. Proceed to Jenkins management to permit this method access or disable sandbox security for your job – agg3l Oct 22 '16 at 19:12
  • Btw, _NotSerializableException_ is also about CPS – agg3l Oct 22 '16 at 19:17
  • Disabling *Use Groovy Sandbox* option for the 2nd example with `@NonCPS` works fine. So if you could wrap it into answer, would be great. Is disabling sandbox necessary to make it work? – kenorb Oct 22 '16 at 19:17

2 Answers2

3

The code works fine when disabling a Use Groovy Sandbox option and adding @NonCPS helper method. Alternatively, as suggested by @agg3l, proceed to Jenkins management to permit this method access.

So the working code is (same as the 2nd example):

@NonCPS
def printParams() {
    Params.split("\\r?\\n").each { param ->
        println "Param: ${param}"
    }
}
printParams()
Community
  • 1
  • 1
kenorb
  • 155,785
  • 88
  • 678
  • 743
  • Alternatively, add your printParams method to a Global Shared Library (see https://jenkins.io/doc/book/pipeline/shared-libraries/#global-shared-libraries) and you don't need to add anything to the scriptApproval – Steve Magness Nov 21 '17 at 09:30
2

I know it's an old post but this is my way to do it, hopefully help anyone else

params.readLines().each {
                            println it
                            if (it) {
                                // if you want to avoid make operation with empty lines
                            }
                        }