There is no bug in Workflow here beyond a lack of diagnosis for the mistake in the script. In Groovy, the loop counter i
is defined in an enclosing scope and mutated, so by the time each closure runs, it has the same value: 5. You can see this, as well as the concept behind the fix, outside Jenkins:
$ groovy -e 'def cs = []; for (int i = 0; i < 5; i++) {def j = i; cs += {println "${i} vs. ${j}"}}; for (c in cs) {c()}'
5 vs. 0
5 vs. 1
5 vs. 2
5 vs. 3
5 vs. 4
In your case, Jenkins saw five attempts to schedule the same downstream project with the same parameters, and coalesced them all into one queue item and thus one build. (Depending on timing, it might have started one downstream build before other build
steps even ran, in which case it would run a second downstream build, but generally it would be fewer than five total builds.)
This new test demonstrates that what you wanted to do is indeed possible; you just need to capture the current value of the loop variable in a new lexically-scoped variable outside the closure.
By the way
def cs = []; (0..4).each {i -> cs += {println i}}; cs*.call()
does work as expected from command-line Groovy, since there is no mutated loop variable. Unfortunately this syntax is not yet available in Workflow: JENKINS-26481
Beware that you should not be using a “dummy” parameter value to differentiate queue entries. While this may happen to work today, expect that behavior to be fixed, so that parameter values specified by build
which do not correspond to any parameter actually defined in the downstream project will either be skipped with a warning, or result in an error. If you think you need a dummy parameter, you are probably doing something else wrong, but it is impossible to advise what that is without any explanation of why you would want a downstream project to run multiple times with nothing in its input differentiating the builds.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…