Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure DevOps - Dynamically evaluate demand name

I am looking for a way to set in Azure DevOps .yaml file dynamic demand name.

Right now we have a few self-hosted build agents that are selected by Azure DevOps services randomly but sometimes we need to choose one agent to investigate why it is not working(or for other rare event). One way is to switch off all other agents and operate on this one desired(it affects our whole CI/CD). Second way is adding temporary pipeline and moving desired agent to next agent pool(it costs time).

I think best solution would be possibility to dynamically set demands. For example I can have in variable groups these:

"DemandName" = "IsBuildAgent"

"DemandValue" = "Yes"

Each agent would have this environment variable set ant it would always allow each agent to run pipeline, but if I would set before running pipeline below variables.

"DemandName" = "AgentNumber"

"DemandValue" = "BuildAgentNr6"

enter image description here

It would override library variables and only one agent would be able to run this pipeline.

pool:
  name: MyBuildAgents
  demands: $(DemandName) -equals $(DemandValue)

DemandValue is correctly evaluated but DemandName cannot be set right now. Is it possible to achieve in slightly changed way? Maybe should I change syntax? Or maybe should I propose this as new feature?

like image 870
Kontekst Avatar asked May 15 '26 18:05

Kontekst


2 Answers

Is it possible to achieve in slightly changed way? Maybe should I change syntax? Or maybe should I propose this as new feature?

Your syntax is correct.

I am afraid there is no such out of box or slightly changed way to achieve it.

Just like you test, DemandName cannot be set right. That because the left side of the equation is treated as a string instead of a value according to the grammatical rules. This will cause Azure devops to find the demand name as a string $(DemandName) instead of the value of $(DemandName) and then looking for the demand name based on the value.

Hope this helps.

like image 166
Leo Liu-MSFT Avatar answered May 19 '26 02:05

Leo Liu-MSFT


I also did a few experiments (on dev.azure.com), with the following results:

A) You cannot use parameters in demands directly:

Example:

trigger: none

parameters:
- name: foo
  type: string

pool:
    name: Default
    demands:
      - SomeDemand -equals ${{ parameters.foo}}

jobs:
- job:
  displayName: 'Job 1'
  steps:
  - script: echo "hello world"

Error: A template expression is not allowed in this context. It does not matter whether you use the parameter in the key or value of the demand.

B) You can use statically-defined variables (with the option to override their values in the Run pipeline dialog)

Example (excerpt):

parameters:
- name: foo
  type: string

variables:
  myvar: ${{ parameters.foo}}

pool:
    name: Default
    demands:
      - SomeDemand -equals $(myvar)

However, if you try to use the variable in the key of the demand (replacing SomeDemand) it won't work, as was already discussed by the OP. Azure DevOps simply prints something like No agent found in pool Default which satisfies the specified demands: $(mykey) -equals <value entered in Run dialog>

C) You cannot use nested variables directly, because the AZP platform does not seem to resolve them properly

Example:

trigger: none

variables:
  myOtherVar: hello
  myvar: $(myOtherVar)-world

jobs:
- job:
  displayName: 'Job 1'
  variables:
    redefined: $[variables.myvar]
  pool:
    name: Default
    demands:
      - SomeDemand -equals $(redefined)
  steps:
  - script: echo "hello world"

Error message: No agent found in pool Default which satisfies the specified demands: SomeDemand -equals $(myOtherVar)-world

D) You can use output variables that you set dynamically via echo "##vso[task.setvariable..., as long as you redefine them.

Example:

trigger: none

variables:
  myOtherVar: hello
  myvar: $(myOtherVar)-world

jobs:
  - job: prepare_demand
    steps:
      - script: echo "##vso[task.setvariable variable=someOutputVar;isoutput=true]$(myvar)"
        displayName: set dynamic output variable
        name: passOutput
  - job: use_demand
    dependsOn: prepare_demand
    variables:
      redefinedVariable: $[ dependencies.prepare_demand.outputs['passOutput.someOutputVar'] ]
    pool:
      name: Default
      demands:
         - SomeDemand -equals $(redefinedVariable)
    steps:
      - script: echo "hello world"

Note: trick D only works for regular jobs, not for deployment jobs!

like image 28
MShekow Avatar answered May 19 '26 02:05

MShekow



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!