0
votes

I've got an Azure DevOps Git repository that sits in Azure DevOps in the cloud. We're using Pull Requests to manage code merging down to our release branch.

The feature branches have an automatic reviewer assigned that will have the sole purpose of adding an approval vote when the functional testing reaches successful completion in our continuous deployment environment. The idea is that this will provide a more robust check on automated merges down to our release branch.

I've got a partial Powershell API that hits the Azure DevOps REST API will get me a reference to the reviewer on the pull request, but I'm getting failures attempting to cast a vote or approval for the reviewer via the API.

The documentation suggests I need the reviewer Id to pass to the following URI

https://dev.azure.com/$organization/$projectId/_apis/git/repositories/$repositoryId/pullrequests/$pullRequestId/reviewers/$reviewerId?api-version=5.0

When I use the reviewer Id which I obtain from the pull request

https://dev.azure.com/$organization/$projectId/_apis/git/repositories/$repositoryId/pullrequests

reviewerUrl : https://dev.azure.com/my-organization/be283e5e-0466-41ef-aeb7-24264e12f6d6/_apis/git/repositories/3c4b0093-30fc-4652-a39e-08bb442b1879/pullRequests/2/reviewers/a72ce17b-22de-41a0-b6a5-49e5ba189826
vote        : 10
isRequired  : True
displayName : [email protected]
url         : https://spsprodcca1.vssps.visualstudio.com/A41d8d933-620f-4153-952c-4ee19c0e4c0b/_apis/Identities/a72ce17b-22de-41a0-b6a5-49e5ba189826
_links      : @{avatar=}
id          : a72ce17b-22de-41a0-b6a5-49e5ba189826
uniqueName  : [email protected]
imageUrl    : https://dev.azure.com/my-organization/_api/_common/identityImage?id=a72ce17b-22de-41a0-b6a5-49e5ba189826

I get the following error

"Invalid argument value.\r\nParameter name: A valid reviewer ID must be supplied."

I'm not sure if I'm going about this the right way, but I would like my Octopus Deployment to initiate functional tests in our target environment and then upon successful test completion, the pull request approval be granted for the automated test reviewer via the REST API.

All the documentation I can find ultimately points me back to this document, but I can't for the life of me see how to apply the approval for my reviewer.

https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull%20request%20reviewers/create%20pull%20request%20reviewer?view=azure-devops-rest-5.0

2
I can't reproduce the issue, I can run the api with reviewer id without any problems.Shayki Abramczyk
Is the reviewer id you use, the one you pull from the reviewer that's attached to the pull request? If not, where did you get it from?BenAlabaster
Yes, from the pull requests (but I added the PR id to the api to get only one PR details)Shayki Abramczyk
In the case of my example - is the id I use a72ce17b-22de-41a0-b6a5-49e5ba189826?BenAlabaster
Exactly, yes...Shayki Abramczyk

2 Answers

3
votes

I don't think that using a fake pull request reviewer is the way to go. Instead I suggest looking into extending the pull request workflow with a Pull Request status.

You use the Status API to add a custom status to your pull request. You call this before starting your tests (with a pending status) and once they are finished (succeeded or failed).

3
votes

A few things to note:

  1. Only the reviewer can post a status update, so the API call must use the PAT for the reviewer that wishes to approve the pull request.

  2. The reviewer that is approving the pull request must have contributor access to the repository in order to approve the pull request. If not, you will get errors.

  3. Ensure the reviewer was added to the pull request. For example add it as an automatic reviewer for the folder so that all pull requests automatically have it added.

  4. The reviewer found on the pull request ($pullRequest.reviewers) appears to have differences than if you use the API call to get the pull request reviewer directly.

  5. The PATCH version to update the pull request reviewers appears to cause errors when trying to update an existing reviewer. You must use the PUT to updated the pull request approval for an existing reviewer.

This is what I did to get it to work:

