-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(github-actions): create an action to rerequest reviews for post …
…approval changes for non-googlers For non-googlers, if a change occurs after the approval has been given, the latest review is rerequested to confirm that the approval still stands. For googlers, they can continue to make post approval changes as they have been.
- Loading branch information
1 parent
01bb903
commit f556a9a
Showing
9 changed files
with
30,777 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
name: Post Approval Changes | ||
|
||
on: [pull_request_target] | ||
|
||
# Declare default permissions as read only. | ||
permissions: read-all | ||
|
||
jobs: | ||
post_approval_changes: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2 | ||
- uses: ./github-actions/post-approval-changes | ||
with: | ||
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
load("//tools:defaults.bzl", "esbuild_checked_in") | ||
|
||
package(default_visibility = ["//github-actions/post-approval-changes:__subpackages__"]) | ||
|
||
esbuild_checked_in( | ||
name = "main", | ||
entry_point = "//github-actions/post-approval-changes/lib:main.ts", | ||
deps = [ | ||
"//github-actions/post-approval-changes/lib", | ||
], | ||
) | ||
|
||
esbuild_checked_in( | ||
name = "post", | ||
entry_point = "//github-actions/post-approval-changes/lib:post.ts", | ||
deps = [ | ||
"//github-actions/post-approval-changes/lib", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
name: 'Post Approval Changes' | ||
description: 'Ensure that unexpected post approval changes do not occur' | ||
author: 'Angular' | ||
inputs: | ||
angular-robot-key: | ||
description: 'The private key for the Angular Robot Github app.' | ||
required: true | ||
runs: | ||
using: 'node12' | ||
main: 'main.js' | ||
post: 'post.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
load("//tools:defaults.bzl", "ts_library") | ||
|
||
package(default_visibility = ["//github-actions/post-approval-changes:__subpackages__"]) | ||
|
||
ts_library( | ||
name = "lib", | ||
srcs = glob( | ||
["*.ts"], | ||
exclude = ["*.spec.ts"], | ||
), | ||
deps = [ | ||
"//github-actions:utils", | ||
"@npm//@actions/core", | ||
"@npm//@actions/github", | ||
"@npm//@octokit/rest", | ||
"@npm//@octokit/webhooks-types", | ||
"@npm//@types/node", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import * as core from '@actions/core'; | ||
import {context} from '@actions/github'; | ||
import {PullRequestEvent} from '@octokit/webhooks-types'; | ||
import {Octokit} from '@octokit/rest'; | ||
import {ANGULAR_ROBOT, getAuthTokenFor} from '../../utils'; | ||
|
||
/** Allow list of googlers whose pull request are allowed to include post approval changes. */ | ||
const googlers = [ | ||
'alan-agius4', | ||
'alxhub', | ||
'amysorto', | ||
'AndrewKushnir', | ||
'andrewseguin', | ||
'atscott', | ||
'clydin', | ||
'crisbeto', | ||
'devversion', | ||
'dgp1130', | ||
'dylhunn', | ||
'jelbourn', | ||
'jessicajaniuk', | ||
'josephperrott', | ||
'madleinas', | ||
'MarkTechson', | ||
'mgechev', | ||
'mmalerba', | ||
'pkozlowski-opensource', | ||
'thevis', | ||
'trekladyone', | ||
'twersky', | ||
'wagnermaciel', | ||
'zarend', | ||
]; | ||
|
||
async function run(): Promise<void> { | ||
if (context.eventName !== 'pull_request_target') { | ||
throw Error('This action can only run for with pull_request_target events'); | ||
} | ||
const {pull_request: pr} = context.payload as PullRequestEvent; | ||
|
||
if (googlers.includes(pr.user.login)) { | ||
core.info('PR author is a googler, skipping as post approval changes are allowed.'); | ||
return; | ||
} | ||
|
||
if ([...pr.requested_reviewers, pr.requested_teams].length > 0) { | ||
core.info('Skipping check as there are still pending reviews.'); | ||
return; | ||
} | ||
|
||
/** Authenticated Github client. */ | ||
const client = new Octokit({auth: await getAuthTokenFor(ANGULAR_ROBOT)}); | ||
/** The repository and owner for the pull request. */ | ||
const {repo, owner} = context.issue; | ||
/** The number of the pull request. */ | ||
const pull_number = context.issue.number; | ||
|
||
/** List of reviews for the pull request. */ | ||
const allReviews = await client.paginate(client.pulls.listReviews, {owner, pull_number, repo}); | ||
/** Set of reviewers whose latest review has already been processed. */ | ||
const knownReviewers = new Set<string>(); | ||
/** The latest approving reviews for each reviewer on the pull request. */ | ||
const reviews = allReviews | ||
// Use new instance of array before reversing it. | ||
.concat() | ||
.reverse() | ||
.filter((review) => { | ||
/** The username of the reviewer, since all reviewers are users this should always exist. */ | ||
const user = review.user!.login; | ||
// Only consider reviews by Googlers for this check. | ||
if (!googlers.includes(user)) { | ||
return false; | ||
} | ||
if (knownReviewers.has(user)) { | ||
return false; | ||
} | ||
knownReviewers.add(user); | ||
return true; | ||
}); | ||
|
||
if (reviews.length === 0) { | ||
core.info('Skipping check as their are no reviews on the pull request.'); | ||
return; | ||
} | ||
|
||
if (reviews.filter((review) => review.state !== 'APPROVED')) { | ||
core.info('Skipping check as there are still non-approved review states.'); | ||
return; | ||
} | ||
|
||
if (reviews.find((review) => review.commit_id === pr.head.sha)) { | ||
core.info(`Passing check as at least one reviews is for the latest commit on the pull request`); | ||
return; | ||
} | ||
|
||
const reviewToRerequest = reviews[0]; | ||
core.info(`Requesting a new review from ${reviewToRerequest.user!.login}`); | ||
await client.pulls.requestReviewers({ | ||
owner, | ||
pull_number, | ||
repo, | ||
reviewers: [reviewToRerequest.user!.login], | ||
}); | ||
} | ||
|
||
// Only run if the action is executed in a repository with is in the Angular org. This is in place | ||
// to prevent the action from actually running in a fork of a repository with this action set up. | ||
// Runs triggered via 'workflow_dispatch' are also allowed to run. | ||
if (context.repo.owner === 'angular') { | ||
run(); | ||
} else { | ||
core.warning( | ||
'Post Approvals changes check was skipped as this action is only meant to run in repos ' + | ||
'belonging to the Angular organization.', | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import {revokeAuthTokenFor, ANGULAR_LOCK_BOT} from '../../utils'; | ||
|
||
async function run(): Promise<void> { | ||
await revokeAuthTokenFor(ANGULAR_LOCK_BOT); | ||
} | ||
|
||
run(); |
Oops, something went wrong.