Skip to content
10 changes: 8 additions & 2 deletions lib/args.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ function buildYargs(args = null) {
describe: 'File to write the metadata in',
type: 'string'
})
.option('comments', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather let this be --check-comments with no aliases, in case we need the c later. This does not seem to be very in demand.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your desires are my commands!

alias: 'c',
demandOption: false,
describe: 'Check for\'LGTM\' in comments',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above^

type: 'boolean'
})
.help()
.alias('help', 'h')
.argv;
Expand All @@ -47,8 +53,8 @@ const PR_RE = new RegExp(
'([0-9]+)(?:/(?:files)?)?$');

function checkAndParseArgs(args) {
const { owner = 'nodejs', repo = 'node', identifier, file } = args;
const result = { owner, repo, file };
const { owner = 'nodejs', repo = 'node', identifier, file, comments } = args;
const result = { owner, repo, file, comments };
if (!isNaN(identifier)) {
result.prid = +identifier;
} else {
Expand Down
19 changes: 11 additions & 8 deletions lib/pr_checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const WEEKDAY_WAIT = 48;
const WEEKEND_WAIT = 72;

const {
REVIEW_SOURCES: { FROM_COMMENT }
REVIEW_SOURCES: { FROM_COMMENT, FROM_REVIEW_COMMENT }
} = require('./reviews');
const {
FIRST_TIME_CONTRIBUTOR, FIRST_TIMER
Expand Down Expand Up @@ -45,9 +45,9 @@ class PRChecker {
);
}

checkAll() {
checkAll(comments = false) {
const status = [
this.checkReviews(),
this.checkReviews(comments),
this.checkCommitsAfterReview(),
this.checkPRWait(new Date()),
this.checkCI()
Expand Down Expand Up @@ -75,7 +75,7 @@ class PRChecker {
return hint;
}

checkReviews() {
checkReviews(comments = false) {
const {
pr, logger, reviewers: { rejected, approved }
} = this;
Expand All @@ -98,10 +98,13 @@ class PRChecker {
let hint = this.getTSCHint(approved);
logger.info(`Approvals: ${approved.length}${hint}`);

for (const { reviewer, review } of approved) {
if (review.source === FROM_COMMENT) {
logger.info(
`${reviewer.getName()}) approved in via LGTM in comments`);
if (comments) {
for (const {reviewer, review} of approved) {
if (review.source === FROM_COMMENT ||
review.source === FROM_REVIEW_COMMENT) {
logger.warn(
`${reviewer.getName()}) approved in via LGTM in comments`);
}
}
}

Expand Down
41 changes: 36 additions & 5 deletions lib/reviews.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ const {
} = require('./review_state');
const { isCollaborator } = require('./collaborators');
const { ascending } = require('./comp');
const LGTM_RE = /(\W|^)lgtm(\W|$)/i;
const LGTM_RE = /^lgtm\W?$/i;
const FROM_REVIEW = 'review';
const FROM_COMMENT = 'comment';
const FROM_REVIEW_COMMENT = 'review_comment';

class Review {
/**
Expand Down Expand Up @@ -55,7 +56,14 @@ class ReviewAnalyzer {
const map = new Map();
const collaborators = this.collaborators;
const list = this.reviews
.filter((r) => r.state !== PENDING && r.state !== COMMENTED)
.filter((r) => r.state !== PENDING)
.filter((r) => {
if (r.state === COMMENTED) {
return this.isApprovedInComment(r);
} else {
return true;
}
})
.filter((r) => {
return (isCollaborator(collaborators, r.author));
}).sort((a, b) => {
Expand All @@ -80,6 +88,12 @@ class ReviewAnalyzer {
new Review(r.state, r.publishedAt, r.url, FROM_REVIEW)
);
break;
case COMMENTED:
map.set(
login,
new Review(APPROVED, r.publishedAt, r.bodyText, FROM_REVIEW_COMMENT)
);
break;
case DISMISSED:
// TODO: check the state of the dismissed review?
map.delete(login);
Expand All @@ -97,7 +111,7 @@ class ReviewAnalyzer {
updateMapByRawReviews(oldMap) {
const comments = this.comments;
const collaborators = this.collaborators;
const withLgtm = comments.filter((c) => LGTM_RE.test(c.bodyText))
const withLgtm = comments.filter((c) => this.hasLGTM(c))
.filter((c) => {
return (isCollaborator(collaborators, c.author));
}).sort((a, b) => {
Expand Down Expand Up @@ -133,17 +147,34 @@ class ReviewAnalyzer {
for (const [ login, review ] of reviewers) {
const reviewer = collaborators.get(login.toLowerCase());
if (review.state === APPROVED) {
result.approved.push({ reviewer, review });
result.approved.push({reviewer, review});
} else if (review.state === CHANGES_REQUESTED) {
result.rejected.push({ reviewer, review });
}
}
return result;
}

/**
* @param review
* @returns {boolean}
*/
isApprovedInComment(review) {
return review.state === COMMENTED && this.hasLGTM(review);
}

/**
* @param object
* @param prop: string
* @returns {boolean}
*/
hasLGTM(object) {
return LGTM_RE.test(object.bodyText.trim());
}
}

const REVIEW_SOURCES = {
FROM_COMMENT, FROM_REVIEW
FROM_COMMENT, FROM_REVIEW, FROM_REVIEW_COMMENT
};

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion steps/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module.exports = async function getMetadata(argv, logger) {
}, 'Generated metadata:');

const checker = new PRChecker(logger, data);
const status = checker.checkAll();
const status = checker.checkAll(argv.comments);
return {
status,
request,
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/README/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ For more information about the governance of the Node.js project, see
**Foo User** <[email protected]> (she/her)
* [Quo](https://github.com/quo) -
**Quo User** <[email protected]> (she/her)
* [Quux](https://github.com/quux) -
**Quux User** <[email protected]> (he/him)

### Collaborator Emeriti

Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/collaborators.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,11 @@
"name": "Quo User",
"email": "[email protected]",
"type": "COLLABORATOR"
},
{
"login": "Quux",
"name": "Quux User",
"email": "[email protected]",
"type": "COLLABORATOR"
}
]
14 changes: 14 additions & 0 deletions test/fixtures/reviewers_approved.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@
"source": "review"
}
},
{
"reviewer": {
"login": "Quux",
"name": "Quux User",
"email": "[email protected]",
"type": "COLLABORATOR"
},
"review": {
"state": "APPROVED",
"date": "2017-10-24T14:49:52Z",
"ref": "LGTM",
"source": "review_comment"
}
},
{
"reviewer": {
"login": "Baz",
Expand Down
9 changes: 9 additions & 0 deletions test/fixtures/reviews_approved.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71488236",
"publishedAt": "2017-10-24T14:49:52Z"
},
{
"bodyText": "LGTM",
"state": "COMMENTED",
"author": {
"login": "Quux"
},
"url": "https://github.com/nodejs/node/pull/16438#pullrequestreview-71817236",
"publishedAt": "2017-10-24T14:49:52Z"
},
{
"bodyText": "A few nits",
"state": "COMMENTED",
Expand Down
1 change: 1 addition & 0 deletions test/unit/args.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const parseArgs = require('../../lib/args');
const assert = require('assert');

const expected = {
comments: false,
owner: `nodejs`,
repo: `node`,
prid: 16637,
Expand Down
1 change: 1 addition & 0 deletions test/unit/metadata_gen.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const expected = `PR-URL: https://github.com/nodejs/node/pull/16438
Fixes: https://github.com/nodejs/node/issues/16437
Refs: https://github.com/nodejs/node/pull/15148
Reviewed-By: Foo User <[email protected]>
Reviewed-By: Quux User <[email protected]>
Reviewed-By: Baz User <[email protected]>
Reviewed-By: Bar User <[email protected]>
`;
Expand Down
7 changes: 4 additions & 3 deletions test/unit/pr_checker.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,13 @@ describe('PRChecker', () => {

const expectedLogs = {
warn: [
['Quux User(Quux)) approved in via LGTM in comments'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a redundant ) here..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this redundant parens is in every test and is in fact in the base template :D
I'll remove it everywhere.

['Bar User(bar)) approved in via LGTM in comments'],
['semver-major requires at least two TSC approvals']
],
info: [
['Rejections: 0'],
['Approvals: 3, 1 from TSC (bar)'],
['Bar User(bar)) approved in via LGTM in comments']
['Approvals: 4, 1 from TSC (bar)']
],
error: [],
trace: []
Expand All @@ -100,7 +101,7 @@ describe('PRChecker', () => {
collaborators
});

const status = checker.checkReviews();
const status = checker.checkReviews(true);
assert(!status);
assert.deepStrictEqual(logger.logs, expectedLogs);
});
Expand Down