{
"$type": "site.standard.document",
"canonicalUrl": "https://johnnyreilly.com/posts/azure-devops-pull-requests-dynamic-required-reviewers",
"description": "How to have dynamically assigned required reviewers for a pull request in Azure DevOps using build validations and the Azure DevOps Client for Node.js.",
"path": "/posts/azure-devops-pull-requests-dynamic-required-reviewers",
"publishedAt": "2025-06-25T00:00:00.000Z",
"site": "at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.publication/3mova7c4nho2b",
"tags": [
"typescript",
"azure devops",
"node.js"
],
"textContent": "Have you ever wanted to have required reviewers for a pull request in Azure DevOps? Probably. And that's an inbuilt feature of Azure DevOps. By using branch policies, you can set required reviewers for a pull request. If you want to ensure the code is reviewed by the appropriate people before it is merged into the main branch, this can prove very useful.\n\nHowever, the required reviewers are static. You can set them up in the branch policies, but they don't change dynamically based on the code being altered or the people involved in the pull request. I spent many moons trawling the internet for an answer to this question, and I found that many people were asking the same question. The answer was always the same: \"You can't do that.\"\n\nHowever, there is a way. It is, hand on heart, marginally clunky. But the clunk is marginal, and more than acceptable. It involves co-opting build validations to achieve the desired effect. In this post, I'll show you how to do that.\n\n\n\nBuild validations and required reviewers\n\nBuild validations in Azure DevOps are a way to ensure that code meets certain criteria before it is merged into the main branch. They are, crucially, Azure DevOps pipelines that run when a pull request is created or updated. They are typically used to ensure that the code builds successfully, tests pass, linting succeeds etc. Build validations are set up in the branch policies for a repository. It's pretty typical for a repository to have a build validations.\n\nThe crucial thing to note is that, typically, build validations must pass before a pull request can be completed. That's how they provide their value; as a control to prevent changes breaking the codebase. What we're going to do, is use this blocking aspect to our advantage. We'll include a new stage in our build validation pipeline that, each time it runs, does one of the following:\n\n1. Dynamically adds a required reviewer to the pull request, if appropriate. The way we decide which reviewers are dynamically added, if any, is down to us to determine. It's entirely flexible. It could be based on the code being changed or the people involved in the pull request, or indeed something else. If no reviewer is added, the pipeline will pass. But if a reviewer is added to the pull request, the pipeline will be made to fail.\n2. If a reviewer is determined as required, and has already been assigned, check if the reviewer has approved the pull request. If they have approved, the pipeline will pass. If they haven't approved the pull request, the pipeline will fail.\n\nThe thing to pay attention to is that the pipeline will fail if dynamically assigned required reviewers have not given their approval by the end of the pipeline run. This applies equally if the pipeline is running for the first time against a pull request and assigning the reviewers. This means that the pull request cannot be completed until any dynamically assigned required reviewers have approved it.\n\nThis is the part that makes your risk and audit teams happy. You cannot circumvent the required reviewers; the pipeline failing will prevent the pull request from being merged / completed until the required reviewers have approved it. This is a way to ensure that the code is reviewed by the appropriate people before it is merged into the main branch.\n\nI mentioned \"clunky\" earlier. The clunkiness comes from the need to rerun the build validation pipeline in the Azure DevOps UI when the approval has been given. This is because there is no way (that I'm aware of) to trigger the build validation pipeline when a reviewer approval has been provided. So, if the required reviewers approve the pull request, you will need to rerun the build validation pipeline to ensure that it passes and the pull request can be completed.\n\nAs long as the failing pipeline provides a clear message about what is required, this is a small price to pay for the ability to have dynamic required reviewers.\n\nNow I've convinced you that this is a good idea, let's look at how to implement it.\n\nCo-opting your existing build validation pipeline\n\nI'm making an assumption that you already have a build validation pipeline set up for your repository. If you don't, you'll need to set one up first.\n\nTo your existing build validation pipeline, you'll need to add a new stage that will run the code to dynamically assign required reviewers:\n\nYou can see reference to the scripts/dynamic-required-reviewers directory. This is where we'll put the code that will dynamically assign required reviewers. The code will run in a Node.js environment, so we'll need to install Node.js and the dependencies for the code to run.\n\nYou can also see that we're using the System.AccessToken and System.PullRequest.PullRequestId variables. The System.AccessToken is a token that allows the code to interact with the Azure DevOps API, and the System.PullRequest.PullRequestId is the ID of the pull request that the build validation pipeline is running against. We'll use these in our code to dynamically assign required reviewers to the pull request.\n\nWe also use the System.CollectionUri, Build.Repository.Name, and System.TeamProject variables to get the organization, repository name, and project name respectively. These will be used to make API calls to Azure DevOps with our token.\n\nSetting up the code to dynamically assign required reviewers\n\nYou'll need to create the scripts/dynamic-required-reviewers directory. In there we're going to add a package.json file to manage our dependencies:\n\nWe also need a tsconfig.json file to configure TypeScript:\n\nNow we'll add our src/index.ts file where we'll put our code to dynamically assign required reviewers.\n\nThere's a good bit of code here, so let's break it down:\n\n- The main function is the entry point of the script. It parses the command line arguments and sets up the Azure DevOps API client.\n- The makeWebApi function creates an instance of the Azure DevOps Web API client using either a Personal Access Token (PAT) or a Service Account Token (SAT). You'll use a PAT for local development and a SAT in the build validation pipeline. If using a PAT it requires the scopes: vso.code and vso.identity.\n- The getRequiredReviewerName function is a placeholder for your logic to determine the name of your required reviewer, if any. You should implement your logic here to determine when dynamically assigned reviewers are appropriate.\n- The searchIdentityForReviewer function searches for the required reviewer in the Azure DevOps identity system. It uses the Azure DevOps REST API to search for identities based on a search term. Rather frustratingly, you can't directly use the Azure AD / Entra ID Graph API to search for users in Azure DevOps.\n- The determineAction function checks if the required reviewer is already assigned to the pull request and whether they have approved it.\n - If they have, it logs a success message.\n - If they haven't, it throws an error with a message indicating that the required reviewer needs to approve the pull request.\n - If the required reviewer is not assigned, it assigns them to the pull request and throws an error with a message indicating that the pull request requires their approval. It also adds a comment on the PR to make the required action obvious to anyone looking at the PR.\n\nRunning the code\n\nYou can run the code locally to test it. You'll need to set up a Personal Access Token (PAT) with the required scopes and set the environment variables accordingly. You can then run the code using:\n\nConclusion\n\nIn this post, we've seen how to dynamically assign required reviewers for a pull request in Azure DevOps using build validations and the Azure DevOps API brought together with a little TypeScript. By co-opting your existing build validation pipeline, you can ensure that the code is reviewed by the appropriate people before it is merged into the main branch.\n\nUse this. Make your risk and audit teams happy!",
"title": "Azure DevOps: pull requests and dynamic required reviewers"
}