Search code examples
tfsazure-devopsvnext

Why one can set TFS predefined variables when they are said to be read-only?


According to https://learn.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=tfs-2018

These variables are automatically set by the system and read-only. (The exceptions are Build.Clean and System.Debug.)

Nonetheless, if one tries to create a vnext build with the following tasks

  1. Inline Powershell - Write-Host $env:BUILD_SOURCEVERSION
  2. Inline Powershell - Write-Host ("##vso[task.setvariable variable=build.sourceversion;]"+'someNewValue')
  3. Inline Powershell - Write-Host $env:BUILD_SOURCEVERSION

Task 2 won't fail, and the last task will output something like

2018-10-24T07:37:23.1232438Z someNewValue

instead of the expected original source version (the value printed in the first task).

So,

  1. Either I am misreading the docs / they are unclear on that account
  2. Or is it some genuine defect in TFS that one should pursue with MS?

Solution

  • That's expected behavior.

    The predefined variables are automatically set by the system and read-only.

    However 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.

    See Environment variables for details.

    So, in your scenario actually you defined a new pipeline variable with the same name as the pre-defined one, but not really overwrite the predefined variable. And they can only be used in the pipelines...


    UPDATE:

    Well, the documentation is somewhat misleading about the Environment Variables and makes some slightly contradictory claims about their readonlyness. Actually all variables (*predefined, build, environment...) basically work as the environment variables mentioned here.

    BTW, you can get all the available environment variables by get-childitem -path env:* in pipeline.*

    PowerShell script for example:

    $environmentVars = get-childitem -path env:*
    foreach($var in $environmentVars)
    {
     $keyname = $var.Key
     $keyvalue = $var.Value
    
     Write-Output "${keyname}: $keyvalue"
    }