How to get count of approved pull request using github actions

Hello everyone, is there any way of counting the approved PR using github actions? I found this API
https://api.github.com/repos/projectname/reponame/pulls/16000/reviews . But this give me the complete history of PR like reviewer when commented on it and when he approved it, which is good. But how can I count the total number of approvals of specific PR?
Any suggestions please?

@so-amuk,
Currently, from the API (List review requests) or the github context, we only can get the pending approvals (the reviewers who have not approved the PR).

So every time when you execute the API or view the github context of a latest workflow run for the PR, you may get different result with previous.

Here I have two workarounds that are relying on jq:
(1) Read from the github context like as below.

echo '${{ toJson(github.event.pull_request.requested_reviewers) }}' | jq '. | length'

After you open a PR and have added all the reviewers on the PR, in the first workflow run for the PR, you can use this step to get the total count of the reviewers. Store and save this number via some way (such as cache) so that you can use it in the subsequent workflow runs for the PR.

In the subsequent workflow runs, if some reviewers have approved the PR, you will get the count of the rest reviewers who have not approved the PR. Subtract this count from the saved total count to get the count of approved.

(2) Read from the Response body of the API (List reviews on a pull request).

$response | ConvertTo-Json | jq '.[] | select(.state=="APPROVED") | length'

Every time when you execute this, it should return the count of approved.

1 Like

Thanks for the answer. Can you please tell me how do you store count number in cache and use it?

@brightran

@brightran I tried using 2nd approach here. I get one issue here. If single user has approved the same PR 10 times, then I am getting 10 Approvals for same user in this case.
The output would be something like:
{
“body”: “”,
“state”: “APPROVED”,
},
{
“body”: “”,
“state”: “APPROVED”,
},
{
“body”: “”,
“state”: “APPROVED”,
}
It shows history of the PR.
How to handle it?

@so-amuk,
Workaround 1: (update)

- name: get the count of requested reviewers
  run: |
    length=$(echo $requested_reviewers | jq '. | length')
    echo "length = $length"
  env:
    requested_reviewers: ${{ toJson(github.event.pull_request.requested_reviewers) }}

Can you please tell me how do you store count number in cache and use it?

You can simply write the total count of the reviewers into a text file, then save this text file as a cache with a specified key (for example, key: PR-<PR_number>-total-reviewers). In the subsequent workflow runs, you can restore this cache to the workspace and read the total count of the reviewers from the text file.
However, if some reviewers are added or removed halfway, there may be problems with the calculated numbers in the subsequent workflow runs. So the premise of the 1st workaround is that you will not add or remove reviewers halfway, and all the required reviewers need being added at the beginning.

I tried using 2nd approach here. I get one issue here.

Sorry for my mistake, I forget that the command “ConvertTo-Json” is used in PowerShell. If you have added “Content-Type: application/json” into the header of the API, you do not need to convert the response to JSON-type again.

Due to the current APIs are based on the review requests, not reviewers. One user may be requested as reviewer multiple times in a PR. So if a user has been requested multiple times, the APIs will return the approvals multiple times.

1 Like

Thanks @brightran for your answer and ConvertTo-Json is working fine. Finally I am able to call API and receive data.

name: Test Github actions
on: 
    pull_request_review:
      types: [submitted]
jobs:
    triggerJenkins:
        name: Trigger Jenkins
        runs-on: ubuntu-latest
        steps:
            -   name: trigger
                shell: pwsh
                run: | 
                    $uri = "https://api.github.com/repos/xyz/project/pulls/2/reviews"
                    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
                    $headers.Add("Authorization", "token xxxxxxx")
                    $headers.Add("Content-Type", "application/json")
                    $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method GET
                    echo $response | ConvertTo-Json | jq '.[] | select(.state=="APPROVED")' json

Now I am facing some new problem, and didn’t get any solution yet. Can you please have a look

jq: error: APPROVED/0 is not defined at , line 1:

@so-amuk,
Try this:

echo $response | ConvertTo-Json | jq '.[] | select(.state=="APPROVED")'

Or try cURL on bash:

      - name: List reviews on the pull request
        shell: bash
        run: |
          token=${{ secrets.GITHUB_TOKEN }}
          base64AuthInfo='$token | base64 -e'
          
          response=$(curl --request GET \
          --url https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews \
          --header 'Authorization: $base64AuthInfo' \
          --header 'Content-Type: application/json')

          echo $response | jq '.[] | select(.state=="APPROVED")'

But there is a problem I found, the select function will return each of the matched objects/elements in the array as an individual object, not group them into a new array. So in this way, it’s hard to get the number of the matched objects.
You may need use a loop to access the every element of the array, and check the value of state in each element and count the “APPROVED”.

1 Like

Thanks @brightran, really appreciated for your answer. This would help me to resolve my problem. Thanks!!

@so-amuk,
You’re welcome.