Reputation: 467
I've been reaching to a point that I really want to use iteration to save redundant code on stage level when building multi-platforms. Below is showcasing what I'm trying to do:
def map = [
Bob : 42,
Alice: 54,
Max : 33
]
pipeline {
agent none
stages {
map.each { entry ->
stage ($entry.key) {
steps{
timestamps{
echo "$entry.value"
}
}
}
}
}
}
I think the concept here is pretty straight forward, but the builds are failing by telling me:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 13: Expected a stage @ line 13, column 9.
map.each { entry ->
^
WorkflowScript: 12: No stages specified @ line 12, column 5.
stages {
^
2 errors
Does this mean jenkins have not yet support user to iterate on stages? If there's anything wrong with what I did, please let me know. Thanks!
-----EDIT------
BTW, @NonCPS is also tried, I don't think this is a each
problem in pipeline script...
def map = [
Bob : 42,
Alice: 54,
Max : 33
]
pipeline {
agent none
stages {
iter_stages map
}
}
@NonCPS
def iter_stages(dd) {
dd.each { entry ->
stage ($entry.key) {
steps{
timestamps{
echo "$entry.value"
}
}
}
}
}
Upvotes: 5
Views: 15049
Reputation: 9693
OP was in the right direction, but there are a few issues with the code:
script
block.steps
inside a dynamic stage (probably because it is in script
block, which means it is no longer declarative).Here is the code that works the way the OP wants:
def map = [
Bob : 42,
Alice: 54,
Max : 33
]
pipeline {
agent any
stages {
stage('Initialize') {
steps {
script {
map.each { entry ->
stage (entry.key) {
timestamps{
echo "$entry.value"
}
}
}
}
}
}
}
}
Here is how the pipeline will look like:
Since this is so dynamic anyway, it should probably use the scripted pipeline syntax instead of the above (which is declarative pipeline), which also makes it possible to avoid the Initialize
stage.
def map = [
Bob : 42,
Alice: 54,
Max : 33
]
node {
map.each { entry ->
stage (entry.key) {
timestamps{
echo "$entry.value"
}
}
}
}
Upvotes: 19
Reputation: 30851
I think this can help you. I don't really know why you want to iterate on stages and not just iterate your function inside a step of a stage:
def map = [
Bob : 42,
Alice: 54,
Max : 33
]
pipeline {
agent any
stages {
stage('loop') {
steps {
loopNames(map)
}
}
}
}
def loopNames(map){
map.each {
key, value -> println "Age of " + key + " is " + value + ".";
}
}
Call a groovy function
in your pipeline and pass map
as parameter.
Below the pipeline I define the content of the function.
Output of this run:
[Pipeline] {
[Pipeline] stage
[Pipeline] { (loop)
[Pipeline] echo
Age of Bob is 42.
[Pipeline] echo
Age of Alice is 54.
[Pipeline] echo
Age of Max is 33.
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Upvotes: 1