Pipeline notifications
Out of the box the owner of a subscription gets notifications about every pipeline that is run. That is too much: you'll get a notification every time new content for a website is pushed to Azure. It is good enough to be notified when the pipeline fails, or if one of the steps in the pipeline requires attention.
Generic pipeline notifications
Azure DevOps has notification settings on several levels: for the user logged in to DevOps, as part of the user settings (top tight) and for a project team in the settings of the project the pipeline is part of. By default several notifications are defined and enabled. These include the Build completes and two for pipelines. The Build completes sends a notification for each pipeline that is completed. I prefer to have notifications only for events that I really have to attend to, so I typically disable all notifications except the useful ones. For pipelines, I disable the three default ones.
One scenario I have to take action is when a build fails. That most likely means that the website is unexpectedly not published, probably due to new incorrect content. That can be done via a new subscription, in the user settings for all pipelines or in the project's settings:
- Click on Add subscription
- Select Build and then Build fails and click Next. (You can also select Build completes and add the clause Status = Failed).
- You can select extra criteria, including (in user settings) the project to limit the notification to, and who/where to send the notification to.
Notifications based on specific conditions
Sometimes whether or not a notification should be send depends on what happens in the pipeline. I have a pipeline that regularly verifies whether the external URLs used in links in the website still exist. I only want a notification if an URL is no longer accessible - and not if it previously was not accessible, because I have already decided that the link does not have to be fixed right away. Obviously Azure Pipelines doesn't know about the business logic.
The solution in a nutshell:
- Create a custom tool that detects whether to notify the user. It creates a specific file if the user has to be notified.
- Add a ManualValidation task to the pipeline and execute it if the specific file exists. The task lets you specify who to notify.
In practice it is a bit harder as the custom tool has to be run in a different context then ManualValidation. The pipeline should be like:
# Put the trigger/schedules here
jobs:
- job: RunCustomTools
pool:
vmImage: windows-latest
steps:
- checkout: self
# Put the steps to run the custom tool(s) here
- pwsh: |
$fileExists = Test-Path -Path "$(System.DefaultWorkingDirectory)/...path to the special file in the git repository clone..."
Write-Output "##vso[task.setvariable variable=SpecialFileExists;isOutput=true]$fileExists"
name: test
displayName: Detect presence of special file
- job: NotifyIssues
dependsOn: RunCustomTools
variables:
SpecialFileExists: $[ dependencies.RunCustomTools.outputs['test.SpecialFileExists'] ]
condition: eq(variables['SpecialFileExists'], True)
pool:
server
steps:
- task: ManualValidation@1
condition: eq(variables['SpecialFileExists'], True)
timeoutInMinutes: 1
inputs:
notifyUsers: 'comma-separated list of email addresses to notify'
onTimeout: 'resume'
Some remarks about this scripts:
- The pipeline should be split into two jobs. The reason is that the
ManualValidation@1task must be run inpool: server, while the custom tools must havepool: vmImage: .... - Azure Pipelines can conditionally run jobs, tasks and steps using the
conditionspecification. At the moment (2025) the syntax to express the condition in has no expression to check for the existence of a file. A workaround is to use Powershell (pwsh, works on Windows and Ubuntu) to detect the file and set a variable that can be used in the pipeline. - The second job depends on the first, so it will not be executed if the first job fails. It also does not run if the special file is not detected.
- The second job has to import the variable from the first job. To make that possible, the variable has to be set with
isOutput=true. It will then be available as part of the outputs of the first job. Thename: testis also required as it determines the name of the variable. - Notifications are sent when
ManualValidation@1is executed. - In general the
ManualValidation@1task is intended to pause the pipeline and let a human take action before it can proceed. In my case the pipeline does not have to wait. AddtimeoutInMinuteswith the smallest value, and setonTimeouttoresumeso the pipeline will not fail.
