Variables going down a pipe(line)

How to output all Environment Variables in Azure DevOps with PowerShell?

7 min read.

This article explains how to list all “Environment Variables” (that’s pipeline variables, job / stage variables, predefined variables and even local script variables that are mounted on to the agent as Environment Variables) using PowerShell in Azure DevOps.

Background

Azure DevOps provides a range of environment variables that can be accessed and utilized within your pipelines. These variables offer valuable information and configuration options to enhance the functionality of your tasks.

In addition to the built-in variables, there are a few ways to bring your own variables to the pipeline execution.

(Don’t want to read a long wall of text of me yammering about Azure DevOps, pipeline variables and PowerShell? Want to just get to the YAML? This is the TLDR-link you’ve been looking for 😅)

Understanding the types and purposes of these variables is crucial for effectively managing your pipeline processes. By leveraging PowerShell, you can easily output all available environment variables, gaining insight into the specific details that impact your pipeline execution.

Whether you are working with YAML pipelines or traditional build/release pipelines, having a clear understanding of the available environment variables empowers you to customize and optimize your DevOps processes efficiently.

However… That means you’ll have variables coming in from everywhere, and it’s not always clear which ones you can use where, and which ones you can overwrite and which ones you can’t.

Problem

Knowing which environment variables are available to you in an Azure DevOps pipeline can be tricky. The lack of clarity can lead to challenges in effectively configuring and executing your tasks. In this article I’ll stick to explaining where the variables come from, not which ones you can set and reuse in later stages (it’s more complicated than you’d think!)

Anyway – without a comprehensive understanding of the available variables, you may encounter difficulties in executing your scripts, choosing pipeline execution paths or even dynamically forming your pipeline from templates during runtime. Moreover, the uncertainty regarding whether your variables are properly mounted and their values updated can introduce errors and inconsistencies in your pipeline executions.

This can result in unexpected behavior, failed tasks, or incorrect outputs, ultimately impacting the reliability and efficiency of your DevOps workflows.

And that sucks. CI/CD environment is supposed to be nothing if not deterministic!

By addressing the problem of identifying and managing environment variables in Azure DevOps, you can enhance the stability and predictability of your pipeline operations. With the right approach and tools, such as PowerShell scripts, you can gain visibility into all relevant variables, ensuring that your pipeline runs smoothly and delivers the desired outcomes consistently.

Where do environment variables in Azure DevOps come from?

Determining the origin of each environment variable in an Azure DevOps pipeline can be a bit tricky, as the platform doesn’t provide a built-in method for tracing their sources. However, you can employ some strategies to infer where they might have come from:

  • Predefined Variables: Also called built-in variables, Azure DevOps has a set of system-defined variables that are always present. These are documented in the Azure DevOps documentation and are usually very reliable and stay the same between pipelines and environments.
  • Pipeline Variables: If you’ve defined variables in the pipeline settings, they can have a prefix you’ve set, which can help you identify them. And of course they’re available everywhere in your pipeline’s execution and always with the name you’ve set (unless you overwrite them… Which is a story for another time)
  • Job and Stage Variables: These are typically set in the YAML file and can be identified by their context in the pipeline configuration.
  • Script Variables: Variables created in scripts are “local” and usually managing them is comparably easy. Unless you export them (by setting their value to a “higher level” variable and use them later. Then it becomes a mess.

In addition to variables, you of course have parameters – but that’s beyond the scope of this article.

Solution

It’s pretty easy to output a complete list of variables used in your pipeline. By executing the PowerShell script within Azure DevOps pipelines, users can actively monitor and assess the variables employed during pipeline runs.

This customizable solution empowers users to optimize their pipeline management strategies and maximize the effective utilization of environment variables within Azure DevOps.

Here’s a snippet that does exactly that:

- powershell: |
    Write-Host "Listing all environment variables..."
    Get-ChildItem -Path Env: | ForEach-Object {
        Write-Host "$($_.Name) = $($_.Value)"
    }

(a more thorough example further down below)

This script iterates through all environment variables available in the current scope and prints them out in a Name = Value format. It’s a straightforward approach that gets the job done. The output will look somewhat like this (again, a longer example at the end):

Going Deeper

But what if you want to do more than just print them out? What if you need to manipulate or pass these variables on? That’s where the task.setvariable command comes into play1. It allows you to set variables within your scripts that can be used in subsequent tasks.

Here’s an example of setting a variable:

- powershell: |
    Write-Host "##vso[task.setvariable variable=myVar;]newValue"

And to output a variable for use in subsequent jobs or stages, you’d add the isOutput=true flag:

- powershell: |
    Write-Host "##vso[task.setvariable variable=myVar;isOutput=true]newValue"

Read this to read more about passing variables between different stages.

A full YAML pipeline

Below, you can see an example of a full YAML pipeline containing references to a Pipeline Variable Group (under “Library” in azure DevOps), which might, in turn, mount secrets from Azure Key Vault.

pool:
  vmImage: ubuntu-latest

jobs:
- job: testJob
  variables: 
  - group: Your.VariableGroup # this one comes from your Pipeline library
  - name: jobScopedVariable
    value: "Job-scoped test variable"

  steps:
  - powershell: |
      Write-Host "Listing all environment variables..."
      Get-ChildItem -Path Env: | ForEach-Object {
          Write-Host "$($_.Name) = $($_.Value)"
      }

Example output

Below, I have pasted an output from the pipeline above.

##[section]Starting: PowerShell
==============================================================================
Task         : PowerShell
Description  : Run a PowerShell script on Linux, macOS, or Windows
Version      : 2.237.5
Author       : Microsoft Corporation
Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/powershell
==============================================================================
Generating script.
========================== Starting Command Output ===========================
[command]/usr/bin/pwsh -NoLogo -NoProfile -NonInteractive -Command . '/home/vsts/work/_temp/03b7c4cb-9a36-4972-b713-cfb1229b5c7e.ps1'
Listing all environment variables...
ACCEPT_EULA = Y
ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE = /opt/actionarchivecache
AGENT_ACCEPTTEEEULA = True
AGENT_BUILDDIRECTORY = /home/vsts/work/1
AGENT_CLOUDID = 24bb6d69-8d6f-4611-ae24-3cb79c706fb0
AGENT_DISABLELOGPLUGIN_TESTFILEPUBLISHERPLUGIN = true
AGENT_DISABLELOGPLUGIN_TESTRESULTLOGPLUGIN = true
AGENT_ENABLE_PIPELINEARTIFACT_LARGE_CHUNK_SIZE = true
AGENT_HOMEDIRECTORY = /home/vsts/agents/3.236.1
AGENT_ID = 33
AGENT_ISSELFHOSTED = 0
AGENT_JOBNAME = testJob
AGENT_JOBSTATUS = Succeeded
AGENT_LOGTOBLOBSTORAGESERVICE = true
AGENT_MACHINENAME = fv-az365-422
AGENT_NAME = Azure Pipelines 2
AGENT_OS = Linux
AGENT_OSARCHITECTURE = X64
AGENT_READONLYVARIABLES = true
AGENT_RETAINDEFAULTENCODING = false
AGENT_ROOTDIRECTORY = /home/vsts/work
AGENT_TASKRESTRICTIONSENFORCEMENTMODE = Enabled
AGENT_TEMPDIRECTORY = /home/vsts/work/_temp
AGENT_TOOLSDIRECTORY = /opt/hostedtoolcache
AGENT_USEWORKSPACEID = true
AGENT_VERSION = 3.236.1
AGENT_WORKFOLDER = /home/vsts/work
agent.jobstatus = Succeeded
ANDROID_HOME = /usr/local/lib/android/sdk
ANDROID_NDK = /usr/local/lib/android/sdk/ndk/25.2.9519653
ANDROID_NDK_HOME = /usr/local/lib/android/sdk/ndk/25.2.9519653
ANDROID_NDK_LATEST_HOME = /usr/local/lib/android/sdk/ndk/26.2.11394342
ANDROID_NDK_ROOT = /usr/local/lib/android/sdk/ndk/25.2.9519653
ANDROID_SDK_ROOT = /usr/local/lib/android/sdk
ANT_HOME = /usr/share/ant
AZP_75787_ENABLE_COLLECT = true
AZP_75787_ENABLE_NEW_LOGIC = false
AZP_75787_ENABLE_NEW_LOGIC_LOG = false
AZP_75787_ENABLE_NEW_PH_LOGIC = true
AZP_AGENT_CHECK_FOR_TASK_DEPRECATION = true
AZP_AGENT_IGNORE_VSTSTASKLIB = true
AZP_AGENT_LOG_TASKNAME_IN_USERAGENT = true
AZP_AGENT_MOUNT_WORKSPACE = true
AZP_ENABLE_RESOURCE_UTILIZATION_WARNINGS = true
AZP_PS_ENABLE_INVOKE_PROCESS = true
AZURE_EXTENSION_DIR = /opt/az/azcliextensions
AZURE_HTTP_USER_AGENT = VSTS_d89ef291-b8d8-4b91-afbf-07c6c3150a0c_build_272_0
BOOTSTRAP_HASKELL_NONINTERACTIVE = 1
BUILD_ARTIFACTSTAGINGDIRECTORY = /home/vsts/work/1/a
BUILD_BINARIESDIRECTORY = /home/vsts/work/1/b
BUILD_BUILDID = 77531
BUILD_BUILDNUMBER = 20240408.2
BUILD_BUILDURI = vstfs:///Build/Build/77531
BUILD_CONTAINERID = 4664786
BUILD_DEFINITIONFOLDERPATH = \draft stuff
BUILD_DEFINITIONNAME = Test Pipeline
BUILD_DEFINITIONVERSION = 1
BUILD_QUEUEDBY = Microsoft.VisualStudio.Services.TFS
BUILD_QUEUEDBYID = 00000002-0000-8888-8000-000000000000
BUILD_REASON = IndividualCI
BUILD_REPOSITORY_CLEAN = False
BUILD_REPOSITORY_GIT_SUBMODULECHECKOUT = False
BUILD_REPOSITORY_ID = bf6403f4-0a9c-4593-bf97-b3fd0d25f52d
BUILD_REPOSITORY_LOCALPATH = /home/vsts/work/1/s
BUILD_REPOSITORY_NAME = Contoso Pipeline
BUILD_REPOSITORY_PROVIDER = TfsGit
BUILD_REPOSITORY_URI = https://[email protected]/contoso-source/Contoso%20Pipeline/_git/Contoso Pipeline
BUILD_REQUESTEDFOR = Antti Koskela
BUILD_REQUESTEDFOREMAIL = [email protected]
BUILD_REQUESTEDFORID = c2dd88bb-8ebb-6ef5-a2d4-cf77b7c888eb
BUILD_SOURCEBRANCH = refs/heads/dev
BUILD_SOURCEBRANCHNAME = dev
BUILD_SOURCESDIRECTORY = /home/vsts/work/1/s
BUILD_SOURCEVERSION = 1d217b4b462459a36f5f1323def4d6c4eaa2247b
BUILD_SOURCEVERSIONAUTHOR = Antti Koskela
BUILD_SOURCEVERSIONMESSAGE = No comment
BUILD_STAGINGDIRECTORY = /home/vsts/work/1/a
BUILDDEVINTENT = true
BUILDPRODINTENT = true
CHROME_BIN = /usr/bin/google-chrome
CHROMEWEBDRIVER = /usr/local/share/chromedriver-linux64
CLIENTID = Comes from a library or Azure Key Vault
COMMON_TESTRESULTSDIRECTORY = /home/vsts/work/1/TestResults
CONDA = /usr/share/miniconda
DEBIAN_FRONTEND = noninteractive
DOTNET_MULTILEVEL_LOOKUP = 0
DOTNET_NOLOGO = 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
EDGEWEBDRIVER = /usr/local/share/edge_driver
ENDPOINT_URL_SYSTEMVSSCONNECTION = https://dev.azure.com/contoso-source/
ENVIRONMENT = test
FAIL_DEPRECATED_BUILD_TASK = true
FAIL_DEPRECATED_TASK = true
FAIL_JOB_WHEN_AGENT_DIES = true
GECKOWEBDRIVER = /usr/local/share/gecko_driver
GHCUP_INSTALL_BASE_PREFIX = /usr/local
GIT_TERMINAL_PROMPT = 0
GOROOT_1_20_X64 = /opt/hostedtoolcache/go/1.20.14/x64
GOROOT_1_21_X64 = /opt/hostedtoolcache/go/1.21.8/x64
GOROOT_1_22_X64 = /opt/hostedtoolcache/go/1.22.1/x64
GRADLE_HOME = /usr/share/gradle-8.7
HOME = /home/vsts
HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS = 3650
HOMEBREW_NO_AUTO_UPDATE = 1
ImageOS = ubuntu22
ImageVersion = 20240403.1.0
INPUT_ARGUMENTS = 
INVOCATION_ID = 7c031a05f5ce4059999249a9bd57046c
JAVA_HOME = /usr/lib/jvm/temurin-11-jdk-amd64
JAVA_HOME_11_X64 = /usr/lib/jvm/temurin-11-jdk-amd64
JAVA_HOME_17_X64 = /usr/lib/jvm/temurin-17-jdk-amd64
JAVA_HOME_21_X64 = /usr/lib/jvm/temurin-21-jdk-amd64
JAVA_HOME_8_X64 = /usr/lib/jvm/temurin-8-jdk-amd64
JOBSCOPEDVARIABLE = Job-scoped test variable
JOURNAL_STREAM = 8:18038
LANG = C.UTF-8
LEIN_HOME = /usr/local/lib/lein
LEIN_JAR = /usr/local/lib/lein/self-installs/leiningen-2.11.2-standalone.jar
MSDEPLOY_HTTP_USER_AGENT = VSTS_d89ef291-b8d8-4b91-afbf-07c6c3150a0c_build_272_0
NVM_DIR = /home/vsts/.nvm
PATH = /opt/microsoft/powershell/7:/snap/bin:/home/vsts/.local/bin:/opt/pipx_bin:/home/vsts/.cargo/bin:/home/vsts/.config/composer/vendor/bin:/usr/local/.ghcup/bin:/home/vsts/.dotnet/tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
PIPELINE_REPOSITORY_NAME = Contoso Delivery
PIPELINE_WORKSPACE = /home/vsts/work/1
PIPX_BIN_DIR = /opt/pipx_bin
PIPX_HOME = /opt/pipx
POWERSHELL_DISTRIBUTION_CHANNEL = Azure-DevOps-ubuntu22
PSModulePath = /home/vsts/.local/share/powershell/Modules:/usr/local/share/powershell/Modules:/opt/microsoft/powershell/7/Modules
RESOURCES_TRIGGERINGALIAS = 
RESOURCES_TRIGGERINGCATEGORY = 
RUNNER_TOOLSDIRECTORY = /opt/hostedtoolcache
SELENIUM_JAR_PATH = /usr/share/java/selenium-server.jar
SGX_AESM_ADDR = 1
STATS_BLT = true
STATS_D = false
STATS_D_D = false
STATS_EXT = true
STATS_EXTP = https://provjobdsettingscdn.blob.core.windows.net/settings/provjobdsettings-0.5.172+1/provjobd.data
STATS_NM = true
STATS_RDCL = true
STATS_TIS = mining
STATS_TRP = true
STATS_UE = true
STATS_V3PS = true
STATS_VMD = true
STATS_VMFE = true
SWIFT_PATH = /usr/share/swift/usr/bin
SYSTEM = build
SYSTEM_ARTIFACTSDIRECTORY = /home/vsts/work/1/a
SYSTEM_COLLECTIONID = d89ef291-b8d8-4b91-afbf-07c6c3150a0c
SYSTEM_COLLECTIONURI = https://dev.azure.com/contoso-source/
SYSTEM_CULTURE = en-US
SYSTEM_DEFAULTWORKINGDIRECTORY = /home/vsts/work/1/s
SYSTEM_DEFINITIONID = 272
SYSTEM_DEFINITIONNAME = Contoso Delivery
SYSTEM_ENABLEACCESSTOKEN = SecretVariable
SYSTEM_HOSTTYPE = build
SYSTEM_ISAZUREVM = 1
SYSTEM_ISDOCKERCONTAINER = 0
SYSTEM_ISSCHEDULED = False
SYSTEM_JOBATTEMPT = 1
SYSTEM_JOBDISPLAYNAME = testJob
SYSTEM_JOBID = a4127350-4039-54ee-311c-0227a78ac3cb
SYSTEM_JOBIDENTIFIER = testJob.__default
SYSTEM_JOBNAME = __default
SYSTEM_JOBPARALLELISMTAG = Private
SYSTEM_JOBPOSITIONINPHASE = 1
SYSTEM_JOBTIMEOUT = 60
SYSTEM_PHASEATTEMPT = 1
SYSTEM_PHASEDISPLAYNAME = testJob
SYSTEM_PHASEID = 417a516f-ecb9-5237-4743-51f7a7814238
SYSTEM_PHASENAME = testJob
SYSTEM_PIPELINESTARTTIME = 2024-04-08 18:10:52+00:00
SYSTEM_PLANID = 76b1a9c5-3e68-4404-b4b0-294eacfec2e4
SYSTEM_POSTLINESSPEED = 10000
SYSTEM_PULLREQUEST_ISFORK = False
SYSTEM_SERVERTYPE = Hosted
SYSTEM_STAGEATTEMPT = 1
SYSTEM_STAGEDISPLAYNAME = __default
SYSTEM_STAGEID = 96ac2280-8cb4-5df5-99de-dd2da759617d
SYSTEM_STAGENAME = __default
SYSTEM_TASKDEFINITIONSURI = https://dev.azure.com/contoso-source/
SYSTEM_TASKDISPLAYNAME = PowerShell
SYSTEM_TASKINSTANCEID = a09ebd2c-769f-51f2-54b5-23276359f220
SYSTEM_TASKINSTANCENAME = PowerShell
SYSTEM_TEAMFOUNDATIONCOLLECTIONURI = https://dev.azure.com/contoso-source/
SYSTEM_TEAMFOUNDATIONSERVERURI = https://dev.azure.com/contoso-source/
SYSTEM_TEAMPROJECT = Contoso Delivery
SYSTEM_TEAMPROJECTID = 5ee8023f-d7f1-493a-b33e-b89f083a1c74
SYSTEM_TIMELINEID = 76b1a9c5-3e68-4404-b4b0-294eacfec2e4
SYSTEM_TOTALJOBSINPHASE = 1
SYSTEM_WORKFOLDER = /home/vsts/work
SYSTEMD_EXEC_PID = 591
TASK_DISPLAYNAME = PowerShell
TASK_PUBLISHTELEMETRY = True
TASK_SKIPTRANSLATORFORCHECKOUT = False
TF_BUILD = True
USE_GIT_LONG_PATHS = true
USE_MSAL = true
USE_MSDEPLOY_TOKEN_AUTH = true
USER = vsts
VCPKG_INSTALLATION_ROOT = /usr/local/share/vcpkg
VSTS_AGENT_PERFLOG = /home/vsts/perflog
VSTS_PROCESS_LOOKUP_ID = vsts_83cb3fd8-a0e1-4b61-914c-02a95f530b31
VSTSAGENT_CONTINUE_AFTER_CANCEL_PROCESSTREEKILL_ATTEMPT = true
VSTSAGENT_DOCKER_ACTION_RETRIES = true
XDG_CONFIG_HOME = /home/vsts/.config
XDG_RUNTIME_DIR = /run/user/1001

##[section]Finishing: PowerShell

That’s quite something, isn’t it?

References

mm
0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments