Reputation: 12077
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 -
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?
Upvotes: 11
Views: 18814
Reputation: 40879
This all depends on the context where you want to use dependency to previous stage:
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
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 calledstageDependencies
.
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
Upvotes: 22