Skip to content

Commit b9c443b

Browse files
authored
fix(pr_checker): do not count non-approving reviews (#680)
Before this commit, any review after the last commit would disable the warning and let the CQ land the PR. This commit makes sure that only approving reviews from collaborators are taken into account to decide if a PR is ready to land.
1 parent e0d6d0d commit b9c443b

8 files changed

+57
-12
lines changed

lib/pr_checker.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ const FAST_TRACK_RE = /^Fast-track has been requested by @(.+?)\. Please 👍 to
3030
const FAST_TRACK_MIN_APPROVALS = 2;
3131
const GIT_CONFIG_GUIDE_URL = 'https://github.com/nodejs/node/blob/99b1ada/doc/guides/contributing/pull-requests.md#step-1-fork';
3232

33+
// eslint-disable-next-line no-extend-native
34+
Array.prototype.findLastIndex ??= function findLastIndex(fn) {
35+
const reversedIndex = Reflect.apply(
36+
Array.prototype.findIndex,
37+
this.slice().reverse(),
38+
arguments);
39+
return reversedIndex === -1 ? -1 : this.length - reversedIndex - 1;
40+
};
41+
3342
export default class PRChecker {
3443
/**
3544
* @param {{}} cli
@@ -520,11 +529,14 @@ export default class PRChecker {
520529
} = this;
521530
const { maxCommits } = argv;
522531

523-
if (reviews.length < 1) {
532+
const reviewIndex = reviews.findLastIndex(
533+
review => review.authorCanPushToRepository && review.state === 'APPROVED'
534+
);
535+
536+
if (reviewIndex === -1) {
524537
return false;
525538
}
526539

527-
const reviewIndex = reviews.length - 1;
528540
const reviewDate = reviews[reviewIndex].publishedAt;
529541

530542
const afterCommits = [];
@@ -537,7 +549,7 @@ export default class PRChecker {
537549

538550
const totalCommits = afterCommits.length;
539551
if (totalCommits > 0) {
540-
cli.warn('Commits were pushed since the last review:');
552+
cli.warn('Commits were pushed since the last approving review:');
541553
const sliceLength = maxCommits === 0 ? totalCommits : -maxCommits;
542554
afterCommits.slice(sliceLength)
543555
.forEach(commit => {

lib/queries/Reviews.gql

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ query Reviews($prid: Int!, $owner: String!, $repo: String!, $after: String) {
1313
author {
1414
login
1515
}
16+
authorCanPushToRepository
1617
url
1718
publishedAt
1819
}

test/fixtures/more_than_three_commits_after_review_reviews.json

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"author": {
55
"login": "foo"
66
},
7+
"authorCanPushToRepository": true,
78
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-89923489",
89
"publishedAt": "2017-07-23T11:19:25Z"
910
}]

test/fixtures/multiple_commits_after_review_reviews.json

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"author": {
55
"login": "foo"
66
},
7+
"authorCanPushToRepository": true,
78
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-89923489",
89
"publishedAt": "2017-09-23T11:19:25Z"
910
}]

test/fixtures/reviews_approved.json

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"author": {
55
"login": "foo"
66
},
7+
"authorCanPushToRepository": true,
78
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71480624",
89
"publishedAt": "2017-10-24T11:19:00Z"
910
},
@@ -13,6 +14,7 @@
1314
"author": {
1415
"login": "Baz"
1516
},
17+
"authorCanPushToRepository": true,
1618
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71488392",
1719
"publishedAt": "2017-10-24T11:50:52Z"
1820
},
@@ -22,6 +24,7 @@
2224
"author": {
2325
"login": "Baz"
2426
},
27+
"authorCanPushToRepository": true,
2528
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-714882992",
2629
"publishedAt": "2017-10-24T12:30:52Z"
2730
},
@@ -31,6 +34,7 @@
3134
"author": {
3235
"login": "Quux"
3336
},
37+
"authorCanPushToRepository": true,
3438
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71817236",
3539
"publishedAt": "2017-10-24T14:49:01Z"
3640
},
@@ -40,6 +44,7 @@
4044
"author": {
4145
"login": "Baz"
4246
},
47+
"authorCanPushToRepository": true,
4348
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71488236",
4449
"publishedAt": "2017-10-24T14:49:02Z"
4550
},
@@ -49,6 +54,7 @@
4954
"author": {
5055
"login": "Quo"
5156
},
57+
"authorCanPushToRepository": true,
5258
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71817236",
5359
"publishedAt": "2017-10-24T19:09:52Z"
5460
},
@@ -58,6 +64,7 @@
5864
"author": {
5965
"login": "bot"
6066
},
67+
"authorCanPushToRepository": true,
6168
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71839232",
6269
"publishedAt": "2017-10-28T19:21:52Z"
6370
}]

test/fixtures/reviews_requesting_changes.json

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"author": {
66
"login": "foo"
77
},
8+
"authorCanPushToRepository": true,
89
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71480624",
910
"publishedAt": "2017-10-24T11:19:25Z"
1011
},
@@ -14,6 +15,7 @@
1415
"author": {
1516
"login": "Baz"
1617
},
18+
"authorCanPushToRepository": true,
1719
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71488392",
1820
"publishedAt": "2017-10-24T11:50:52Z"
1921
},
@@ -23,6 +25,7 @@
2325
"author": {
2426
"login": "Baz"
2527
},
28+
"authorCanPushToRepository": true,
2629
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-714882992",
2730
"publishedAt": "2017-10-24T12:30:52Z"
2831
},
@@ -32,6 +35,7 @@
3235
"author": {
3336
"login": "Quo"
3437
},
38+
"authorCanPushToRepository": true,
3539
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71817236",
3640
"publishedAt": "2017-10-24T19:09:52Z"
3741
},
@@ -41,6 +45,7 @@
4145
"author": {
4246
"login": "bot"
4347
},
48+
"authorCanPushToRepository": true,
4449
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71839232",
4550
"publishedAt": "2017-10-24T19:21:52Z"
4651
},
@@ -50,6 +55,7 @@
5055
"author": {
5156
"login": "bar"
5257
},
58+
"authorCanPushToRepository": true,
5359
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71482624",
5460
"publishedAt": "2017-10-24T11:27:02Z"
5561
}]

test/fixtures/single_commit_after_review_reviews.json

+19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@
44
"author": {
55
"login": "foo"
66
},
7+
"authorCanPushToRepository": true,
78
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71480624",
89
"publishedAt": "2017-10-24T11:19:25Z"
10+
},{
11+
"bodyText": "Not sure about that last change",
12+
"state": "COMMENTED",
13+
"author": {
14+
"login": "foo"
15+
},
16+
"authorCanPushToRepository": true,
17+
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71480625",
18+
"publishedAt": "2017-10-26T11:19:25Z"
19+
},{
20+
"bodyText": "Good idea",
21+
"state": "APPROVED",
22+
"author": {
23+
"login": "bar"
24+
},
25+
"authorCanPushToRepository": false,
26+
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71480626",
27+
"publishedAt": "2017-10-26T11:19:25Z"
928
}]

test/unit/pr_checker.test.js

+7-9
Original file line numberDiff line numberDiff line change
@@ -2059,7 +2059,7 @@ describe('PRChecker', () => {
20592059

20602060
const expectedLogs = {
20612061
warn: [
2062-
['Commits were pushed since the last review:'],
2062+
['Commits were pushed since the last approving review:'],
20632063
['- src: fix issue with es-modules']
20642064
],
20652065
info: [],
@@ -2091,7 +2091,7 @@ describe('PRChecker', () => {
20912091

20922092
const expectedLogs = {
20932093
warn: [
2094-
['Commits were pushed since the last review:'],
2094+
['Commits were pushed since the last approving review:'],
20952095
['- src: add requested feature'],
20962096
['- nit: edit mistakes']
20972097
],
@@ -2122,7 +2122,7 @@ describe('PRChecker', () => {
21222122
const { commits, reviews } = moreThanThreeCommitsAfterReview;
21232123
const expectedLogs = {
21242124
warn: [
2125-
['Commits were pushed since the last review:'],
2125+
['Commits were pushed since the last approving review:'],
21262126
['- src: add requested feature'],
21272127
['- nit: edit mistakes'],
21282128
['- final: we should be good to go'],
@@ -2180,20 +2180,18 @@ describe('PRChecker', () => {
21802180
commits: simpleCommits,
21812181
collaborators,
21822182
authorIsNew: () => true,
2183-
getThread() {
2184-
return PRData.prototype.getThread.call(this);
2185-
}
2183+
getThread: PRData.prototype.getThread
21862184
}, {}, argv);
21872185

21882186
const status = checker.checkCommitsAfterReview();
2189-
assert.deepStrictEqual(status, true);
2187+
assert.strictEqual(status, true);
21902188
});
21912189

21922190
it('should log as expected if passed 1 as flag', () => {
21932191
const { commits, reviews } = moreThanThreeCommitsAfterReview;
21942192
const expectedLogs = {
21952193
warn: [
2196-
['Commits were pushed since the last review:'],
2194+
['Commits were pushed since the last approving review:'],
21972195
['- final: we should be good to go'],
21982196
['...(use `--max-commits 4` to see the full list of commits)']
21992197
],
@@ -2224,7 +2222,7 @@ describe('PRChecker', () => {
22242222
const { commits, reviews } = moreThanThreeCommitsAfterReview;
22252223
const expectedLogs = {
22262224
warn: [
2227-
['Commits were pushed since the last review:'],
2225+
['Commits were pushed since the last approving review:'],
22282226
['...(use `--max-commits 4` to see the full list of commits)']
22292227
],
22302228
info: [],

0 commit comments

Comments
 (0)