Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell environment variable in Jenkins Pipeline gives `org.jenkinsci.plugins.workflow.cps.EnvActionImpl@1b69f5bb:VARIABLE_NAME`

Tags:

Has anyone run into a problem when using PowerShell in a Jenkins Pipeline, where when you try to pull in an environmental variable (e.g., $env:CHANGE_ID), it evaluates to something like this?

org.jenkinsci.plugins.workflow.cps.EnvActionImpl@1b69f5bb:VARIABLE_NAME

It looks like someone else was running into the same problem in this question, but I'm not sure that it was answered there (they show how to print all environment variables, but not how to get a specific one when toString is not implemented): Retrieve all properties of env in Jenkinsfile

My Jenkins pipeline file:

pipeline {
  agent {
    node {
      label 'jenkins_managed_windows'
    }
  }

  stages {
    stage('SonarQube Analysis') {
      steps {
        powershell "dotnet sonarscanner begin /k:project-key /d:sonar.branch.name=$env:BRANCH_NAME"
      }
    }

    stage('Build') {
      steps {
        powershell 'dotnet build'
      }
    }

    stage('SonarQube End') {
      steps {
        powershell 'dotnet sonarscanner end'
      }
    }
  }
}

The step with the environment variable gets run as:

dotnet sonarscanner begin /k:project-key /d:sonar.branch.name=org.jenkinsci.plugins.workflow.cps.EnvActionImpl@54ee3a8:BRANCH_NAME
Interestingly, if I use single quoting:
powershell 'dotnet sonarscanner begin /k:project-key /d:sonar.branch.name=$env:BRANCH_NAME'
It doesn't even evaluate the environment variable at all, and just gets run as:
dotnet sonarscanner begin /k:project-key /d:sonar.branch.name=$env:BRANCH_NAME
like image 684
olucafont6 Avatar asked Sep 03 '19 20:09

olucafont6


1 Answers

The syntax forms $env:BRANCH_NAME and the equivalent ${env:BRANCH_NAME} are PowerShell constructs, which means that in order to pass them through to PowerShell in an interpolating Groovy string ("..."), you must \-escape the $ character to prevent Groovy from interpreting the construct up front:

powershell "dotnet sonarscanner begin ... /d:sonar.branch.name=\$env:BRANCH_NAME"

That said, given that your command contains no Groovy variables that need to be interpolated (it's safe and more robust to let PowerShell reference environment variables), you can simply use a literal Groovy string, '...', where $ chars. destined for PowerShell need no escaping:

powershell 'dotnet sonarscanner begin ... /d:sonar.branch.name=$env:BRANCH_NAME'

As for what you tried:

"... $env:BRANCH_NAME" in an interpolating Groovy string causes Groovy to interpolate variable env (since it is preceded by $), and treat :BRANCH_NAME as a literal.

Since env refers to the object that contains all environment variables, what you're seeing is the (unhelpful) stringification of that object, which is the class name (org.jenkinsci.plugins.workflow.cps.EnvActionImpl) followed by an instance-specific hash code (@54ee3a8).

Using ${env.BRANCH_NAME} would have worked - given that the value of environment variable BRANCH_NAME can be accessed as a property of the env object - but note that this means that Groovy interpolates the value up front and that PowerShell then only sees the resulting value.

In simple cases (environment-variable values without whitespace or special characters), "${env.BRANCH_NAME}" (up-front interpolation by Groovy) and "\${env:BRANCH_NAME}" (later interpretation by PowerShell) are interchangeable, but only the latter approach works robustly with all values.

like image 174
mklement0 Avatar answered Nov 15 '22 05:11

mklement0