How to add dependency in Azure Pipeline Stages?
Overview
Many scenarios you come across when you create an Azure Pipeline that you need dependency between stages like you want to run the next stage only if the previous stage is succeeded or you need to run the next stage even if the last stage is failed.
For all such scenarios, we need to create a dependency between stages. In this article, we are going to explain how you can create a dependency between stages using the YAML pipeline.
Possible Scenarios
- Without Dependency
- Run stages in Parallel
- Run stage conditionally
- Run Stage always
Let’s go through each scenario.
Scenario 1: Without dependency
In this case, we will fail stage A to see if stage B can run and we have a basic pipeline for it as shown below.
trigger:
- None
pool:
vmImage: ubuntu-latest
stages:
- stage: A
displayName: Stage A
jobs:
- job: Job1
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
throw 'Failing this stage explicitly'
- stage: B
displayName: Stage B
jobs:
- job: Job1
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Write-Host "This stage will not run"
Output:
As shown in the above output, stage B will not run if stage A failed because, in the YAML pipeline, we haven’t specified anything that creates dependency.
This scenario is similar to preventing the next stage run if the last stage is failed because, in the “Stages to run” section, it says Stage B is dependent on Stage A.
The above pipeline code for stage B is similar to,
- stage: B
displayName: Stage B
dependsOn: A
jobs:
- job: Job1
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Write-Host "This stage will not run"
Here, the dependsOn parameter is used to specify the dependency between stages means that Stage B will always run after Stage A if Stage A is successful.
Scenario 2: Run Stages in Parallel
In the first scenario, we have seen that if there are two stages then they will run in sequence only. In this case, if you want to run two stages in parallel then better to opt for one stage and multiple jobs so they can be executed in parallel.
Let’s consider the scenario below,
As shown in the above image, we need to run Stage-B and Stage-C in parallel with Stage-A and stage-D after Stage-B and Stage-C.
The below code just shows how this scenario can be created. Full code you can download it from Git Repo.
https://github.com/chiragce17/MyPublicRepo/blob/main/AzurePipeline/StageDependency.yaml
stages:
- stage: A
- stage: B
dependsOn: A # this stage runs after Stage-A
- stage: C
dependsOn: A # this stage runs in parallel with Stage-B, after A
- stage: D
dependsOn: # this stage runs after Stage-B and Stage-C
- B
- C
If you see the stages to run,
In another way, you can clearly see the stage dependency when you run the pipeline as shown below
Stage Output:
Scenario 3: Run Stage conditionally
In scenario-2 we have specified only the stage dependencies and how they can be executed in serially and parallelly but we haven’t decided how the stage will run on condition bases.
For example, I need to run stage B even if stage-A fails then the code will be as below.
trigger:
- None
pool:
vmImage: ubuntu-latest
stages:
- stage: A
displayName: Stage A
jobs:
- job: Job1
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
throw 'Failing Stage-A'
- stage: B
displayName: Stage B
condition: failed()
jobs:
- job: Job1
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Write-Host "This stage will run if the stage-A failed"
Output:
If there are more stages then you can specify the stage name inside the condition. For example, failed(‘A’). In this case, if Stage-A is succeeded then Stage-B is skipped.
Let’s add one more stage and I want the new Stage-C will run only if stage-B is succeeded. For that, you need to use succeeded() condition with the Stage name specified.
Code you can get from my GitHub repository.
https://github.com/chiragce17/MyPublicRepo/blob/main/AzurePipeline/StageCondition.yaml
Output:
Scenario 4: Run Stage Always
In some scenarios, we need to run stage(s) always regardless of the previous stage status. You need to use Always() function there.
Always() is the expression for the Stage condition. More conditions you can find in the article below.
StageB you need to specify like this,
- stage: B
displayName: Stage B
condition: always()
jobs:
- job: Job1
steps:
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Write-Host "This stage will always run"
Let’s run the pipeline.
As you can see Stage B was executed regardless of the status of stage A. Here Stage A is failed.