Azure Pipelines | TFS 2018 | TFS 2017 | TFS 2015
In Microsoft Team Foundation Server (TFS) 2018 and previous versions, build and release pipelines are called definitions, service connections are called service endpoints, stages are called environments, and jobs are called phases.
Variables give you a convenient way to get key bits of data into various parts of the pipeline. As the name suggests, the contents of a variable may change from run to run or job to job of your pipeline. Some variables are predefined by the system, and you are free to add your own as well.
Working with variables
Variables add a layer of indirection to your pipeline. Almost any place where a pipeline requires a text string or a number, you can use a variable instead of hard-coding a value. The system will replace the variable with its current value during the pipeline's execution.
Variable names consist of letters, numbers,
How you reference a variable depends on context.
The following table indicates how you can reference a variable called
Build.DefinitionName in each context.
|Version control tag applied by the build|| ||Learn about repository version control tagging.|
|Custom build number|| ||Learn about build number format options.|
|Designer input fields|| |
|YAML input fields|| |
|Windows batch script|| || Name is upper-cased, |
|PowerShell script|| |
|Bash script|| |
Some variables are automatically inserted by the system. As a pipeline author or end user, you cannot set the contents of such variables. See the comprehensive lists of build variables and release variables to learn which ones are available.
Secret variables such as System.AccessToken have special behavior. Secrets aren't available to scripts and tasks by default. You must explicitly allow secret variables on a pipeline-by-pipeline basis. This reduces the chances for a malicious script or task to steal the credentials they contain.
In YAML, you must explicitly map System.AccessToken into the pipeline using a variable. You can do this at the step or task level:
steps: - bash: echo This is a script that could use $SYSTEM_ACCESSTOKEN env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) - powershell: Write-Host "This is a script that could use $env:SYSTEM_ACCESSTOKEN" env: SYSTEM_ACCESSTOKEN: $(System.AccessToken)
Some build templates automatically create variables for you.
For example, when you create a new .NET app build,
BuildPlatform are automatically defined for you.
You are free to define additional variables in your pipelines.
Both of these are considered user-defined variables.
YAML builds can have variables defined at the pipeline or job level. They can also access variables defined when the build is queued.
# Set variables once variables: configuration: debug platform: x64 steps: # Build solution 1 - task: MSBuild@1 inputs: solution: solution1.sln configuration: $(configuration) # Use the variable platform: $(platform) # Build solution 2 - task: MSBuild@1 inputs: solution: solution2.sln configuration: $(configuration) # Use the variable platform: $(platform)
Parameters to YAML statements
To use a variable in a YAML statement, wrap it in
$(). For example:
pool: vmImage: 'ubuntu-16.04' steps: - script: ls workingDirectory: $(agent.homeDirectory)
To use a variables in a script, use environment variable syntax. Replace
_, capitalize the letters, and then use your platform's syntax for
referencing environment variables.
variables: MY_CUSTOM: MyValue jobs: - job: LinuxOrMacOS pool: vmImage: 'ubuntu-16.04' steps: - bash: echo $AGENT_HOMEDIRECTORY - job: Windows pool: vmImage: 'vs2017-win2016' steps: - script: echo %AGENT_HOMEDIRECTORY% - powershell: Write-Host $env:AGENT_HOMEDIRECTORY
You can create a counter that is automatically incremented by one in each execution of your pipeline. You can optionally provide a seed value for the counter if you need to start at a specific number. The counter can be assigned to a variable and then referenced in task inputs or scripts as you would any other variable.
variables: major: 2 minor: 1 # creates a counter called versioncounter and seeds it at 100 and then assigns the value to a variable named patch. patch: $[counter('versioncounter', 100)] # use the patch variable as part of your pipeline naming scheme name: $(Date:yyyyMMdd).$(patch) pool: vmImage: 'ubuntu-16.04' steps: # use the variables as part of your versioning for your nuget package - script: | dotnet pack /p:PackageVersion=$(major).$(minor).$(patch)
Set a job-scoped variable from a script
To set a variable from a script, you use a command syntax and print to stdout. This does not update the environment variables, but it does make the new variable available to downstream steps within the same job.
pool: vmImage: 'ubuntu-16.04' steps: # Create a variable - script: | echo '##vso[task.setvariable variable=myVariable]abc123' # Print the variable - script: | echo my variable is $(myVariable)
Set an output (multi-job) variable
If you want to make a variable available to future jobs, you must mark it as
an output variable using
isOutput=true. Then you can map it into future
$ syntax and including the step name which set the variable.
jobs: # Set an output variable from job A - job: A pool: vmImage: 'vs2017-win2016' steps: - powershell: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the value" name: setvarStep - script: echo $(setvarStep.myOutputVar) name: echovar # Map the variable into job B - job: B dependsOn: A pool: vmImage: 'ubuntu-16.04' variables: myVarFromJobA: $[ dependencies.A.outputs['setvarStep.myOutputVar'] ] # map in the variable steps: - script: echo $(myVarFromJobA) name: echovar
jobs: # Set an output variable from a job with a matrix - job: A pool: vmImage: 'ubuntu-16.04' strategy: maxParallel: 2 matrix: debugJob: configuration: debug platform: x64 releaseJob: configuration: release platform: x64 steps: - script: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the $(configuration) value" name: setvarStep - script: echo $(setvarStep.myOutputVar) name: echovar # Map the variable from the debug job - job: B dependsOn: A pool: vmImage: 'ubuntu-16.04' variables: myVarFromJobADebug: $[ dependencies.A.outputs['debugJob.setvarStep.myOutputVar'] ] steps: - script: echo $(myVarFromJobADebug) name: echovar
jobs: # Set an output variable from a job with slicing - job: A pool: vmImage: 'ubuntu-16.04' parallel: 2 # Two slices steps: - script: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the slice $(system.jobPositionInPhase) value" name: setvarStep - script: echo $(setvarStep.myOutputVar) name: echovar # Map the variable from the job for the first slice - job: B dependsOn: A pool: vmImage: 'ubuntu-16.04' variables: myVarFromJobsA1: $[ dependencies.A.outputs['job1.setvarStep.myOutputVar'] ] steps: - script: "echo $(myVarFromJobsA1)" name: echovar
YAML builds are not yet supported on TFS.
We recommend that you make the variable Secret if it contains a password, keys, or some other kind of data that you need to avoid exposing.
TFS 2017.2, TFS 2017.3
TFS 2017 RTM
Important: By default with GitHub repositories, secret variables associated with your build pipeline are not made available to pull request builds of forks. See Validate contributions from forks.
Secret variables are encrypted at rest with a 2048-bit RSA key. They are automatically masked out of any log output from the pipeline. Unlike a normal variable, they are not automatically decrypted into environment variables for scripts. You can explicitly map them in, though:
steps: # Create a secret variable - powershell: | Write-Host '##vso[task.setvariable variable=mySecret;issecret=true]abc' # Attempt to output the value in various ways - powershell: | # Using an input-macro: Write-Host "This works: $(mySecret)" # Using the env var directly: Write-Host "This does not work: $env:MYSECRET" # Using the mapped env var: Write-Host "This works: $env:MY_MAPPED_ENV_VAR" env: MY_MAPPED_ENV_VAR: $(mySecret)
The output from the above script would look like this:
This works: *** This does not work: This works: ***
YAML builds are not yet available on TFS.
Allow at queue time
You can choose which variables are allowed to be set at queue time and which are fixed by the pipeline author.
If a variable appears in the
variables block of a YAML file, it is fixed and cannot be overridden at queue time.
To allow a variable to be set at queue time, make sure it doesn't appear in the
variables block of a pipeline or job.
You can also pass environment variables from the agent host into build tasks. For example, on the Build tab of a build pipeline, add this task:
|Utility: Command Line||Tool:
If you have defined a pipeline variable of the same name as an environment variable (for example,
PATH), your pipeline variable value overrides the agent host's environment variable.
Q & A
What are the predefined release variables?
Do I need an agent?
You need at least one agent to run your build or release. Get an agent for Linux, macOS, or Windows.
I can't select a default agent pool and I can't queue my build or release. How do I fix this?
See Agent pools.