Skip to content

Commit

Permalink
Implement allow_duplicate
Browse files Browse the repository at this point in the history
Introduce a new option `allow_duplicate` (`true` by default). If it is
`true` the behavior keeps the same. When it is `false`, the review is
only sent if there not already a review by `github-actions` with the
same body and type.

Closes AndrewMusgrave#39
  • Loading branch information
Ana06 committed May 19, 2021
1 parent 5351aff commit 4c2cdd8
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 22 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
event: APPROVE
body: 'Thank you dependabot 🎊'
allow_duplicate: false
```
## Workflow options
These are the options recommended to be changed. For more detailed explanation of the workflow file, check out the [GitHub documentation](https://help.github.com/en/articles/configuring-a-workflow#creating-a-workflow-file).
| Setting | Description | Values |
| ------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------ |
| `event` | The event to perform on the pull request review. | APPROVE \| COMMENT \| DISMISS \| REQUEST_CHANGES |
| `body` | The contents of the review body comment. Required when event is COMMENT or REQUEST_CHANGES | String |
| `repo-token` | The personal access token | `${{ secrets.GITHUB_TOKEN }}` |
| Setting | Description | Values |
| ----------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------ |
| `event` | The event to perform on the pull request review. | APPROVE \| COMMENT \| DISMISS \| REQUEST_CHANGES |
| `body` | The contents of the review body comment. Required when event is COMMENT or REQUEST_CHANGES | String |
| `allow_duplicate` | The review is sent more than once. `true` by default. | `true` or `false` |
| `repo-token` | The personal access token | `${{ secrets.GITHUB_TOKEN }}` |
2 changes: 2 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ inputs:
default: 'APPROVE'
body:
description: 'The contents of the review body comment. Required when event is COMMENT or REQUEST_CHANGES.'
allow_duplicate:
default: true
repo-token:
description: 'The GH_TOKEN secret can be passed in using {{ secrets.GH_TOKEN }}'
required: true
4 changes: 2 additions & 2 deletions dist/index.js

Large diffs are not rendered by default.

85 changes: 72 additions & 13 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,78 @@
import * as core from '@actions/core';
import * as github from '@actions/github';

/** Returns true if any review in the reviews array has author's login
'github-actions' and the body given as parameter */
function isAnyDuplicatedReview(reviews: Array<any>, body: string): boolean {
for (let review of reviews) {
if(review.author.login === 'github-actions' && review.body === body){
core.info('Duplicated review');
return true;
}
}
core.info('No duplicated review');
return false;
}

/** Gets the PR reviews by querying the GitHub API (GraphQL) and calls
isAnyDuplicatedReview to know if any of them is a duplicate */
async function existsDuplicatedReview(octokit: any, reviewState: string, pullRequest: any, body: string): Promise<boolean | undefined > {
const repo = pullRequest.base.repo
const query = `
query {
repository(owner: "${repo.owner.login}", name: "${repo.name}") {
pullRequest(number: ${pullRequest.number}) {
reviews(last: 100, states: ${reviewState}) {
nodes {
author {
login
}
body
}
}
}
}
}`;

try {
const { repository } = await octokit.graphql(query, {});
const reviews = repository.pullRequest.reviews.nodes
return isAnyDuplicatedReview(reviews, body);
}
catch (err) {
core.error(`${err} ${query}`);
core.setFailed(err.message);
}
}

/** Send the review if there is not a duplicate or if duplicates are allowes */
async function sendReview(octokit: any, reviewState: string, pullRequest: any, body: string, allow_duplicate: boolean): Promise<void> {
if(allow_duplicate || !(await existsDuplicatedReview(octokit, reviewState, pullRequest, body))) {
const query = `
mutation {
addPullRequestReview(input: {
pullRequestId: "${(<any>pullRequest)['node_id']}",
event: ${requestEvent},
body: "${body}"
}) {clientMutationId}
}`;
octokit.graphql(query).catch((err: Error) => {
core.error(`${err} ${query}`);
core.setFailed(err.message);
});
}
}

const token = core.getInput('repo-token');
const requestEvent = core.getInput('event');
const body = core.getInput('body');
const allow_duplicate = core.getInput('allow_duplicate').toUpperCase() === 'TRUE';
const pullRequestReviewState : Record<string, string> = {
APPROVE: 'APPROVED',
COMMENT: 'COMMENTED',
DISMISS: 'DISMISSED',
REQUEST_CHANGES: 'CHANGES_REQUESTED'
}

const octokit = github.getOctokit(token)

Expand All @@ -20,16 +89,6 @@ if (!pullRequest) {
core.setFailed('This action is meant to be ran on pull requests');
}

const query = `
mutation {
addPullRequestReview(input: {
pullRequestId: "${(<any>pullRequest)['node_id']}",
event: ${requestEvent},
body: "${body}"
}) {clientMutationId}
}`;

octokit.graphql(query).catch((err) => {
core.error(err);
core.setFailed(err.message);
});

const reviewState = pullRequestReviewState[requestEvent];
sendReview(octokit, reviewState, pullRequest, body, allow_duplicate);
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"homepage": "https://github.com/andrewmusgrave/automatic-pull-request-review#readme",
"dependencies": {
"@actions/core": "^1.2.7",
"@actions/github": "^4.0.0"
"@actions/github": "^4.0.0",
"@octokit/webhooks": "^9.6.1"
},
"devDependencies": {
"@types/node": "^12.7.4",
Expand All @@ -41,4 +42,4 @@
"pre-commit": "npm run build && git add ./dist/index.js"
}
}
}
}

0 comments on commit 4c2cdd8

Please sign in to comment.