bazza2000 bazza2000 - 1 year ago 127
Groovy Question

Jenkins Build Flow Plugin sequentially chain multiple jobs in parallel

I'm attempting to replicate this functionality from the Build Flow Plugin: https://wiki.jenkins-ci.org/display/JENKINS/Build+Flow+Plugin:

parallel (
{
build("job1")
build("job2")
},
{
build("job5")
build("job6")
}
)


I have the following DSL job:

subjob = "test"
subjob2 = "test2"
series1 = []
series2 = []
subjob = []

["job1","job2"].each{ parameter ->
series1.add({build( subjob, param: parameter )})
}

["job5","job6"].each{ parameter2 ->
series2.add({build( subjob2, param: parameter2)})
}

subjob.add(series1)
subjob.add(series2)

parallel( subjob )


My goal is to run one set of jobs 1&2 in series and another set of jobs 5&6 in series, but to run both sets of jobs in parallel. i.e. Job 1 and 5 kick off at the same time, then when job 1 finishes job 2 start and when job 5 finishes job 6 starts.

However, I've tried a number of variations on the above code, but different errors each time. The above code gives the following:

ERROR: Failed to run DSL Script
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[[email protected], [email protected]]' with class 'java.util.ArrayList' to class 'groovy.lang.Closure' due to: groovy.lang.GroovyRuntimeException: failed to invoke constructor: public groovy.lang.Closure(java.lang.Object,java.lang.Object) with arguments: [[email protected], [email protected]] reason: java.lang.InstantiationException


Is there a better way of doing this?

Answer Source

The parallel step / function expects a list of closures, e.g. a list of code blocks. What you are giving it is a list of list with closures, and naturally you can't cast that to a closure, hence the error:

Cannot cast object '...' with class 'java.util.ArrayList' to class 'groovy.lang.Closure'

What you need to do is to wrap the serial jobs in a closure:

subjob = "test"
subjob2 = "test2"
series1 = []
series2 = []
subTasks = []

["job1","job2"].each{ parameter ->
  series1.add({build( subjob, param: parameter )})
}

["job5","job6"].each{ parameter2 ->
  series2.add({build( subjob2, param: parameter2)})
}

subTasks.add({
  series1.each{it()}
})
subTasks.add({
  series2.each{it()}
})

parallel( subTasks )

An explanation of what I do:

subTasks.add({
  series1.each{it()}
})

First we add a new closure to the list subTasks, this closure takes each element in the list and executes it (it()).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download