More on when Azure DevOps variables are available in pipeline runs
Introduction
I have previously blogged a good deal on Azure DevOps variable evaluation, see here and here, but the saga continues…
When variables exist
Today I realised, something I guess should have been obvious, that when you manually queue a run, pre-defined variables such as $(Build.SourceBranchName)
are not available until the pipeline is compiled and starts running. This is because though there is a value in UI branch combo but this value is not in $(Build.SourceBranchName)
until the pipeline starts running.
This would seem unimportant, and it is, except in the case when you are manually picking which stages to run via the run pipeline dialog. Only stages that have no conditional expressions, or ones where the $(Build.SourceBranchName)
name is empty are shown in the list of stages to run.
Updated 22 July 2024 - Rik Hepworth pointed out to me that a good use of the Stage Picker UI is to do a ‘richer’ validation of the YAML pipeline.
This is useful as though the Azure DevOps UI does a validation of any YAML edits, it only shows compile time issues, mostly typos and indenting issues, it does not validate any runtime values.
Rik’s suggested that he had found loading the Stage Picker UI is a good way to do further validation of “some of the runtime values”. This is a good suggestion, it is not perfect validation, but allows you to do a bit more checking before queuing a run.
trigger: none
pool:
vmImage: ubuntu-latest
stages:
- stage: No_Conditions
jobs:
- job: Job1
steps:
- script: echo 'Running on $(Build.SourceBranchName)'
- ${{ if eq(variables['Build.SourceBranchName'], 'main') }}:
- stage: BranchName_is_main
jobs:
- job: Job2
steps:
- script: echo 'Running on $(Build.SourceBranchName)'
- ${{ if or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], '')) }}:
- stage: BanchName_is_main_or_empty
jobs:
- job: Job3
steps:
- script: echo 'Running on $(Build.SourceBranchName)'
- stage: Using_Conditions
condition: eq(variables['Build.SourceBranchName'], 'main')
jobs:
- job: Job4
steps:
- script: echo 'Running on $(Build.SourceBranchName)'
Remember if you wish to if a
{
expression to actually filter on a branch name you need to use an{if }} Or
to handle both the UI and runtime conditions
Basically, you cannot rely on the value of Build.SourceBranchName
and -{
expressions to trim the list of available stages in the run build UI. In my opinion, best to avoid even trying to do this.
What can I do with conditions?
If you want to be able to pick the stages to run in the UI, and need checks against items like branch names, the simple answer is to use conditions on the stages. These are only evaluated at the moment the stage is started, unlike expressions which are evaluated when the run is queued.
But how can we give users an indication of what will be run, or not, as soon as the run is started as opposed to only finding out as it completes?
Variables and expressions are the answer here. Using expressions we can set a variable based on the branch name at queue time. This can be used in a displayname for the stage so in the UI it shows if a stage will be run or not
variables:
- ${{ if eq(variables['Build.SourceBranchName'], 'main') }}:
- name: willdeployToProdString
value: Yes
- ${{ if ne(variables['Build.SourceBranchName'], 'main') }}:
- name: willdeployToProdString
value: No
stages:
# other stages shown above left of for clarity of the example
- stage: Using_Conditions
displayName: Will deploy ${{variables.willdeployToProdString}}
condition: eq(variables['Build.SourceBranchName'], 'main')
jobs:
- job: Job4
steps:
- script: echo 'Running on $(Build.SourceBranchName)'
Remember if you are skipping steps with conditions, you may need to set the
condition
on subsequent stages to run. The default (if no condition is set) is to only run on success of the previous stage. See the official docs for more details on your options
Conclusion
As I have written about before, use compile time expressions in Azure DevOps Pipelines with care, their evaluation can get complex.
So a bit of a niche blog post, hope it is of use to someone
For the original version of this post see Richard Fennell's personal blog at More on when Azure DevOps variables are available in pipeline runs