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

Declarative pipeline functions cannot access defined environment variables from environment block

    XMLWordPrintable

    Details

    • Similar Issues:

      Description

      Functions that are called from within the environment block do not have access to environment variables that are defined previously in the same environment block. Parameters work as expected and accessing the function outside of the environment block works as expected.

      Example pipeline that exhibits the null environment variable function

      #!/usr/bin/env groovy
      
      def returnEnvVar() {
        env.VARIABLE
      }
      
      pipeline {
          environment {
            VARIABLE = "I'm set"
            COPY_VARIABLE = returnEnvVar() // this gets set to null
          }
          stages {
              stage('Print Environment') {
                  steps {
                      echo "${VARIABLE}"
                      echo "${COPY_VARIABLE}" // this prints out null
                  }
              }
          }
      }

        Attachments

          Activity

          Hide
          abayer Andrew Bayer added a comment -

          Yeah, that's expected - environment variable resolution is an annoyingly complicated thing, but the gist is that we resolve the values before any of them are added to env, and then add all of them to env together. You can reference one variable in another (i.e., in this case, COPY_VARIABLE = VARIABLE would work) because the resolution process knows to look for references to one of the variables in the value for another, but the referenced variable has to be referenced explicitly, not indirectly via a method.

          Show
          abayer Andrew Bayer added a comment - Yeah, that's expected - environment variable resolution is an annoyingly complicated thing, but the gist is that we resolve the values before any of them are added to env , and then add all of them to env together. You can reference one variable in another (i.e., in this case, COPY_VARIABLE = VARIABLE would work) because the resolution process knows to look for references to one of the variables in the value for another, but the referenced variable has to be referenced explicitly, not indirectly via a method.
          Hide
          brianskarda Brian Skarda added a comment -

          Ah, interesting. Thanks for the explanation Andrew. Is variable resolution documented anywhere or could I open a PR to add declarative pipeline variable resolution into one of the documentation sources?

          Show
          brianskarda Brian Skarda added a comment - Ah, interesting. Thanks for the explanation Andrew. Is variable resolution documented anywhere or could I open a PR to add declarative pipeline variable resolution into one of the documentation sources?
          Hide
          wyvern8 Andrew Vaughan added a comment -

          This sounds somewhat related to an issue i am seeing.   Perhaps you can advise Andrew Bayer?

          I want to call some shell commands to set env vars based on other env vars, and when they are cross-referenced, they appear to get re-evaluated.   Here is a basic example just using uuidgen - the use case is that the command setting SHARED_VALUE is not idempotent:

          pipeline {
              agent any
              environment {        
                  // SHARED_VALUE is re-evaluated each time it is referenced below
                  SHARED_VALUE = sh(returnStdout: true, script: """uuidgen""").trim()        
                  TEST_ONE = sh(returnStdout: true, script: """echo '${SHARED_VALUE}' """).trim()
                  TEST_TWO = sh(returnStdout: true, script: """echo '${SHARED_VALUE}' """).trim()
                  TEST_THR = sh(returnStdout: true, script: """echo '${SHARED_VALUE}' """).trim()    
              }    
          
              stages {        
                  stage('Test') {            
                      steps {                
                          echo "JUST TESTING"                
                          // each of these are different UUIDs
                          sh '''                    
                              echo "ONE = $TEST_ONE"
                              echo "TWO = $TEST_TWO"
                              echo "THR = $TEST_THR"                
                          '''               
                       }
                  }   
              }   
          }
          

          Is this expected behaviour?  i have not found a workaround, so have reverted to a bash script in the step instead.

          Show
          wyvern8 Andrew Vaughan added a comment - This sounds somewhat related to an issue i am seeing.   Perhaps you can advise Andrew Bayer ? I want to call some shell commands to set env vars based on other env vars, and when they are cross-referenced, they appear to get re-evaluated.   Here is a basic example just using uuidgen - the use case is that the command setting SHARED_VALUE is not idempotent: pipeline { agent any environment { // SHARED_VALUE is re-evaluated each time it is referenced below SHARED_VALUE = sh(returnStdout: true , script: """uuidgen" "").trim() TEST_ONE = sh(returnStdout: true , script: """echo '${SHARED_VALUE}' " "").trim() TEST_TWO = sh(returnStdout: true , script: """echo '${SHARED_VALUE}' " "").trim() TEST_THR = sh(returnStdout: true , script: """echo '${SHARED_VALUE}' " "").trim() } stages { stage( 'Test' ) { steps { echo "JUST TESTING" // each of these are different UUIDs sh ''' echo "ONE = $TEST_ONE" echo "TWO = $TEST_TWO" echo "THR = $TEST_THR" ''' } } } } Is this expected behaviour?  i have not found a workaround, so have reverted to a bash script in the step instead.

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            brianskarda Brian Skarda
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated: