Skip to content
This repository was archived by the owner on Mar 22, 2020. It is now read-only.

Commit 6cd6e23

Browse files
committed
bot
1 parent 42ea8ea commit 6cd6e23

10 files changed

Lines changed: 285 additions & 60 deletions

File tree

config.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const path = require('path');
22
const fs = require('fs');
3+
const _ = require('lodash');
34

45
const config = {
56
projectRoot: process.cwd(),
@@ -11,7 +12,20 @@ const config = {
1112
botUser: "javascript-translate-bot",
1213
repoSuffix: "javascript.info",
1314
langMain: "en",
14-
teamMain: "translate"
15+
teamMain: "translate",
16+
labels: _.keyBy([{
17+
name: "need +1",
18+
color: '3b22e2',
19+
}, {
20+
name: "review needed",
21+
color: 'b72d32'
22+
}, {
23+
name: "changes requested",
24+
color: '82ffdf'
25+
}, {
26+
name: 'ready to merge',
27+
color: '006400'
28+
}], 'name')
1529
};
1630

1731
config.langs = {};

handlers/hook.js

Lines changed: 141 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
11
const crypto = require('crypto');
22
const config = require('../config');
33
const debug = require('debug')('handlers:hook');
4+
const Octokit = require('@octokit/rest');
5+
const _ = require('lodash');
6+
const octokit = new Octokit({
7+
auth: `token ${config.secret.github.token}`,
8+
log: console,
9+
previews: ['hellcat-preview', 'mercy-preview'], // enables nested teams API
10+
});
11+
// chinese bot: https://github.com/fanyijihua/robot
12+
13+
async function removeLabel(labels, params) {
14+
return await octokit.issues.removeLabel({
15+
owner: config.org,
16+
...params
17+
});
18+
}
19+
20+
async function addLabels(params) {
21+
return await octokit.issues.removeLabel({
22+
owner: config.org,
23+
...params
24+
});
25+
}
426

527
exports.post = async function(ctx) {
628

@@ -22,40 +44,143 @@ exports.post = async function(ctx) {
2244

2345
//debug("github hook", ctx.request);
2446

25-
debug("Hook data", ctx.request.body);
26-
27-
let repo = config.secret.repos[ctx.request.body.repository.full_name];
28-
if (!repo.lang) {
29-
// __proto__ as repo name
30-
this.throw(400);
31-
}
3247

3348
// koa-bodyparser gives that
3449
debug(ctx.request.rawBody);
3550

3651
signature = signature.replace(/^sha1=/, '');
3752
let computedSignature = crypto
38-
.createHmac('sha1', Buffer.from(repo.githubSecret, 'utf-8'))
53+
.createHmac('sha1', Buffer.from(config.secret.github.hook, 'utf-8'))
3954
.update(ctx.request.rawBody)
4055
.digest('hex');
4156

57+
debug("Hook data", event, ctx.request.body);
58+
4259
debug("Compare signature", computedSignature, signature);
4360

4461
if (computedSignature !== signature) {
4562
ctx.throw(400, 'X-Hub-Signature does not match blob signature');
4663
}
4764

48-
if (ctx.request.body.ref !== 'refs/heads/master') {
49-
// ignore non-master pushes
50-
ctx.body = {ok: true};
51-
return;
52-
}
65+
let action = ctx.request.body.action;
5366

67+
// new pr
68+
if (event === 'pull_request' && action === 'opened') {
69+
await onPullOpen(ctx.request.body);
70+
}
5471

55-
ctx.body = {ok: true};
72+
// changes requested
73+
if (event === 'pull_request_review' && action === 'submitted') {
74+
await onPullRequestReviewSubmit(ctx.request.body);
75+
}
5676

57-
await updateRepo(ctx.request.body.repository.name);
77+
// /done
78+
if (event === 'issue_comment' && action === 'created') {
79+
await onIssueComment(ctx.request.body);
80+
}
5881

59-
await Stats.instance().gather(ctx.request.body.repository.name);
82+
ctx.body = '';
6083

6184
};
85+
86+
async function onIssueComment({issue, repository, comment}) {
87+
debug("Comment to Issue");
88+
89+
if (!issue.pull_request) {
90+
return; // comment to issue, not to PR?
91+
}
92+
93+
debug("Comment to PR");
94+
95+
let labels = _.keyBy(issue.labels, 'name');
96+
97+
if (comment.body.trim() === '/done') {
98+
await removeLabel({
99+
repo: repository.name,
100+
issue_number: issue.number,
101+
name: 'changes requested',
102+
});
103+
104+
await addLabels({
105+
repo: repository.name,
106+
issue_number: issue.number,
107+
labels: ['review needed'],
108+
});
109+
}
110+
}
111+
112+
async function onPullOpen({repository, number}) {
113+
debug("PR open");
114+
115+
await addLabels({
116+
repo: repository.name,
117+
issue_number: number,
118+
labels: ['review needed'],
119+
});
120+
}
121+
122+
async function onPullRequestReviewSubmit({repository, review, pull_request: {number, labels}}) {
123+
124+
debug("PR request submitted", review.state);
125+
126+
labels = _.keyBy(labels, 'name');
127+
128+
if (review.state === "changes_requested") {
129+
await removeLabel({
130+
repo: repository.name,
131+
issue_number: number,
132+
name: 'review needed',
133+
});
134+
135+
await addLabels({
136+
repo: repository.name,
137+
issue_number: number,
138+
labels: ['changes requested'],
139+
});
140+
}
141+
142+
if (review.state === "approved") {
143+
await removeLabel({
144+
repo: repository.name,
145+
issue_number: number,
146+
name: 'changes requested',
147+
});
148+
149+
debug("Labels", labels);
150+
151+
if (!labels['need +1']) {
152+
await removeLabel({
153+
repo: repository.name,
154+
issue_number: number,
155+
name: 'review needed'
156+
});
157+
await addLabels({
158+
repo: repository.name,
159+
issue_number: number,
160+
labels: ['need +1'],
161+
});
162+
} else {
163+
// maybe just merge on 2nd approval, so this never happens
164+
await removeLabel({
165+
repo: repository.name,
166+
issue_number: number,
167+
name: 'need +1'
168+
});
169+
await addLabels({
170+
repo: repository.name,
171+
issue_number: number,
172+
labels: ['ready to merge']
173+
});
174+
}
175+
}
176+
177+
}
178+
179+
180+
/**
181+
1) каждый PR помечается review needed
182+
2) когда ревьювер request changes, PR помечается changes requested
183+
3) когда чел вносит изменения, он пишет /done, и PR помечается review needed
184+
4) когда изменения приняты (changes approved) PR помечается +1 review needed
185+
5) то же самое еще раз для второго review (edited)
186+
*/

langs/ru.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Russian",
33
"code": "ru",
4-
"maintainers": ["iliakan", "lex111"],
4+
"maintainers": ["iliakan", "lex111", "dandgerson"],
55
"//": "An exception for Russian",
66
"published": "learn.javascript.ru"
77
}

lib/hookValidate.js

Whitespace-only changes.

lib/init/createReadme.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const path = require('path');
55
const fs = require('mz/fs');
66
const run = require('../run');
77
const ejs = require('ejs');
8-
const updateRepo = require('../updateRepo');
8+
const updateLocalRepo = require('../updateLocalRepo');
99
const findProgressIssue = require('../findProgressIssue');
1010

1111
const octokit = new Octokit({
@@ -40,7 +40,7 @@ module.exports = async function(langInfo) {
4040
progressIssue
4141
});
4242

43-
await updateRepo(langInfo.code);
43+
await updateLocalRepo(langInfo.code);
4444

4545
let readmePath = path.join(translatedPath, 'README.md');
4646
fs.writeFileSync(readmePath, text);

0 commit comments

Comments
 (0)