2
votes

I have an Azure DevOps pipleline with one stage that is dependant upon two others. This stage should run conditionally if both of the following are true -

  • Stage 1 (Deploy_BVT_UKS_Internal) sets an output variable with a specific value in one of it's jobs.
  • Stage 2 (Test_BVT) either failed or was skipped.

Here is the condition that I am using. However, it is not working and the stage is being skipped when I expect it to run. The syntax for checking the value of the output variable was taken from the documentation.

condition: >-
  and(
    in(dependencies.Test_BVT.result, 'Skipped', 'Failed'),
    eq(dependencies.Deploy_BVT_UKS_Internal.outputs['Swap_Slots.Output_Slot_Swap_Success_Variable.slotSwapped'], 'true')
  )

To confirm, I'm formatting the output variable check as follows -

dependencies.<stageName>.outputs['<jobName>.<taskName>.<variableName>']

If I simply use in(dependencies.Test_BVT.result, 'Skipped', 'Failed') as my condition then the stage runs if the Test_BVT stage is skipped or fails. So this suggests that the output variable check is the issue, though I can't be as logs no longer seem to show how conditions are evaluated.

Confusingly the same documentation shows stage dependencies formatted in two different ways, so I have added a task to write the value of the output variable using both formats. The format that uses stageDependencies produces the expected result, proving that the output variable is being set as expected. However, the format that uses dependencies does not work.

- job: test
  variables:
    one: $[dependencies.Deploy_BVT_UKS_Internal.outputs['Swap_Slots.Output_Slot_Swap_Success_Variable.slotSwapped']]
    two: $[stageDependencies.Deploy_BVT_UKS_Internal.Swap_Slots.outputs['Output_Slot_Swap_Success_Variable.slotSwapped']]
  steps:
  - script: |
      echo $(one)
      echo $(two)
    displayName: Output SlotSwapped Value

I did try the stageDependencies format in my condition, just in case, but that also failed.

Am I missing something here, or does this just not worked as documented?

1
On the stage level you should use dependencies level and on the job level stageDependencies to refer to previous stagesKrzysztof Madej
So while that is just really confusing, that would mean that my condition is (in theory) formatted correctly?David Gard
Yeap. Can you check my answer.Krzysztof Madej

1 Answers

5
votes

This all depends on the context where you want to use dependency to previous stage:

  • if you use this on stage level - you should use syntax with dependencies like here:
stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
     # or on Windows:
     # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
       name: printvar

- stage: B
  condition: and(succeeded(), eq(dependencies.A.outputs['A1.printvar.shouldrun'], 'true'))
  dependsOn: A
  jobs:
  - job: B1
    steps:
    - script: echo hello from Stage B
  • but on the job level you should use stageDependencies syntax like here:
trigger: none

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
     # or on Windows:
     # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
       name: printvar

- stage: B
  dependsOn: A
  jobs:
  - job: B1
    condition: in(stageDependencies.A.A1.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
    steps:
    - script: echo hello from Job B1
  - job: B2
    condition: eq(stageDependencies.A.A1.outputs['printvar.shouldrun'], 'true')
    steps:
     - script: echo hello from Job B2


As it is written in the link you gave:

The context is called dependencies for jobs and stages and works much like variables. Inside a job, if you refer to an output variable from a job in another stage, the context is called stageDependencies.

I made more tests and it looks like a bug. It all depends on the order in your condition. Please compare this

condition: and(eq(dependencies.B.outputs['B1.printvar.shouldrun'], 'true'), in(dependencies.A.result, 'Failed', 'Skipped')) # it works

and this

condition: and(in(dependencies.A.result, 'Failed', 'Skipped'), eq(dependencies.B.outputs['B1.printvar.shouldrun'], 'true')) # it doesn't work

It should give the same output but it's not.

stages:
- stage: A
  condition: false
  jobs:
  - job: A1
    steps:
    - script: echo Job A1
- stage: B
  condition: always()
  jobs:
  - job: B1
    steps:
     - bash: echo "##vso[task.setvariable variable=shouldrun;isOutput=true]true"
     # or on Windows:
     # - script: echo ##vso[task.setvariable variable=shouldrun;isOutput=true]true
       name: printvar

- stage: C
  condition: and(eq(dependencies.B.outputs['B1.printvar.shouldrun'], 'true'), in(dependencies.A.result, 'Failed', 'Skipped')) # it works
  dependsOn:
  - A
  - B
  jobs:
  - job: C1
    steps:
    - script: echo hello from Stage C

- stage: D
  condition: and(in(dependencies.A.result, 'Failed', 'Skipped'), eq(dependencies.B.outputs['B1.printvar.shouldrun'], 'true')) # it doesn't work
  dependsOn:
  - A
  - B
  jobs:
  - job: D1
    steps:
    - script: echo hello from Stage D

enter image description here