Title: Message Title
Nadav Goldin commented on JENKINS-38268
Re: Parallel step and closure scope
Hi, I'm experiencing what I think is a symptom of the same issue, while trying to trigger parallel builds, take this pipeline job, assuming the dummy jobs 'job-1,2,3' exists:
@NonCPS
def get_dummy_params(val)
{
return [string(name: 'dummy', value: "$val")]
}
@NonCPS
def create_jobs()
{
def jobs = [:]
(1..3).each { jobs["job-$it"] = { -> build([job: "job-$it", parameters: get_dummy_params(it) ]) } }
return jobs
}
stage ('triggering') {
parallel(create_jobs())
}
I would expect it to trigger the 3 jobs in parallel, instead it 'nests' under 'job-1' branch all 3 jobs, and creates empty branches for 'job-2' and 'job-3', causing the job to never end. Console output:
Started by user admin
[Pipeline] stage
[Pipeline] { (triggering)
[Pipeline] parallel
[Pipeline] [job-1] { (Branch: job-1)
[Pipeline] [job-1] build (Building job-1)
[job-1] Scheduling project: job-1
[Pipeline] [job-2] { (Branch: job-2)
[Pipeline] [job-1] build (Building job-2)
[job-1] Scheduling project: job-2
[Pipeline] [job-3] { (Branch: job-3)
[Pipeline] [job-1] build (Building job-3)
[job-1] Scheduling project: job-3 !pipeline_steps.png|thumbnail!
[job-1] Starting building: job-3 #1
...
I found only 2 workarounds: 1. Don't use any functions to generate data fed into 'parallel' function(i.e. create everything under the 'stage' step). 2. Feeding a newly created map to parallel and redefining the groovy closures with a '.call()' (frankly I have no idea how I came up with this). I.e. replace the 'stage' in the previous example with:
stage ('triggering') {
def jobs = create_jobs()
parallel([
'job-1': { jobs['job-1'].call() },
'job-2': { jobs['job-2'].call() },
'job-3': { jobs['job-3'].call() },
])
}
Output as expected:
Started by user admin
[Pipeline] stage
[Pipeline] { (triggering)
[Pipeline] parallel
[Pipeline] [job-1] { (Branch: job-1)
[Pipeline] [job-2] { (Branch: job-2)
[Pipeline] [job-3] { (Branch: job-3)
[Pipeline] [job-1] build (Building job-1)
[job-1] Scheduling project: job-1
[Pipeline] [job-2] build (Building job-2)
[job-2] Scheduling project: job-2
[Pipeline] [job-3] build (Building job-3)
[job-3] Scheduling project: job-3
[job-1] Starting building: job-1 #2
[job-2] Starting building: job-2 #2
[Pipeline] [job-2] }
[job-3] Starting building: job-3 #2
[Pipeline] [job-1] }
[Pipeline] [job-3] }
[Pipeline] // parallel
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS