DevOpsy
DevOpsy

Reputation: 727

Azure DevOps Yaml pipelines: Stage condition variable syntax

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

Answers (4)

MeneerBij
MeneerBij

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

DevOpsy
DevOpsy

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

Bright Ran-MSFT
Bright Ran-MSFT

Reputation: 13444

On a stage, to reference an output variable from another stage, you should use the following expression formats:

  • At the stage level, the format for referencing an output variable from another stage is dependencies.STAGE.outputs['JOB.TASK.VARIABLE'].
  • At the job level, the format for referencing an output variable from another stage is 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.

enter image description here

Below is an example as reference:

  1. azure-pipelines.yml
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)"
  1. Result.

    enter image description here

    enter image description here

Upvotes: 7

Schamal
Schamal

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

Related Questions