I needed one stage to compute something and later stages to condition on it.
Azure DevOps supports this. It also fails silently in three specific ways, and
none of them produce an error message that points at the cause.
Nothing Fabric-specific here. This applies to any multi-stage pipeline.
Setting the variable
- stage: DetectChanges
jobs:
- job: Detect
steps:
- script: python scripts/detect_changes.py
name: detect # <- required
The script writes:
##vso[task.setvariable variable=ved;isOutput=true]true
Reading it
- stage: Deploy_ved
dependsOn: DetectChanges
condition: >-
eq(dependencies.DetectChanges.outputs['Detect.detect.ved'], 'true')
Gotcha 1: the values are strings
eq(dependencies.DetectChanges.outputs['Detect.detect.ved'], true) # never matches
eq(dependencies.DetectChanges.outputs['Detect.detect.ved'], 'true') # correct
The first one is valid YAML, valid expression syntax, and always false. Your
stage skips every time and the pipeline goes green because a skipped stage is
not a failed stage.
Quote the value.
Gotcha 2: the reference has three parts, not one
dependencies.<Stage>.outputs['<Job>.<StepName>.<Variable>']
^^^^^ ^^^^^^^^^^ ^^^^^^^^^^
The job name and the step name both appear in the string. Miss either and you
get an empty value rather than an error.
The step name is not displayName. If your step only has a displayName, it
has no addressable name and the variable is unreachable.
Gotcha 3: the consuming stage must declare the dependency
- stage: Deploy_ved
dependsOn: DetectChanges # without this the variable cannot resolve
dependencies.X only sees stages this stage actually depends on. Without
dependsOn, the expression resolves to nothing. No error, no warning, and the
condition evaluates false.
Why all three fail the same way
Every one of these produces an empty string, which compares false, which skips
the stage, which is a legitimate outcome that Azure DevOps reports as success.
You get a green pipeline that did nothing. That is worse than a red one, because
nothing prompts you to look.
Debugging it
Print what you set, in the producing job:
- script: echo "ved=$(detect.ved)"
And publish the decision as a build artifact. I write a JSON file from the
detection script and publish it, so every run has a durable record of what it
decided rather than a log line that ages out.
- publish: $(Build.ArtifactStagingDirectory)/change-detection.json
artifact: change-detection
The one that bit hardest
Not in the list above. A stage skipping is indistinguishable, in the UI, from a
stage that was correctly filtered out.
So when you are looking at a run and thinking "good, the unrelated stages were
skipped", check why they skipped. Branch condition and output-variable
condition look identical in the stage view and mean completely different things.
I nearly used a screenshot as evidence for the wrong claim on exactly that
basis.
Full context: [https://www.linkedin.com/pulse/enterprise-microsoft-fabric-cicd-selective-one-azure-devops-ghosh-uxzsf]
Code: [https://github.com/VEDAFORGE/fabric-cicd-reference/tree/v2.0.0]
Top comments (0)