Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create dynamically stages in a Jenkins pipeline?

I need to launch a dynamic set of tests in a declarative pipeline. For better visualization purposes, I'd like to create a stage for each test. Is there a way to do so?

The only way to create a stage I know is:

stage('foo') {
   ...
}

I've seen this example, but I it does not use declarative syntax.

like image 872
david.perez Avatar asked Mar 16 '17 14:03

david.perez


People also ask

Can a Jenkins stage have multiple steps?

Jenkins Pipeline allows you to compose multiple steps in an easy way that can help you model any sort of automation process. Think of a "step" like a single command which performs a single action. When a step succeeds it moves onto the next step. When a step fails to execute correctly the Pipeline will fail.

How do you parameterize Jenkins pipeline?

Any Jenkins job or pipeline can be parameterized. All we need to do is check the box on the General settings tab, “This project is parameterized”: Then we click the Add Parameter button.

What are the 3 types of pipelines in Jenkins?

Declarative versus Scripted Pipeline syntax Declarative and Scripted Pipelines are constructed fundamentally differently. Declarative Pipeline is a more recent feature of Jenkins Pipeline which: provides richer syntactical features over Scripted Pipeline syntax, and.

How does Jenkins pipeline define stages?

A node block is used in scripted pipeline syntax. Stage: This block contains a series of steps in a pipeline. i.e., build, test, and deploy processes all come together in a stage. Generally, a stage block visualizes the Jenkins pipeline process.


3 Answers

Use the scripted syntax that allows more flexibility than the declarative syntax, even though the declarative is more documented and recommended.

For example stages can be created in a loop:

def tests = params.Tests.split(',')
for (int i = 0; i < tests.length; i++) {
    stage("Test ${tests[i]}") {
        sh '....'
    }
}
like image 79
david.perez Avatar answered Oct 05 '22 13:10

david.perez


As JamesD suggested, you may create stages dynamically (but they will be sequential) like that:

def list
pipeline {
    agent none
    options {buildDiscarder(logRotator(daysToKeepStr: '7', numToKeepStr: '1'))}
    stages {
        stage('Create List') {
            agent {node 'nodename'}
            steps {
                script {
                    // you may create your list here, lets say reading from a file after checkout
                    list = ["Test-1", "Test-2", "Test-3", "Test-4", "Test-5"]
                }
            }
            post {
                cleanup {
                    cleanWs()
                }
            }
        }
        stage('Dynamic Stages') {
            agent {node 'nodename'}
            steps {
                script {
                    for(int i=0; i < list.size(); i++) {
                        stage(list[i]){
                            echo "Element: $i"
                        }
                    }
                }
            }
            post {
                cleanup {
                    cleanWs()
                }
            }
        }
    }
}

That will result in: dynamic-sequential-stages

like image 29
Anton Yurchenko Avatar answered Oct 05 '22 13:10

Anton Yurchenko


@Jorge Machado: Because I cannot comment I had to post it as an answer. I've solved it recently. I hope it'll help you.

Declarative pipeline:

A simple static example:

stage('Dynamic') {
        steps {
            script {
                stage('NewOne') {

                        echo('new one echo')

                }
            }
        }
    }

Dynamic real-life example:

    // in a declarative pipeline
        stage('Trigger Building') {
              when {
                environment(name: 'DO_BUILD_PACKAGES', value: 'true')
              }
              steps {
                executeModuleScripts('build') // local method, see at the end of this script
              }
            }


    // at the end of the file or in a shared library
        void executeModuleScripts(String operation) {

          def allModules = ['module1', 'module2', 'module3', 'module4', 'module11']

          allModules.each { module ->  
          String action = "${operation}:${module}"  

          echo("---- ${action.toUpperCase()} ----")        
          String command = "npm run ${action} -ddd"                   

            // here is the trick           
            script {
              stage(module) {
                bat(command)
              }
            }
          }

}
like image 24
BuckTheBug Avatar answered Oct 05 '22 11:10

BuckTheBug