Can Conditional Variable Assignment be Done in Azure Pipelines?
Asked Answered
H

7

75

Azure Pipelines has Expressions and Conditions, but I can find no way to assign one of two values to a variable, based on a condition.

Is there any way to accomplish what this pseudo-code would?

    ${{ if endsWith( variables['Build.SourceBranchName'], '/master' ) }}: 
      buildVersion: variables['mavenVersion']
    ${{ else }}: 
      buildVersion: variables['Build.SourceBranchName']
Health answered 16/8, 2019 at 23:27 Comment(1)
Now your yaml is valid :) learn.microsoft.com/en-us/azure/devops/release-notes/2021/…Adherence
D
12

This should do the trick....

BuildVersion is initialised as $(Build.SourceBranch) if it's the master branch you change that to the $(mavenVersion) else no change.

variables:
  mavenVersion: '1.0'
  buildVersion: $(Build.SourceBranch)

pool:
  vmImage: 'ubuntu-latest'

steps:

- script: echo '##vso[task.setvariable variable=buildVersion]$(mavenVersion)'
  displayName: "Set the buildVersion as mavenVersion if the Build.SourceBranch = 'refs/heads/master' "
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')

- script: echo $(buildVersion)
  displayName: 'Printing the variable'

non-master branches prints 'refs/heads/branch_name' which is mavenVersion non-master branches prints 'refs/heads/branch_name' which is mavenVersion

master branch prints 1.0 which is mavenVersion master branch prints 1.0 which is mavenVersion

Darien answered 17/8, 2019 at 0:18 Comment(3)
Thanks. That is a good answer, and I might be able to use that type of solution in the future. I neglected to mention that I need to use this variable to construct the build run name, so I need the variable before any steps are run. name: $(buildKey)_$(buildNum) # build run nameHealth
you could potentially have two builds which has triggers for branches. one with include and the other with exclude. not sure if that is what you are after..Darien
The code I posted, which goes in the variables section of the pipeline, solved my need for variables to use to define the build run name for the pipeline. Thanks.Health
B
71

As an extension to @Mike Murray's answer, if you are using variable groups you must define additional variables as name value pairs. To use conditional variable assignment in this case would be as follows:

variables:
- group: 'my-variable-group'
- name: myfirstadditionalvariable
  value: 100
- name: myconditionalvariable
  ${{ if eq( variables['Build.SourceBranchName'], 'master' ) }}: 
    value: masterBranchValue
  ${{ if ne( variables['Build.SourceBranchName'], 'master' ) }}: 
    value: featureBranchValue
Bragg answered 30/7, 2020 at 14:28 Comment(6)
Hello! This syntax gives me an Unexpected property ${{ if .... }} in Azure's online editor. When I save the file anyway and hit the Validate / Run button, I get a popup indicating 'value' is already defined 🤔Balanchine
Nevermind, my two conditions were evaluated to true, hence the error when validating / running. The online editor still gives me the warning but that's not a big deal.Balanchine
@Balanchine How did you fix 'value' is already defined? I am also using eq and ne and I don't understand how they are both evaluating to true.Dinesh
In my case, the conditions were more complex than the ones of this answer and I got mixed up. I've fixed the conditions so that they are mutually exclusive. How do your conditions look like?Balanchine
Thanks a lot! Was trying to figure out exactly this: how to use conditions with the name value syntax.United
@HeatherSawatsky in my case I fixed the " 'value' is already defined " error by adding a tab spacing before value: masterBranchValue. The yaml expected a +1 indentation level with reference to the previous sentenceSynge
H
50

I was closer than I thought. This is not pretty, but it worked. (with more yaml context)

variables:
  ${{ if eq( variables['Build.SourceBranchName'], 'master' ) }}: 
    buildVersion: ${{ variables['mavenVersion'] }}
  ${{ if ne( variables['Build.SourceBranchName'], 'master' ) }}: 
    buildVersion: ${{ variables['Build.SourceBranchName'] }}

  buildKey: ${{ format('{0}_{1}', variables['supportReleaseNumber'], variables['buildVersion']) }}
  buildNum: $[counter(variables['buildKey'], 1)]  # same as $(Rev:r), but more widely usable 

name: $(buildKey)_$(buildNum)  # build run name
Health answered 17/8, 2019 at 0:54 Comment(3)
Hi, I'm following your example and I got an error like Unexpected value 'env', which env is my variable to assign the value. I think it's because I'm using it with variable group so I can't use the example as it is. Do you have this IF ELSE expression(?) reference url that I can refer to my case?Fredella
The three docs links I included in the original post were all I could find related to this topic. There is no 'else', so you need to chain 'if's. Different variables types require different syntax. Check the Understand variable syntax section.Health
Thanks. I found if from templates section in the end. I was trying not to use template to simplify, so didn't know there was an explanation of if there.Fredella
A
16

With this update your YAML is valid:

    ${{ if endsWith( variables['Build.SourceBranchName'], '/master' ) }}: 
      buildVersion: variables['mavenVersion']
    ${{ else }}: 
      buildVersion: variables['Build.SourceBranchName']

All works fine with this

trigger: none

name: if-else

pool:
  vmImage: ubuntu-latest

variables:
  ${{ if endsWith( variables['Build.SourceBranchName'], 'master' ) }}: 
    buildVersion: 'master'
  ${{ else }}: 
    buildVersion: 'none-master'

steps:
- script: |
    echo "$(Build.SourceBranchName)"
    echo "$(buildVersion)"
  displayName: 'Display buildVersion'

Simply Build.SourceBranchName contains just master.

Generating script.
========================== Starting Command Output ===========================
/usr/bin/bash --noprofile --norc /home/vsts/work/_temp/1121efc8-6445-4e19-be5a-8d525a76467e.sh
master
master
Finishing: Display buildVersion

Note: This doesn't work on Azure DevOps Server - please be aware of that! Thanks @psulek for highlighting this!

Adherence answered 9/9, 2021 at 15:10 Comment(3)
Can you share a screenshot of this working so I can see precisely what is configured? I can't get it to work in my variables section.Swallowtailed
@Swallowtailed please check my edit.Adherence
this just does not work in Azure DevOps on promise, see github.com/MicrosoftDocs/azure-devops-docs/issues/…Mecke
D
12

This should do the trick....

BuildVersion is initialised as $(Build.SourceBranch) if it's the master branch you change that to the $(mavenVersion) else no change.

variables:
  mavenVersion: '1.0'
  buildVersion: $(Build.SourceBranch)

pool:
  vmImage: 'ubuntu-latest'

steps:

- script: echo '##vso[task.setvariable variable=buildVersion]$(mavenVersion)'
  displayName: "Set the buildVersion as mavenVersion if the Build.SourceBranch = 'refs/heads/master' "
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')

- script: echo $(buildVersion)
  displayName: 'Printing the variable'

non-master branches prints 'refs/heads/branch_name' which is mavenVersion non-master branches prints 'refs/heads/branch_name' which is mavenVersion

master branch prints 1.0 which is mavenVersion master branch prints 1.0 which is mavenVersion

Darien answered 17/8, 2019 at 0:18 Comment(3)
Thanks. That is a good answer, and I might be able to use that type of solution in the future. I neglected to mention that I need to use this variable to construct the build run name, so I need the variable before any steps are run. name: $(buildKey)_$(buildNum) # build run nameHealth
you could potentially have two builds which has triggers for branches. one with include and the other with exclude. not sure if that is what you are after..Darien
The code I posted, which goes in the variables section of the pipeline, solved my need for variables to use to define the build run name for the pipeline. Thanks.Health
T
3

@Mike Murray, thank you for this! I have been trying to solve this for ages. When builds are triggered from pull requests the SourceBranchName is always 'merge'. Your answer helped me come up with this solution for getting the target branch name for both scenarios, manual builds and builds triggered by pull-requests:

${{ if ne( variables['Build.SourceBranchName'], 'merge' ) }}: 
    environment: ${{ variables['Build.SourceBranchName'] }}
  ${{ if endsWith( variables['System.PullRequest.TargetBranch'], 'dev' ) }}: 
    environment: dev
  ${{ if endsWith( variables['System.PullRequest.TargetBranch'], 'staging' ) }}: 
    environment: staging
  ${{ if endsWith( variables['System.PullRequest.TargetBranch'], 'master' ) }}: 
    environment: prod

Not very pretty, but finally works.

Touraine answered 21/8, 2019 at 20:27 Comment(1)
This does not work. As shown on The docs of predefined variables, everything in System.PullRequest (except IsFork) is NOT available in template syntaxCochineal
M
3

You can have conditional variables based on parameters:

parameters:
- name: example
  default: master
  values:
  - master
  - branch1
  - branch2

variables:
  ${{ if eq( parameters.example, 'master' ) }}: 
    buildVersion: 'this'
  ${{ else }}: 
    buildVersion: 'that' # buildVersion = this

Won't work if the variables are in a separate template.

Mallee answered 6/7, 2022 at 4:27 Comment(2)
Any reason as to why the ${{ }} does not work in a separate template or another way to get around it?Mammet
Hey sorry for not responding earlier. It's because ${{ }} works at compile time.Mallee
C
2

In a template with parameters you are maybe tempted to try something like this (remark: variables in templates can be declared in jobs or stages):

variables:
  ${{ if eq( ${{parameters.Environment}}, 'DEV' ) }}: 
    targetenv: myDevMachine
  ${{ if eq( ${{parameters.Environment}}, 'TST' ) }}: 
    targetenv: myTSTMachine

Unfortunately that doesn't work. A workaround for that is to store the template variable first in a temporary variable like this:

variables:
  env: ${{parameters.Environment}} 
  ${{ if eq( variables.env, 'DEV' ) }}: 
    targetenv: myDevMachine
  ${{ if eq( variables.env, 'TST' ) }}: 
    targetenv: myTSTMachine
Comatulid answered 21/8, 2023 at 9:32 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.