Skip to content

Commit 612ec49

Browse files
authored
bugfix: "the action skips PRs that is used to have request-for-change review" by @nafur
- bugfix: "the action skips PRs that is used to have `request-for-change` review" - deduplicate reviews by reviewer thanks @nafur
2 parents 83c61e2 + d9c35da commit 612ec49

File tree

2 files changed

+90
-10
lines changed

2 files changed

+90
-10
lines changed

src/lib/github.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,16 @@ export const getApprovalStatus = async (pullNumber) => {
115115
pull_number: pullNumber,
116116
});
117117

118+
let reviewers = new Set();
118119
let changesRequestedCount = 0;
119120
let approvalCount = 0;
120121

121-
reviewsData.forEach(({ state }) => {
122+
reviewsData.reverse().forEach(({ state, user }) => {
123+
if (reviewers.has(user.login)) return;
124+
if (!['CHANGES_REQUESTED', 'APPROVED'].includes(state)) return;
122125
if (state === 'CHANGES_REQUESTED') changesRequestedCount += 1;
123126
if (state === 'APPROVED') approvalCount += 1;
127+
reviewers.add(user.login);
124128
});
125129

126130
return {

src/lib/github.test.js

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ describe('getApprovalStatus()', () => {
243243
});
244244
});
245245

246-
describe('getAutoUpdateCanidate()', () => {
246+
describe('getAutoUpdateCandidate()', () => {
247247
const pullsList = require('../../test/fixtures/pulls_list.json');
248248
const reviewsList = require('../../test/fixtures/list_reviews.json');
249249
const prMetaData = require('../../test/fixtures/pr_metadata.json');
@@ -329,14 +329,43 @@ describe('getAutoUpdateCanidate()', () => {
329329
expect(mockedGet).toHaveBeenCalledTimes(0);
330330
expect(res).toBe(null);
331331
});
332+
333+
test('PR with approvals from a single users will not be selected', async () => {
334+
// 2 approvals, but from the same user
335+
const reviews = {
336+
...reviewsList,
337+
data: [
338+
{ ...reviewsList.data[0], state: 'APPROVED' },
339+
{ ...reviewsList.data[0], state: 'APPROVED' },
340+
],
341+
};
342+
const prList = [{ ...pullsList.data[0], auto_merge: {} }];
343+
const mockedListReviews = jest.fn().mockResolvedValue(reviews);
344+
const mockedGet = jest.fn();
345+
346+
github.getOctokit.mockReturnValue({
347+
pulls: { listReviews: mockedListReviews, get: mockedGet },
348+
});
349+
350+
const res = await gitLib.getAutoUpdateCandidate(prList);
351+
expect(mockedListReviews).toHaveBeenCalled();
352+
expect(utils.log).toHaveBeenCalledTimes(2);
353+
expect(utils.printFailReason).toHaveBeenCalledTimes(1);
354+
expect(utils.printFailReason).toHaveBeenCalledWith(
355+
prList[0].number,
356+
`approvalsCount: 1, requiredApprovalCount: ${requiredApprovalCount}, changesRequestedReviews: 0`,
357+
);
358+
expect(mockedGet).toHaveBeenCalledTimes(0);
359+
expect(res).toBe(null);
360+
});
332361

333362
test('PR with mergeable !== true will not be selected', async () => {
334363
// has 2 approvals, not request for change review
335364
const reviews = {
336365
...reviewsList,
337366
data: [
338367
{ ...reviewsList.data[0], state: 'APPROVED' },
339-
{ ...reviewsList.data[0], state: 'APPROVED' },
368+
{ ...reviewsList.data[1], state: 'APPROVED' },
340369
],
341370
};
342371
const prData = {
@@ -369,7 +398,7 @@ describe('getAutoUpdateCanidate()', () => {
369398
...reviewsList,
370399
data: [
371400
{ ...reviewsList.data[0], state: 'APPROVED' },
372-
{ ...reviewsList.data[0], state: 'APPROVED' },
401+
{ ...reviewsList.data[1], state: 'APPROVED' },
373402
],
374403
};
375404
// pr mergeable: true, merge_state: clean
@@ -397,13 +426,13 @@ describe('getAutoUpdateCanidate()', () => {
397426
expect(res).toBe(null);
398427
});
399428

400-
test('PR with failed checks wonnt be selected', async () => {
429+
test('PR with failed checks wont be selected', async () => {
401430
// has 2 approvals, no request for change review
402431
const reviews = {
403432
...reviewsList,
404433
data: [
405434
{ ...reviewsList.data[0], state: 'APPROVED' },
406-
{ ...reviewsList.data[0], state: 'APPROVED' },
435+
{ ...reviewsList.data[1], state: 'APPROVED' },
407436
],
408437
};
409438
// pr mergeable: true, merge_state: clean
@@ -452,7 +481,7 @@ describe('getAutoUpdateCanidate()', () => {
452481
...reviewsList,
453482
data: [
454483
{ ...reviewsList.data[0], state: 'APPROVED' },
455-
{ ...reviewsList.data[0], state: 'APPROVED' },
484+
{ ...reviewsList.data[1], state: 'APPROVED' },
456485
],
457486
};
458487
// pr mergeable: true, merge_state: clean
@@ -489,13 +518,60 @@ describe('getAutoUpdateCanidate()', () => {
489518
const res = await gitLib.getAutoUpdateCandidate(prList);
490519
expect(res).toBe(prList[0]);
491520
});
521+
522+
test('Should ignore trailing comment reviews', async () => {
523+
// has approvals, and some reviews at the end
524+
const reviews = {
525+
...reviewsList,
526+
data: [
527+
{ ...reviewsList.data[0], state: 'APPROVED' },
528+
{ ...reviewsList.data[1], state: 'APPROVED' },
529+
{ ...reviewsList.data[0], state: 'COMMENTED' },
530+
{ ...reviewsList.data[2], state: 'COMMENTED' },
531+
],
532+
};
533+
// pr mergeable: true, merge_state: clean
534+
const prData = {
535+
data: {
536+
...prMetaData.data,
537+
...{ mergeable: true, mergeable_state: 'behind' },
538+
},
539+
};
540+
541+
const check = checksList.data.check_runs[0];
542+
const checks = {
543+
...checksList,
544+
data: {
545+
total_count: 2,
546+
check_runs: [
547+
{ ...check, conclusion: 'success' },
548+
{ ...check, conclusion: 'success' },
549+
],
550+
},
551+
};
552+
553+
// has auto-merge PR
554+
const prList = [{ ...pullsList.data[0], auto_merge: {} }];
555+
const mockedListReviews = jest.fn().mockResolvedValue(reviews);
556+
const mockedGet = jest.fn().mockResolvedValue(prData);
557+
const mockedListForRef = jest.fn().mockResolvedValue(checks);
558+
559+
github.getOctokit.mockReturnValue({
560+
pulls: { listReviews: mockedListReviews, get: mockedGet },
561+
checks: { listForRef: mockedListForRef },
562+
});
563+
564+
const res = await gitLib.getAutoUpdateCandidate(prList);
565+
expect(res).toEqual(prList[0]);
566+
});
567+
492568
test('Should return the first PR if it is all good', async () => {
493569
// has 2 approvals, no request for change review
494570
const reviews = {
495571
...reviewsList,
496572
data: [
497573
{ ...reviewsList.data[0], state: 'APPROVED' },
498-
{ ...reviewsList.data[0], state: 'APPROVED' },
574+
{ ...reviewsList.data[1], state: 'APPROVED' },
499575
],
500576
};
501577
// pr mergeable: true, merge_state: clean
@@ -541,14 +617,14 @@ describe('getAutoUpdateCanidate()', () => {
541617
...reviewsList,
542618
data: [
543619
{ ...reviewsList.data[0], state: 'APPROVED' },
544-
{ ...reviewsList.data[0], state: 'CHANGES_REQUESTED' },
620+
{ ...reviewsList.data[1], state: 'CHANGES_REQUESTED' },
545621
],
546622
};
547623
const reviewsSecond = {
548624
...reviewsList,
549625
data: [
550626
{ ...reviewsList.data[0], state: 'APPROVED' },
551-
{ ...reviewsList.data[0], state: 'APPROVED' },
627+
{ ...reviewsList.data[1], state: 'APPROVED' },
552628
],
553629
};
554630
// pr mergeable: true, merge_state: clean

0 commit comments

Comments
 (0)