16

I'm trying to figure out how to access an Azure DevOps matrix variable, in a compile time expression. The reference value is always null/empty/missing. Like the variable hasn't been set.

here's a sample yml file I was trying:


jobs:
- job: LinuxBuild
  displayName: Pew Pew
  strategy:
    matrix:
      debugJob:
        buildConfiguration: Debug
      releaseJob:
        buildConfiguration: Release
  pool:
    vmImage: 'ubuntu-16.04'

 steps:
  - script: echo ${{variables.debugJob.buildConfiguration}} ## <-- always null/empty

  - script: echo ${{variables['debugJob.buildConfiguration']}}  ## <-- always null/empty

  - ${{ if eq(variables.debugJob.buildConfiguration, 'Debug') }}: ## <-- never ran/executed
    - template: doSomething.yml@templates

1 Answer 1

20

For keywords Matrix, it is used to expand the multi-configs into multiple runtime jobs. In another word, the YAML which contain the Matrix keywords will be expanded at runtime instead of parse time. So, the variable buildConfiguration is a runtime variable, and it is not available at compile time, also can not be get then.

Also, ${{ }} is a format which to process the variables at compile time.

Now, there's no doubt to know that the issue you met is a expected action since you are trying to get a runtime variable at compile time.


So, to print out the value of buildConfiguration, you need use the format of $()

Change your YAML script to this:

jobs:
- job: LinuxBuild

  displayName: Pew Pew
  strategy:
    matrix:
      debugJob:
        buildConfiguration: Debug
      releaseJob:
        buildConfiguration: Release
  pool:
    vmImage: 'ubuntu-16.04'

  steps:
  - script: echo $(buildConfiguration) 

  - script: echo "hello"
    condition: and(succeeded(), eq(variables.buildConfiguration, 'Debug'))

Now, let's focus on the another try you made: - ${{ if eq(variables.debugJob.buildConfiguration, 'Debug') }}:.

Firstly, you need know that ${{ if xxx }}, this is a template expression which processed at compile time. This means, the system will go parsing the value then decide whether next steps/jobs/templates should be ran. This process are happen before pipeline run. We call that initial step.

As I mentioned above, buildConfiguration is a runtime variable. It only available at run time. So, its value could not be get at compile time. In compile time, its value will be parsed into null. This is why you template never be ran.

There has 2 work arounds you can consider to make this condition true.

1) Change to use another variable in condition, the one which can available at both compile time and run time. e.g Build.SourceBranchName.

2) Split the condition and change them into the tasks' condition which defined in template yml file.

Like:

  - script: echo "hello"
    condition: and(succeeded(), eq(variables.buildConfiguration, 'Debug'))
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the excellent answer. The matrix variables being runtime variables was my gut feeling - so I'm glad that has been confirmed. What I was really hoping for was an answer for the last part -> conditional template. I was using a compile time template expression, which can't/doesn't work. So now I'm unsure how to have a conditional template based on a MATRIX variable.
Further more, I can't use suggestion #1 - because the matrix defines the variable. Not a global variables for the entire pipeline. As for suggestion #2 - that only works on various steps ... but the template step doesn't have a condition allowed on it. Which was why i was trying to leverage compile time or run time expressions.
@Pure.Krome Limited by the variable you were using is a runtime variable. No way to get it at compile time. If you change to use another variable, that would be much easy.
@Pure.Krome Nope, for suggestion #2, what I mean is put condition onto one specific step. For example, there has one powershell task in template, then I make that condition to powershell task. I know this way verrry trouble, but I would say it works.
correct. i know the condition works for every step. This now means: all "runs" in the matrix (in my scenarion, run 1 == Debug, run 2 == Release) will -all- include/run that template .. but only one of them will actually do each step. (the step will say condition: skip if RELEASE). So Release will have all this extra noise in the logs. skip / skip / skip / skip / .. etc... I thought (actually, HOPED and PRAYED) that this would be a feature of Azure DevOps pipelines. If it's not - where do we pray/ask for this feature?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.