ZDunker
ZDunker

Reputation: 467

Jenkins Pipeline - Iteration on stage level

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

Answers (2)

haridsv
haridsv

Reputation: 9693

OP was in the right direction, but there are a few issues with the code:

  • The code to create dynamic stages needs to be in a script block.
  • You need at least one stage with steps so that you can put the above logic
  • You don't need steps inside a dynamic stage (probably because it is in script block, which means it is no longer declarative).
  • The value passed to stage name has a syntax error, it is probably a typo

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:

Pipeline view

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

lvthillo
lvthillo

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

Related Questions