How to create a comment in Azure DevOps PR in case of build failure?
Asked Answered
M

3

21

I have a custom build step that fails under certain conditions during my Pull Request build, within Azure DevOps.

I would like to extend it further by raising a PR comment, similar to this sort of thing in GitHub: https://developer.github.com/v3/issues/comments/#create-a-comment

I don't have code samples to add here as I could not find useful examples to build upon. I use PowerShell for my custom build step - how do I achieve this when running a PR build of my branch?

Mccrae answered 3/2, 2020 at 23:20 Comment(1)
Do you mean that you want to create a PR comment for the specific pull request in the PR build pipeline?Asir
J
50

I can help with an example. There is a bunch of value in posting custom messages\status to PRs from your pipelines.

First things first, make sure your build service has permissions to contribute to pull requests in your repository. (Go to Project Settings -> Repositories -> Security. The user is named <projectname> Build service)

permissions

Then you want to add a conditional PowerShell step. This one is just based on it being a PR build, but you might want to add a depends on failure for the previous step, based on your workflow.

- task: PowerShell@2
  condition: eq(variables['Build.Reason'], 'PullRequest')
  displayName: Post Message to PR
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)  
  inputs:
      targetType: filePath
      filePath: PostToPR.ps1

So the basic workflow is:

  • Build the Markdown Message
  • Build the JSON Body
  • Post the Message to the PR

PostToPR.ps1

#Going to create the comment in an Active state, assuming it needs to be resolved
#See https://learn.microsoft.com/en-us/dotnet/api/microsoft.teamfoundation.sourcecontrol.webapi.commentthreadstatus?view=azure-devops-dotnet
$StatusCode = 1 

$Stuff = $env:Build_Repository_Name
$Things = "Other things you might want in the message"

#Build Up a Markdown Message to 
$Markdown = @"
## Markdown Message here
|Column0 |Column1|
|--------|---------|
|$Stuff|$Things|  
"@

#Build the JSON body up
$body = @"
{
    "comments": [
      {
        "parentCommentId": 0,
        "content": "$Markdown",
        "commentType": 1
      }
    ],
    "status": $StatusCode 
  }
"@

Write-Debug $Body
#Post the message to the Pull Request
#https://learn.microsoft.com/en-us/rest/api/azure/devops/git/pull%20request%20threads?view=azure-devops-rest-5.1
try {
    $url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/git/repositories/$($env:Build_Repository_Name)/pullRequests/$($env:System_PullRequest_PullRequestId)/threads?api-version=5.1"
    Write-Host "URL: $url"
    $response = Invoke-RestMethod -Uri $url -Method POST -Headers @{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"} -Body $Body -ContentType application/json
  if ($response -ne $Null) {
    Write-Host "*******************Bingo*********************************"
  }
}
catch {
  Write-Error $_
  Write-Error $_.Exception.Message
}

And you end up with a nice markdown table with custom status information in your PR!

enter image description here

Jempty answered 4/2, 2020 at 2:43 Comment(5)
Fantastically in-depth but concise example! Thank you!Mccrae
I don't know if this is because I run that on Ubuntu build host, but Build_Repository_Name and System_PullRequest_PullRequestId have to be UPPER_CASED - otherwise there is no value.Kulp
This just totally helped me out - thank you sir :)Durer
To get the env:SYSTEM_ACCESSTOKEN accessible you need to enable the option in your Agent job, toggle the checkbox allow scripts to access the OAuth tokenExecutant
How to update comment when there is a new code change pushed to the PR?Foamy
J
10

Building on the great answers already provided, this is the equivalent inline YAML pipeline script:

  - powershell: |
      $body = @"
      {
          "comments": [
            {
              "parentCommentId": 0,
              "content": "Your comment here",
              "commentType": 1
            }
          ],
          "status": 4
        }
      "@
      $url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/git/repositories/$($env:Build_Repository_Name)/pullRequests/$($env:System_PullRequest_PullRequestId)/threads?api-version=5.1"
      $result = Invoke-RestMethod -Uri $url -Method POST -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Body $Body -ContentType application/json
    displayName: Post comment on PR
Juryman answered 4/1, 2021 at 14:15 Comment(1)
I had to use $env:BUILD_REPOSITORY_NAME and $env:env:SYSTEM_PULLREQUEST_PULLREQUESTIDKhalil
A
5

If you mean creating PR comment in the build pipeline, then you can add a PowerShell task in your pipeline and run the script to call the REST API (Pull Request Thread Comments - Create).

Below PowerShell script for your reference:

Param(
   [string]$baseurl = "https://dev.azure.com/{organization}",
   [string]$projectName = "0508-t",
   [string]$repositoryId = "62c8ce54-a7bb-4e08-8ed7-40b27831bd8b",
   [string]$pullRequestId = "35",
   [string]$threadId = "229",
   [string]$user = "",
   [string]$token = "PAT"  
)

# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
write-host $WorkitemType

#Create Jason body

function CreateJsonBody
{

    $value = @"
{
  "content": "Test Comment 0204",
  "parentCommentId": 1,
  "commentType": 1
}
"@

 return $value
}

$json = CreateJsonBody

$uri = "$baseurl/$projectName/_apis/git/repositories/$repositoryId/pullRequests/$pullRequestId/threads/$threadId/comments?api-version=5.1"
Write-Host $uri
$result = Invoke-RestMethod -Uri $uri -Method Post -Body $json -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}
Asir answered 4/2, 2020 at 3:9 Comment(1)
Great example. And very readable code too :) #UpvoteDaciadacie

© 2022 - 2024 — McMap. All rights reserved.