Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-46762

Parallel stages don't honor agent { label ("label_name") } set at the top level of a pipeline

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not A Defect
    • Icon: Critical Critical
    • None
    • Declarative - 1.2

      Summary:
      Stages executed in parallel, via the new parallel stage execution feature being worked on for Declarative 1.2, don't honor a globally-set agent label like this one:

      agent {
          label ("linux")
      }
      

      This means that if you have >1 connected agent, and one of them isn't able to perform the steps required of it, the pipeline will fail. For instance, a Windows agent being incorrectly called upon to run UNIX shell steps.

      Prerequisites:
      1. One Linux agent, connected to Jenkins, with an agent label of linux:

      2. One Windows agent, connected to Jenkins, with an agent label of windows

      3. This can be recreated either with a Jenkinsfile checked into a repo somewhere, or as an inline job created on box.

      Steps to recreate:
      1. Create a Declarative Pipeline that includes an agent section limiting execution to agents which have the label linux. I'll attach the entire Jenkinsfile as well.

      pipeline {
          parameters {
              string(name:'SIZE_OF_GIBBERISH_FILE', defaultValue: '1000', description: 'Set the size of your gibberish file here')
          }
      
          // We should never run on the windows agent, but we do.
          agent {
              label ("linux")
          }
      
          options {
              timestamps()
          }
      
          triggers {
              // This should cause us to poll GitHub every 5 minutes.
              pollSCM('*/5 * * * *')
          }
      
          tools {
              jdk 'jdk8'
          }
      
          stages {
              stage ('Parallel Wrapper') {  // start of parallel wrapper
                  parallel {
                      stage('-P1-') {
                          steps {
                              echo "--> SIZE_OF_GIBBERISH_FILE is ${params.SIZE_OF_GIBBERISH_FILE}"
                              script {
                                  int randomFileSize = "${params.SIZE_OF_GIBBERISH_FILE}"
                                  for (int i = 0; i < 5; i++) {
      
                                      stage ("LP1 Stage $i") {
                                          for (int j = 0; j < 5; j++) {
                                              node {
                                                  sh "for i in `seq 1 100`; do cat /dev/urandom | env LC_CTYPE=c tr -dc \'[:alpha:]\' | head -c $randomFileSize; done"
                                              }
                                          }
                                      }
                                  }
                              }                        
                          }
                      }
                      stage('-P2-') {
                          steps {
                              echo "--> SIZE_OF_GIBBERISH_FILE is ${params.SIZE_OF_GIBBERISH_FILE}"
                              script {
                                  int randomFileSize = "${params.SIZE_OF_GIBBERISH_FILE}"
                                  for (int i = 0; i < 5; i++) {
      
                                      stage ("LP1 Stage $i") {
                                          for (int j = 0; j < 5; j++) {
                                              node {
                                                  sh "for i in `seq 1 100`; do cat /dev/urandom | env LC_CTYPE=c tr -dc \'[:alpha:]\' | head -c $randomFileSize; done"
                                              }
                                          }
                                      }
                                  }
                              }                        
                          }
      
                      }
                      stage('-P3-') {
                          steps {
                              echo "--> SIZE_OF_GIBBERISH_FILE is ${params.SIZE_OF_GIBBERISH_FILE}"
                              script {
                                  int randomFileSize = "${params.SIZE_OF_GIBBERISH_FILE}"
                                  for (int i = 0; i < 5; i++) {
      
                                      stage ("LP3 Stage $i") {
                                          for (int j = 0; j < 5; j++) {
                                              node {
                                                  sh "for i in `seq 1 100`; do cat /dev/urandom | env LC_CTYPE=c tr -dc \'[:alpha:]\' | head -c $randomFileSize; done"
                                              }
                                          }
                                      }
                                  }
                              }
                          }
                      }
                      stage('-P4-') {
                          steps {
                              echo "--> SIZE_OF_GIBBERISH_FILE is ${params.SIZE_OF_GIBBERISH_FILE}"
                              script {
                                  int randomFileSize = "${params.SIZE_OF_GIBBERISH_FILE}"
                                  for (int i = 0; i < 5; i++) {
      
                                      stage ("LP4 Stage $i") {
                                          for (int j = 0; j < 5; j++) {
                                              node {
                                                  sh "for i in `seq 1 100`; do cat /dev/urandom | env LC_CTYPE=c tr -dc \'[:alpha:]\' | head -c $randomFileSize; done"
                                              }
                                          }
                                      }
                                  }
                              }                        
                          }
                      }
      
                      stage('-P5-') {
                          steps {
                              echo "--> SIZE_OF_GIBBERISH_FILE is ${env.SIZE_OF_GIBBERISH_FILE}"
                              script {
                                  int randomFileSize = "${params.SIZE_OF_GIBBERISH_FILE}"
                                  for (int i = 0; i < 5; i++) {
      
                                      stage ("LP5 Stage $i") {
                                          for (int j = 0; j < 5; j++) {
                                              node {
                                                  sh "for i in `seq 1 100`; do cat /dev/urandom | env LC_CTYPE=c tr -dc \'[:alpha:]\' | head -c $randomFileSize; done"
                                              }
                                          }
                                      }
                                  }
                              }                        
                          }
                      }
                  } // end of parallel
              } // end of wrapper stage
          } // end stages
          post {
              always {
                  echo "ALWAYS --> Runs all the time."
                  deleteDir()
              }
              success {
                  echo "SUCCESS --> Whatever we did, it worked. Yay!"
              }
              failure {
                  echo "FAILURE --> Failed. Womp womp."
              }
              unstable {
                  echo "UNSTABLE --> Something fishy."
              }
              changed {
                  echo "CHANGED --> This result is different than build n-1"
              }
          }
      
       }
      

      2. Run the Pipeline. Notice that in stage view, some of our parallel stages are failing, because we're trying to run something in C:\jenkins\workspace\blah..., and that's not going to work, because it's trying to run shell steps that aren't possible on the windows box.

      3. As a proof, temporarily disable the Windows agent...

      ...and run the job again, and it will work. We'll set the NaN problem in Stage View aside for another day:

      There's a sample log attached from one of the failed attempts. This one was from a Jenkinsfile stored in a GH repo, but the failure is the same.

            abayer Andrew Bayer
            kshultz Karl Shultz
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: