Pull Request bots with Azure DevOps
Adding bespoke functionality to your Azure DevOps CI solution
"Why can't I do [x] with Azure DevOps?"
With the best will in the world, CI/CD systems such as Azure DevOps and github, among others, can't always cater for every feature everybody wants.
If you're a hobbyist or otherwise in complete control of a single project it's an obvious (if not entirely painless) choice to use a different system that offers you the functionality you need.
But what if you're locked in to the system you're on due to a choice by your employer, or some other integration that you're relying on?
That's the problem faced to us recently whereby a not-so-straightforward setup of CI pipelines resulted in a cumbersome experience when queueing Integration Test pipelines against build output artefacts which were generated from a Pull Request in our main product.
For simplicity's sake, this is a rough overview of what we have

Basically, our main branch in the main product git repo will not accept new commits other than when it's come in from a Pull Request.
The Pull Request configuration for that branch has various quality gates configured on it, but the main thing of interest here is that we do build that Pull Request. Doing this allows us to test the result of building the proposed change, merged with main at the time of the build, which is the build we would get should we merge the changes. Testing in this way allows us to fail fast, and increase our confidence that we have not left main in a state that would be unreleasable.
The next thing to note is that we have a separate repository for our System Integration tests. There are reasons for this which aren't really relevant for this blog post. The setup we have here is that we can queue the System Integration Test pipeline by telling it the build number of the main product which we want to test, this pipeline will then retrieve the correct build artefacts, deploy it to the test hosts and run all of the integration tests.
So the question was raised, can we use a bot to orchestrate this for us? The immediate answer was "maybe but I don't know how to", because all of our build agents run on private networks and are not accessible via the internet. This meant we couldn't run a jenkins (or equivalent) instance on a server in our farm, and setup an Azure DevOps Service Connection to post events to it.
However, Azure DevOps does now allow you to setup an "Incoming WebHook", which pipelines can consume to use as a trigger.
Setting up the WebHooks
In your Azure DevOps project, click the "⚙️ Settings" link in the lower left portion of the view. From the settings page, first click the "Service connections" option under the heading Pipelines. Then click to Create a new service connection, and choose Incoming WebHook from the list of options. Click next, and then fill in the pane with a chosen WebHook Name. When I do this, I provide the same value for the Service connection name. (TODO: Provide info about the Secret)

Click save.
Still in the Settings section for your project, you now want to set up some Service Hooks to call in to the Web Hook you just created.
Cilck "Servce hooks" under the General heading and then click "Create subscription". Select "Web Hooks" from the list of options and click Next.

For my purposes I created two service subscriptions, one for "Pull request created" and another for "Pull request commented on"
The URL to post to should be in the format
So what now?
Now you've done that. Your WebHook will start to receive events. It doesn't matter that you're not consuming the events yet. Once some events have occurred that will have triggered the Service Hooks, you will be able to see the logs of them by clicking the burger button and clicking History

You will then be able to inspect the payload data, and review which items are relevant for what you want to achieve. The yaml pipeline example below shows how to access the value from the WebHook payload.

How do I use it in a pipeline then?
Here is a very simple pipeline which will consume both of the service connections as part of a single pipeline. It determines which tasks to run based on the eventType member of the json payload.
This pipeline will update the original description of the PR (based on the Pull Request created service connection), with some basic text instructing viewers on how to trigger the bot to perform some work.
Final steps
When your pipeline such as the above runs, you may need to grant it permission in Azure DevOps to checkout your additional repositories as required.
You will also need to grant the build service account permission to contribute to Pull Requests.
To do this, go to your Project Settings and select the Repositories section. Click on your repo which is getting the Pull Requests, and then click Permissions.
In here, select the "{project name} Build Service" account, and change "Contribute to pull requests" from "Not set" to "Allowed"

I hope you find this useful!
Last updated
Was this helpful?