azure-devopsazure-pipelines

How to use Azure DevOps REST API to post link in PR comments from Azure Pipeline?


parameters:
      comment: >
        {
          "comments": [
            {
              "parentCommentId": 0,
              "content": "<a href\=\"$(taskUrl)\">Click here to see colored output of Terraform plan:</a>\\n\`\`\`hcl$(plan)\`\`\`",
              "commentType": "system"
            }
          ],
          "status": "byDesign"
        }

...some template...

  curl --fail \
    --request POST "$URL" \
    --header "Authorization: Bearer ${{ parameters.accessToken }}" \
    --header "Content-Type: application/json" \
    --data @- <<- EOF
  ${{ parameters.comment }}
  EOF

This is my code, doesn't work.

I think Azure Pipelines is sanitizing my code, when I inspect the element there's nothing after href, completely deleted.

At the same time, I've tried with Markdown [example](https://link.com), but I get parsing error due to ().

Tried escaping them, but this also doesn't work. I actually tried everything I could think of for one week straight. Couldn't find any solution


Solution

  • I have no issues commenting on the PR using the script you provided. I suspect the value of your variable $(taskUrL) doesn't have a value.

    In the following template, I'm using a job template so that I can write the variables into the job.

    parameters:
    - name: taskUrl
      type: string
    
    - name: hclPlan
      type: string
    
    - name: comment
      type: string
      default: |-
        {
          "comments": [
            {
            "parentCommentId": 0,
              "content": "<a href=\"$(taskUrl)\">$(hclPlan)</a>",
              "commentType": "system"
            }
          ],
          "status": "byDesign"
        }
    
    jobs:
    - job: displayjob
      variables:
        taskUrl: ${{ parameters.taskUrl }}
        hclPlan: ${{ parameters.hclPlan }}
      steps:
      - script: |
          baseUrl="$(System.TeamCollectionUri)/$(System.TeamProject)"
          apiUrl="/_apis/git/repositories/$(Build.Repository.Id)/pullRequests/$(System.PullRequest.Id)/threads?api-version=6.0"
          url = $baseUrl$apiUrl
          curl --fail \
            --request POST "$url" \
            --header "Authorization: Bearer $(System.AccessToken)" \
            --header "Content-Type: application/json" \
            --data @- <<- EOF
          ${{ parameters.comment }}
          EOF
    

    Under the hood, here's the order of operations:

    1. At compile time, the template is expanded and the values of the expressions are written into the YAML. At this time $(taskUrl) has no value because it's a runtime value.
    2. The script task pre-processes the inline script as it appears in the YAML and replaces all references of variables written in macro syntax $(<variable-name>) with their runtime values.
    3. The script task writes the resulting script to disk as a temporary file and then executes it.