Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple parallel execution in Jenkins for an array

Tags:

jenkins

groovy

I'm having trouble running a Jenkins job using Groovy, and it seems super simple but I'm 1) a noob at Java/Groovy and 2) all the examples I can find are not quite what I need to do.

I found the following similar question: Jenkins Groovy Parallel Variable not working, but that exact code results in an error:

java.lang.UnsupportedOperationException: Calling public static java.util.List org.codehaus.groovy.runtime.DefaultGroovyMethods.collect(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

Here's my pseudo-code of what I want to do:

String[] arr = [ "one","two","three",'four','five' ]
echo "Running commands: ${arr}"
int top = arr.size()
echo "top is ${top}"
parallel arr.each {
    echo "${it}"
}

I've tried closures, but they throw an error and honestly I barely know how to use them. The following code

String[] arr = [ "one","two","three",'four','five' ]
echo "Running commands: ${arr}"

parallel arr.collect { item ->
    { -> 
        echo "${item}"
    }
}

throws the same "java.lang.UnsupportedOperationException" as the related question above.

I'm trying to learn how to properly utilize Groovy with Jenkins, but it's been rough. Just looking for any help I can get at this point.

Thank you.

like image 901
Frederick Rueger Avatar asked Apr 26 '17 22:04

Frederick Rueger


People also ask

How do I run parallel execution in Jenkins?

This plugin adds a tool that lets you easily execute tests in parallel. This is achieved by having Jenkins look at the test execution time of the last run, split tests into multiple units of roughly equal size, then execute them in parallel.

Can Jenkins run parallel builds?

Jenkins is a great CI tool when it comes to flexibility. Every simple thing can be done in ten different ways, including parallelizing a build.


1 Answers

It's a pretty annoying limitation, but currently you can't use .each in a pipeline script (as documented here: https://issues.jenkins-ci.org/browse/JENKINS-26481)

You need to do an actual loop, like

String[] arr = [ "one","two","three",'four','five' ]
echo "Running commands: ${arr}"
int top = arr.size()
echo "top is ${top}"
for (it in arr) {
    echo "${it}"
}

If actually need parallel execution the code will look more like:

String[] arr = [ "one","two","three",'four','five' ]
echo "Running commands: ${arr}"
int top = arr.size()
echo "top is ${top}"
def stepsForParallel = [:]

for (int i = 0; i < arr.size(); i++) {
    def it = arr[i]
    def stepName = "running ${it}"
    stepsForParallel[stepName] = { ->           
        echo "${it}"
    }
}

parallel stepsForParallel

The other stackoverflow you linked to uses the Build Flow plugin, which is the predecessor to the Pipeline plugin that you're using. That's why the same code doesn't work.

EDIT: In modern Jenkins (tested in 2.150.1) the original bug listed above is fixed, and .each works. You can do the following for parallel execution:

String[] arr = [ "one","two","three",'four','five' ]

def stepsForParallel = [:]
arr.each {
    def stepName = "running ${it}"
    stepsForParallel[stepName] = { ->           
        echo "${it}"
    }
}
parallel stepsForParallel
like image 68
Kendall Trego Avatar answered Nov 01 '22 20:11

Kendall Trego