Administrative stuff:

  • Ensure reviewer has an account in Azure DevOps and has BASIC Access Level

  • Ensure reviewer is part of the project team and thus has contributor access to the Project, and most importantly can approve pull requests.

  • Ensure reviewer has a PAT token that can be used for API access.

API Stuff

  • GET Pull Request Reviewers for known pull request using the PAT assigned to the reviewer:

  • Update the reviewer votes to 10

  • Ensure the reviewer data is converted to JSON format correctly.

  • Ensure the headers you're passing with the PUT API call have the correct Authorization & Content-Type. "Basic <Base64String>" and "application/json"

function ConvertTo-Base64 {

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][System.String]$input)

    $inputBytes = [System.Text.Encoding]::ASCII.GetBytes($input);
    $inputBase64 = [System.Convert]::ToBase64String($inputBytes);
    return $inputBase64
}

function Get-AzureDevOpsPullRequestReviewer {

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][System.String]$token,
          [Parameter(Mandatory=$true)][System.String]$organization,
          [Parameter(Mandatory=$true)][System.String]$projectId,
          [Parameter(Mandatory=$true)][System.String]$repositoryId,
          [Parameter(Mandatory=$true)][System.String]$pullRequestId,
          [Parameter(Mandatory=$false)][System.String]$reviewerId=$null)

    $uri = "https://dev.azure.com/$organization/$projectId/_apis/git/repositories/$repositoryId/pullrequests/$pullrequestId/reviewers";

    if ($reviewerId) { $uri = "$uri/$reviewerId" }

    $uri = "$uri`?api-version=5.0";

    $tokenBase64 = ConvertTo-Base64(":$token");

    $headers = @{
        "Accept" = "application/json";
        "Authorization" = "Basic $tokenBase64";
    }

    $response = Invoke-WebRequest -Uri $uri -headers $headers;

    $content = ConvertFrom-Json($response.Content);
    if ($reviewerId) { return $content } else { return $content.value }
}

function Approve-AzureDevOpsPullRequest {

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][System.String]$token,
          [Parameter(Mandatory=$true)][System.String]$organization,
          [Parameter(Mandatory=$true)][System.String]$projectId,
          [Parameter(Mandatory=$true)][System.String]$repositoryId,
          [Parameter(Mandatory=$true)][System.String]$pullRequestId,
          [Parameter(Mandatory=$true)]$reviewer)

    $uri = "https://dev.azure.com/$organization/$projectId/_apis/git/repositories/$repositoryId/pullrequests/$pullRequestId/reviewers/$($reviewer.id)`?api-version=5.0"

    $tokenBase64 = ConvertTo-Base64(":$token");

    $headers = @{
        "Accept" = "application/json";
        "Authorization" = "Basic $tokenBase64";
        "Content-Type" = "application/json";
    }

    $body = ConvertTo-Json($reviewer);

    $response = Invoke-WebRequest -Uri $uri -headers $headers -body $body -Method Put

    return $response;
}

$myOrganization  = "benco-devops";
$myProjectId     = "47b0a6fc-a58f-4bbf-9950-2d5e33ae0587";
$myRepositoryId  = "1582ab2b-ae01-41e1-9695-f9966fdd7985";
$myReviewerId    = "[email protected]";
$myReviewerPAT   = "1z3xq9zmw1syznfhqzoeaoppbx2xsowvqscgnowuin7xkxk5fy7c";
$myPullRequestId = 2;

$reviewer = Get-AzureDevopsPullRequestReviewer -token $myReviewerPAT -organization $myOrganization -projectId $myProjectId -repositoryId $myRepositoryId -pullRequestId $myPullRequestId | ? uniqueId -eq $myReviewerId;

$reviewer.votes = 10;

Approve-AzureDevOpsPullRequest -token $myReviewerPAT -organization $myOrganization -projectId $myProjectId -repositoryId $myRepositoryId -pullRequestId $myPullRequestId -reviewer $reviewer;