Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
8 changes: 1 addition & 7 deletions dist/index.js

Large diffs are not rendered by default.

91 changes: 76 additions & 15 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,84 @@
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 same body */
function isAnyDuplicatedReview(reviews: Array<any>): 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(): Promise<boolean | undefined > {
const repo = <any>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 = <Array<any>>repository.pullRequest.reviews.nodes;
return isAnyDuplicatedReview(reviews);
}
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(): Promise<void> {
if(allow_duplicate || !(await existsDuplicatedReview())) {
const query = `
mutation {
addPullRequestReview(input: {
pullRequestId: "${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 octokit = github.getOctokit(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 reviewState = pullRequestReviewState[requestEvent];

const octokit = github.getOctokit(token)
if(!reviewState){
core.setFailed('Invalid event type, allowed values: APPROVE, COMMENT, DISMISS, REQUEST_CHANGES')
}

if (
(requestEvent === 'COMMENT' || requestEvent === 'REQUEST_CHANGES') &&
Expand All @@ -14,22 +87,10 @@ if (
core.setFailed('Event type COMMENT & REQUEST_CHANGES require a body.');
}

const pullRequest = github.context.payload['pull_request'];
const pullRequest = <any>github.context.payload['pull_request'];

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);
});
sendReview();
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"
}
}
}
}