be9inn3r
be9inn3r

Reputation: 103

multistage azure devops pipeline - skip stage sequentially

I have an azure devops pipeline which run as follow:

parameters:
- name: environments
  type: object
  default:
  - a
  - b


stages:
- ${{ each env in parameters.environments }}:
  - stage: Plan_${{ env }}
    condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
    jobs:
    - job: Plan
      steps:
      - template: s1.yml
        parameters:
          env: ${{ env }}
          action: plan
          workingDirectory: '${{ parameters.workingDirectory }}'
  
  - stage: Apply_${{ env }}
    dependsOn: Plan_${{ env }}
    condition: and(succeeded(), eq(dependencies.Plan_${{ env }}.outputs['Plan.x.y'], 'true'))   #where x is a task from template s1.yml and y is the output variable;
    jobs: 
     .................

Running this pipeline, it runs sequential not as I wish, I need. I need to have something like:

Currently, it is working as: considering no changes for both environment, pipeline starts with plan.a, it matches the condition then it skips apply.a, skips plan.b and apply.b .

I tried in parallel mode, introducing before Plan a new stage and to make Plan to depends by that stage and they working in parallel, but in sequent mode, how to make it works as I need?

ps: I tried excluding dependsOn, not working; I tried with parallel depending on another previous stage if I create it but I need it in sequential mode.

I tried this way:




stages:
        - ${{ each env in parameters.environments }}:
          - stage: Plan_${{ env }}
            condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
            jobs:
            - job: Plan
              steps:
              - template: s1.yml
                parameters:
                  env: ${{ env }}
                  action: plan
                  workingDirectory: '${{ parameters.workingDirectory }}'
       **- ${{ each env in parameters.environments }}:**
          - stage: Apply_${{ env }}
            dependsOn: Plan_${{ env }}
            condition: and(succeeded(), eq(dependencies.Plan_${{ env }}.outputs['Plan.x.y'], 'true'))   #where x is a task from template s1.yml and y is the output variable;
            jobs: 
             .................

and the pipeline now is working in this way: starts with plan.a (finishing it, result no changes), continue with plan.b (result no changes) then skipping apply.a , skipping apply.b .

I need them to be sequentially plan.a, apply.a; plan.b, apply.b and skipping the apply after each plan stage started and having an output variable that match or not condition.

Upvotes: 2

Views: 624

Answers (1)

Scott Richards
Scott Richards

Reputation: 726

Solution 1

Add dependsOn: [] on in the Plan_${{ env }} stage:

parameters:
- name: environments
  type: object
  default:
  - a
  - b

stages:
- ${{ each env in parameters.environments }}:
  - stage: Plan_${{ env }}
    condition: and(succeeded(), ne(variables['Build.Reason'], 'Manual'))
    dependsOn: []
    jobs:
    - job: Plan
      steps:
      - task: PowerShell@2
        name: SetVariable
        inputs:
          targetType: "inline"
          script: |
            Write-Host "##vso[task.setvariable variable=runApply;isOutput=true]false"
  
  - stage: Apply_${{ env }}
    dependsOn: Plan_${{ env }}
    condition: and(succeeded(), eq(dependencies.Plan_${{ env }}.outputs['Plan.SetVariable.runApply'], 'true'))
    jobs:
    - job: Apply
      steps:
      - task: PowerShell@2
        name: SetVariable
        inputs:
          targetType: "inline"
          script: |
            Write-Host "Running Apply"

Output:

enter image description here

Solution 2

The reason Plan_B is being blocked is because the stage before it is in a skipped state, which is not succeeded. To get around this we can alter the condition from succeeded() to not(or(failed(), canceled())).

parameters:
- name: environments
  type: object
  default:
  - a
  - b

stages:
- ${{ each env in parameters.environments }}:
  - stage: Plan_${{ env }}
    condition: and(not(or(failed(), canceled())), ne(variables['Build.Reason'], 'Manual'))
    jobs:
    - job: Plan
      steps:
      - task: PowerShell@2
        name: SetVariable
        inputs:
          targetType: "inline"
          script: |
            Write-Host "##vso[task.setvariable variable=runApply;isOutput=true]false"
  
  - stage: Apply_${{ env }}
    dependsOn: Plan_${{ env }}
    condition: and(not(or(failed(), canceled())), eq(dependencies.Plan_${{ env }}.outputs['Plan.SetVariable.runApply'], 'true'))
    jobs:
    - job: Apply
      steps:
      - task: PowerShell@2
        name: SetVariable
        inputs:
          targetType: "inline"
          script: |
            Write-Host "Running Apply"

Output:

enter image description here

Upvotes: 2

Related Questions