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

Environment variables can't be used in agent configuration

    XMLWordPrintable

Details

    Description

      If you try something like

      agent {
        label "${SOME_ENV_VAR}"
      }
      environment {
        SOME_ENV_VAR = "some-label"
      }
      

      You'll get an error due to SOME_ENV_VAR not existing in the binding. Not ideal, obviously, but I'm not sure if we can actually solve this without significant rewrites.

      Attachments

        Issue Links

          Activity

            allanlewis_youview Allan Lewis added a comment -

            I finally found a workaround for this:

            registry = 'my-registry'
            imageRepo = 'my-repo-name'
            
            def getImageName(def doCheckout = false) {
              def treeHash = node {
                if (doCheckout) checkout scm
                sh(script: 'git rev-parse HEAD:', returnStdout: true).trim()
              }
              "$registry/$imageRepo:$treeHash"
            }
            
            pipeline {
              agent {
                label 'docker-builder'
              }
            
              stages {
                stage('Build & Push Docker Image') {
                  steps {
                    script {
                      docker.build(getImageName()).push()
                    }
                  }
                }
                stage('Do Stuff') {
                  agent {
                    docker {
                      image getImageName(true)
                    }
                  }
                  steps {
                    sh 'echo hello'
                  }
                }
              }
            }
            
            allanlewis_youview Allan Lewis added a comment - I finally found a workaround for this: registry = 'my-registry' imageRepo = 'my-repo-name' def getImageName( def doCheckout = false ) { def treeHash = node { if (doCheckout) checkout scm sh(script: 'git rev-parse HEAD:' , returnStdout: true ).trim() } "$registry/$imageRepo:$treeHash" } pipeline { agent { label 'docker-builder' } stages { stage( 'Build & Push Docker Image' ) { steps { script { docker.build(getImageName()).push() } } } stage( 'Do Stuff' ) { agent { docker { image getImageName( true ) } } steps { sh 'echo hello' } } } }
            eplodn1 efo plo added a comment -

            Would also like to have this implemented.

             

            We need to dynamically assign a label based on branch, so that branches of Team A run on the resources of that team, etc. We contact Consul for the mapping of branch to label. Currently this is not possible as the label expression is evaluated before the pipeline is run, not at the beginning of the relevant step, so any changes to variables or environment do not affect the node where the step is run.

            eplodn1 efo plo added a comment - Would also like to have this implemented.   We need to dynamically assign a label based on branch, so that branches of Team A run on the resources of that team, etc. We contact Consul for the mapping of branch to label. Currently this is not possible as the label expression is evaluated before the pipeline is run, not at the beginning of the relevant step, so any changes to variables or environment do not affect the node where the step is run.
            datajack Jack P added a comment -

             I would like to bump interest in this as well recently got diverted here from posting a [similar question on stack overflow|https://stackoverflow.com/questions/55267427/how-can-i-use-different-private-docker-agents-based-on-parameter-in-jenkins-decl.]

             

            The solution seems to mean restarting the same environment between stages which feels a bit off and results in me having to merge stages that would be nice to keep separate.

            datajack Jack P added a comment -  I would like to bump interest in this as well recently got diverted here from posting a [similar question on stack overflow| https://stackoverflow.com/questions/55267427/how-can-i-use-different-private-docker-agents-based-on-parameter-in-jenkins-decl .]   The solution seems to mean restarting the same environment between stages which feels a bit off and results in me having to merge stages that would be nice to keep separate.
            eplodn1 efo plo added a comment -

            datajack We worked around this limitation by implementing a scripted pipeline before declarative:

            node('master') {
                stage('Choose Label') {
                    LABEL = 'my_desired_label' // script it anyway you want
                }
            }
            
            
            pipeline {
                agent {
                    node {
                        label "${LABEL}"
                    }
                }
            // etc.
            }
            
            eplodn1 efo plo added a comment - datajack We worked around this limitation by implementing a scripted pipeline before declarative: node( 'master' ) { stage( 'Choose Label' ) { LABEL = 'my_desired_label' // script it anyway you want } } pipeline { agent { node { label "${LABEL}" } } // etc. }
            datajack Jack P added a comment - - edited

            eplodn1 Thank you! I am eternally greatful. Totally works with docker and azure storage plugin, here's my stackoverflow example fixed as per yours.

             
             

            node('master') { 
             stage('Choose Label') { 
              URL_VAR = "${env.registrySelection == "PROD" ? "urlProd.azure.io" : "urlTest.azure.io"}" 
              CREDS_VAR = "${env.registrySelection == "PROD" ? "credsProd" : "credsTest"}" 
             } 
            } 
            pipeline { 
              parameters { 
                choice( 
                name: 'registrySelection', 
                choices: ['TEST', 'PROD'], 
                description: 'Is this a deployment to STAGING or PRODUCTION environment?' ) 
              } 
              agent { 
                docker { 
                  image "${URL_VAR}/image:tag" 
                  registryUrl "https://${URL_VAR}" registryCredentialsId "${CREDS_VAR}" 
                } 
              } 
              stages{ 
                stage('test'){ 
                  steps{ 
                    echo "${URL_VAR}" 
                    echo "${CREDS_VAR}" 
                  } 
                } 
              } 
            }

             

            datajack Jack P added a comment - - edited eplodn1 Thank you! I am eternally greatful. Totally works with docker and azure storage plugin, here's my stackoverflow example fixed as per yours.     node( 'master' ) { stage( 'Choose Label' ) { URL_VAR = "${env.registrySelection == " PROD " ? " urlProd.azure.io " : " urlTest.azure.io "}" CREDS_VAR = "${env.registrySelection == " PROD " ? " credsProd " : " credsTest "}" } } pipeline { parameters { choice( name: 'registrySelection' , choices: [ 'TEST' , 'PROD' ], description: 'Is this a deployment to STAGING or PRODUCTION environment?' ) } agent { docker { image "${URL_VAR}/image:tag" registryUrl "https: //${URL_VAR}" registryCredentialsId "${CREDS_VAR}" } } stages{ stage( 'test' ){ steps{ echo "${URL_VAR}" echo "${CREDS_VAR}" } } } }  

            People

              Unassigned Unassigned
              abayer Andrew Bayer
              Votes:
              22 Vote for this issue
              Watchers:
              33 Start watching this issue

              Dates

                Created:
                Updated: