Reputation: 727
I am working on a azure devops multi stage yaml pipeline. I set a variable in the first stage and then for the next stage, I have a condition based on that variable. I am also retrieving the variable value in the next stage. Apparently there is slight difference between the syntax for accessing inter-stage variables in the condition and at the stage level. I am not able to figure out the syntax I need to use in the condition. I have tried all possible variations but none seems to be working. In the example below, I am expecting the lint stage to run however it gets skipped. What should be exact syntax for the condition here?
stages:
- stage: build
displayName: build
pool:
name: Azure Pipelines
vmImage: ubuntu-latest
dependsOn: []
jobs:
- deployment: build_job
environment:
name: "test"
strategy:
runOnce:
deploy:
steps:
- task: PowerShell@2
displayName: "get commitMessage variable"
name: getCommitMessage
inputs:
targetType: inline
pwsh: true
script: |
$commitMessage = "abcd_import/"
echo "setting commitMessage: $commitMessage"
echo "##vso[task.setvariable variable=commitMessage;isOutput=true]$commitMessage"
- stage: lint
displayName: lint
dependsOn:
- 'build'
condition: contains(stageDependencies.build.build_job.outputs['build_job.getCommitMessage.commitMessage'], 'import/')
pool:
name: Azure Pipelines
vmImage: ubuntu-latest
variables:
- name: BUILD_STAGE_GET_COMMIT_MESSAGE
value: $[stageDependencies.build.build_job.outputs['build_job.getCommitMessage.commitMessage']]
jobs:
- deployment: validate
environment:
name: "test"
strategy:
runOnce:
deploy:
steps:
- task: PowerShell@2
displayName: "commitMessage is empty"
name: fail
inputs:
targetType: inline
pwsh: true
script: "echo $(BUILD_STAGE_GET_COMMIT_MESSAGE)"
Update(Answer): I raised a MS support case on this one and got a resolution. The right syntax is
condition: contains(dependencies.build.outputs['build_job.build_job.getCommitMessage.commitMessage'], 'import/')
A few points on this weird issue:
Upvotes: 5
Views: 9425
Reputation: 327
The stage dependencies are hard to debug. There are no logs of the evaluation, it's trail and error. The weird thing is the double reference of the job name?? Can someone confirm this if its also true for you (upvote)?
Stage condition: dependencies.STAGE.outputs['JOB.JOB.TASK.VARIABLE'].
Example
stages:
- stage: stage_A
jobs:
- job: job1
steps:
# Note: isOutput is set to true
- bash: echo "##vso[task.setvariable variable=boolVar1;isOutput=true]true"
name: task_1 # Note name is important for reference
- stage: stage_B # no dependsOn, automatically depends on previous stage.
condition: and(succeeded(), eq(dependencies.stage_A.outputs['job1.job1.task_1.boolVar1'], 'true'))
jobs:
- job: running
variables:
boolVar1: $[ stageDependencies.stage_A.job1.outputs['job1.task_1.boolVar1']]
steps:
- bash: echo "Variable reference inside Job: $(boolVar1)"
Upvotes: 0
Reputation: 727
I raised a MS support case on this one and got a resolution. The right syntax is
condition: contains(dependencies.build.outputs['build_job.build_job.getCommitMessage.commitMessage'], 'import/')
I have updated the original question with the answer as well.
Upvotes: 1
Reputation: 13444
On a stage, to reference an output variable from another stage, you should use the following expression formats:
dependencies.STAGE.outputs['JOB.TASK.VARIABLE']
.stageDependencies.STAGE.JOB.outputs['TASK.VARIABLE']
.For more details, you can see the document about "Use outputs in a different stage".
In addition, on a stage, if you set a stage-level variable using the output from another stage, you should use the format stageDependencies.STAGE.JOB.outputs['TASK.VARIABLE']
instead of dependencies.STAGE.outputs['JOB.TASK.VARIABLE']
. See this document.
Below is an example as reference:
parameters:
- name: RunStgB
type: string
default: YesRun
values:
- YesRun
- NoRun
stages:
- stage: A
displayName: 'Stage A'
pool:
vmImage: ubuntu-latest
jobs:
- job: A1
displayName: 'Job A1'
steps:
- task: Bash@3
name: setOutput
displayName: 'Set output variable'
inputs:
targetType: inline
script: |
echo "parameters.RunStgB = ${{ parameters.RunStgB }}"
echo "##vso[task.setvariable variable=RunStgB;isoutput=true]${{ parameters.RunStgB }}"
- stage: B
displayName: 'Stage B'
dependsOn: A
condition: eq(dependencies.A.outputs['A1.setOutput.RunStgB'], 'YesRun')
variables:
- name: Output_RunStgB
value: $[ stageDependencies.A.A1.outputs['setOutput.RunStgB'] ]
pool:
vmImage: ubuntu-latest
jobs:
- job: B1
displayName: 'Job B1'
steps:
- task: Bash@3
displayName: 'show output variable'
inputs:
targetType: inline
script: echo "Output_RunStgB = $(Output_RunStgB)"
Upvotes: 7
Reputation: 306
As described here: https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#dependencies i think your condition instead of this
condition: contains(stageDependencies.build.build_job.outputs['build_job.getCommitMessage.commitMessage'], 'import/')
should look like this:
condition: contains(dependencies.build.outputs['build_job.getCommitMessage.commitMessage'], 'import/')
Upvotes: 0