Search code examples
jenkinsjenkins-pipelinepipelinejenkins-groovy

How to run a Jenkins pipeline multiple times, based on the multiple/different parameters. (Please refer the description for more details)


I have a string parameter used in pipeline. names="name1,name2" (In a single textbox, User will enter the names separated by commas)

I am converting this string to list using tokenize method. After this, list will have [name1, name2]

I have a pipeline script with 3 stages (Build, Test, Deploy). In above case, there are only 2 names. so, this pipeline should be executed for 2 times. Similarly, based on how many names we are passing, the pipeline should run that many times.

You will get some idea about what i am actually asking, after seeing the below code.

//Getting values using String Parameter in Jenkins. "name1, name2" is entered for "NAMES" as input
//Tokenize will turn "name1, name2" to [name1, name2]

namesList = params.NAMES.tokenize(',') 

for(name in namesList){
     .......
     //Pipeline should be triggered using 'name1' and 'name2', either one by one or parallel.   

}
pipeline{
   agent any
   stages{
      stage('build'){
         steps{
            sh 'curl https://abc.xyz/'+ name +'/sample'   //name should be passed to run this command
         }
      }
      stage('test'){
         ......
      }
      stage('deploy'){
         ......
      }
}

1st iteration: name1 should be passed to pipeline.

2nd iteration: name2 should be passed to pipeline.

Execution can by either one by one or parallel. Both answers are welcomed.


Solution

  • Unfortunately, as far as I know, this can not be done with declarative pipeline, because there is no way to have dynamic stages and/or parallel branches (I've got no source for this fact, but as far as I can tell from the documentation and implementation, it doesn't see to be possible). Fortunately, scripted pipeline is much more dynamic and is able to facilitate what you need. The following code should work as desired:

    def namesList = params.NAMES.tokenize(',')
    
    def parts = [:]
    namesList.each { name ->
        parts[name] = {
            stage('build'){
                echo "build for ${name}"
            }
            stage('test'){
                echo "test for ${name}"
            }
            stage('deploy'){
                echo "deploy for ${name}"
            }
        }
    }
    parallel parts
    

    The code is very simple, we tokenize the input parameter, declare a map to store the different branches. Loop through the names, and for each name we assign an element in the branch with a closure defining the steps for the flow. Then we execute the branches using parallel step.

    Edit 2019-11-25 The recently added matrix directive (in beta right now) could solve your problems. I haven't tried it out, but if it is possible to reference parameters in the axes section, then you could have a dynamic number of branches.