After using Azure DevOps YAML Pipelines for a few years it took me an embarrassingly long time to realise that it wasn’t possible to set demands when manually queueing a pipeline like it was when queueing a classic pipeline, this change kind-of made sense to me as everything should be declared in code right? Well variables can be declared at runtime and declared within YAML just like they could with classic pipelines so the change to demands was confusing and somewhat frustrating. After scratching my head for a few hours I came up with a solution that restored runtime demands and thought it was worth a share as it’s not straightforward.
We’re going to need to make a few changes to our YAML to put runtime demands back, firstly we need to add a parameter. If you’ve never used a parameter before it allows control of what values can be passed to a pipeline, they work similarly to variables however you can predefined values. More info on parameters can be found here. Here is our starting pipeline:
name: Pipeline_$(Build.SourceBranchName).$(Year:yy)$(DayOfYear)$(Rev:.r)
trigger: none
stages:
- stage: Build
jobs:
- job: "Build"
workspace:
clean: all
pool:
name: PoolName
steps:
- checkout: self
- powershell: 'write-host "TEST"'
displayName: 'PowerShell Script'
Let’s add a parameters block and declare a ‘Demands’ parameter.
name: Pipeline_$(Build.SourceBranchName).$(Year:yy)$(DayOfYear)$(Rev:.r)
trigger: none
parameters:
- name: Demands
displayName: 'Demands'
type: object
default: ''
stages:
- stage: Build
jobs:
- job: "Build"
workspace:
clean: all
pool:
name: PoolName
steps:
- checkout: self
- powershell: 'write-host "TEST"'
displayName: 'PowerShell Script'
The one thing to be aware of here is that type is set to object, it looks like it would make more sense to be a string parameter however a string parameter cannot use ” as a default value. We want ” as a default value as we may not want to supply any runtime demands and we still want the pipeline to run correctly. Next we need to add a variable that links to our parameter:
name: Pipeline_$(Build.SourceBranchName).$(Year:yy)$(DayOfYear)$(Rev:.r)
trigger: none
parameters:
- name: Demands
displayName: 'Demands'
type: object
default: ''
variables:
Demands: '${{ parameters.Demands }}'
stages:
- stage: Build
jobs:
- job: "Build"
workspace:
clean: all
pool:
name: PoolName
steps:
- checkout: self
- powershell: 'write-host "TEST"'
displayName: 'PowerShell Script'
For some reason you have to use a variable to set the demand but that variable has to be linked to a parameter, I tried many ways of getting this to work and this was the only way that worked. Finally we need to use an if statement to conditionally set demands if our Demands variable has a value set.
name: Pipeline_$(Build.SourceBranchName).$(Year:yy)$(DayOfYear)$(Rev:.r)
trigger: none
parameters:
- name: Demands
displayName: 'Demands'
type: object
default: ''
variables:
Demands: '${{ parameters.Demands }}'
stages:
- stage: Build
jobs:
- job: "Build"
workspace:
clean: all
pool:
name: PoolName
${{ if ne(variables['Demands'], '') }}:
demands: ${{variables.Demands}}
steps:
- checkout: self
- powershell: 'write-host "TEST"'
displayName: 'PowerShell Script'
That’s all there is to it, commit the YAML and manually queue the pipeline. You will now see a ‘Demands’ box you can use to set runtime demands:
It’s unfortunate that Azure DevOps prevents setting of runtime demands for YAML pipelines but at least there is a workaround so if you do need to use them it can be done. If you have any questions or comments then please leave a comment or contact me onĀ Twitter. Thanks.