Edit 1: In the original post I have a typo: inside step #4 I used compile-time expressions which is not correct of course, and in my original pipeline I am using template expressions. Sorry for the confusion – now YAML snippets in this post are identical to my pipeline. And yes, it’s still not working.
Screenshot of execution
Because of some reason, I have some trouble while using template expressions syntax (If-else statement especially) with variables that are imported from a template. Which broking all logic of my pipeline.
So, I have a quite simple ADO Yaml pipeline:
azure-pipelines.yml
parameters:
- name: applicationType
type: string
values:
- Backend
- Frontend
- Others
default: Backend
trigger: none
resources:
repositories:
- repository: Templates
type: git
name: Templates
variables:
- name: applicationType
value: ${{ parameters.applicationType }}
- template: vars/vars.yml@Templates
parameters:
varAppType:$(applicationType)
stages:
- stage: Test
jobs:
- job: Test
pool:
vmImage: ubuntu-latest
steps:
- bash: echo $(applicationType) #1
- ${{ if eq(variables.applicationType, 'Backend') }}: #2
- bash: echo "It is Backend"
- ${{ else }}:
- bash: echo "It is something different"
- bash: echo $(varAppType) #3
- ${{ if eq(variables.varAppType, 'Backend') }}: #4
- bash: echo "It is Backend"
- ${{ else }}:
- bash: echo "It is something different"
And here is the snippet of vars/vars.yml which located in Templates repo:
parameters:
- name: varAppType
default: ''
variables:
- name: varAppType
value: ${{ parameters.varAppType }}
Everything looks fine and straightforward, but here is what I see in logs during the run if I set applicationType as ‘Backend’:
#1 output: Backend
#2 output: It is Backend
#3 output: Backend
#4 output: It is something different
Because conditionals only work when used with template syntax I don’t even know what else I can try to do.
Its strange why ADO making such a difference between typical vars and imported from template ones, as I thought it should be working well because template syntax get processed at compile time, before runtime starts.
Maybe somebody knows how to fix this and what point I am missing with such a trivial task.
Any help would be appreciated, so thanks in advance.
2
Answers
For #4 you are using runtime expression (
$[]
), while for #2 – compile-time expression (${{}}
). Conditional insertion can work only with compile-time expressions, that’s why #4 is not working. More info about expressions: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devopsTo solve your problem you can try to change your pipeline in a way that you would use compile-time expressions or use
condition
field which is present in any step. In second option it would be possible to use runtime expressionsYou’re mixing different types of variables.
$(applicationType)
is macro syntax, which is evaluated at runtime. However, template parameters are resolved at compilation time. Thus,varAppType:$(applicationType)
should actually bevarAppType: ${{ variables.applicationType }}
(or more ideally,${{ parameters.applicationType }}
) so it can be resolved at compilation time.However, the mapping of parameters into variables that you’re doing is largely unnecessary. You can just reference the parameter directly as
${{ parameters.applicationType }}
throughout. As such, your entirevars.yml
template is unnecessary.Another best practices note:
What you’re doing here:
- bash: echo $(applicationType)
is potentially dangerous. Just like SQL injection, you’re taking an arbitrary string and injecting it directly into a script. This is called a script injection vulnerability.The better way to handle this is to map your parameter into an environment variable and reference it as an environment variable within your script, as follows: