A few weeks ago we covered Conditionals in YAML to show how to conditionally run tasks and jobs as well as how to make a job dependent on another job. This post is going to cover combing conditional and job dependencies. If you are new to this series you can use the following posts to catch up.
Getting Started with Azure DevOps
Pipeline Creation in Azure DevOps
Azure DevOps Publish Artifacts for ASP.NET Core
Azure DevOps Pipelines: Multiple Jobs in YAML
Azure DevOps Pipelines: Reusable YAML
Azure DevOps Pipelines: Use YAML Across Repos
Azure DevOps Pipelines: Conditionals in YAML
Azure DevOps Pipelines: Naming and Tagging
Azure DevOps Pipelines: Manual Tagging
Existing Job
As a reminder, our sample pipeline has 4 jobs. The WebApp1 job always runs, the WebApp2 job is run or skipped based on a pipeline variable, the DependentJob depends on WebApp1 and WebApp2, and finally, the TagSources job is dependent on all the previous jobs. We are going to be tweaking the TagSources job in this post. The following is the YAML for the setup of the TagSources job without its tasks.
- job: TagSources displayName: 'Tag Sources' pool: vmImage: 'ubuntu-latest' dependsOn: - WebApp1 - WebApp2 - DependentJob
With this setup WebApp1, WebApp2, and DependentJob all have to report successful or the TagSources job will be skipped. The following screenshot shows a pipeline run with the variable to build WebApp2 set to false.
As you can see the TagSources job was skipped because one of its dependent jobs was skipped.
Dependencies with Conditions
Let us say for our pipeline we want the TagSources job to run as long as all jobs were successful or if WebApp1 was successful and the WebApp2 and DependentJob jobs were skipped. To do this we are going to add a condition element and manually check the results of the dependencies as you can see in the following.
- job: TagSources displayName: 'Tag Sources' pool: vmImage: 'ubuntu-latest' dependsOn: - WebApp1 - WebApp2 - DependentJob condition: | and ( eq(dependencies.WebApp1.result, 'Succeeded'), in(dependencies.WebApp2.result, 'Succeeded', 'Skipped'), in(dependencies.DependentJob.result, 'Succeeded', 'Skipped') )
And you can see in the results the TagSources job ran even with the two skipped jobs.
Wrapping Up
If there is a simpler way to accomplish what we did above I would love to hear about it. If I remember correctly I found the above in a GitHub issue, but I don’t have the link. I’m not sure how many of you will have Pipelines that will need this, but hopefully, this will save someone some research time.
Also published on Medium.
This works great when you skip the steps. But for anyone attempting to use this when the steps are Waiting, it will not work. In his final example, if Build WebApp2 and Build Dependent Job are still in a Waiting, Tag Sources will not run unless you manually skip those other steps. We attempted to use this to manage the flow of deployment stages between test/production environments, and were unable to do so.