Created
April 4, 2019 16:18
-
-
Save heybenchen/c88e2cc14bc4f8cd2ca594fb9c66ad60 to your computer and use it in GitHub Desktop.
PR Review Bot
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
var express = require('express'); | |
var Webtask = require('webtask-tools'); | |
var bodyParser = require('body-parser'); | |
var urlParse = require('url-parse'); | |
var rp = require('request-promise'); | |
var app = express(); | |
app.use(bodyParser.urlencoded({extended: true})); | |
app.use(bodyParser.json()); | |
app.post('/event', function(req, res) { | |
if (req.body.challenge) { return res.json({challenge: req.body.challenge}); } | |
var prUrl = req.body.event.links[0].url; | |
return fetchGithubPrAndRespond(req.webtaskContext.secrets, prUrl, res); | |
// TODO: To make this work, we have to return a response within 3 seconds. | |
// Let's return a button to convert to Github link instead of trying to fetch PR right away. | |
}); | |
app.post('/create', function(req, res) { | |
var body = req.body; | |
if (!verifyToken(body.token, req)) { return res.status(401); } | |
var prUrl = body.text; | |
return fetchGithubPrAndRespond(req.webtaskContext.secrets, prUrl, res); | |
}); | |
app.post('/update', function(req, res) { | |
var parsedPayload = JSON.parse(req.body.payload); | |
if (!verifyToken(parsedPayload.token, req)) { return res.status(401); } | |
var action = parsedPayload.actions[0].name; | |
var prUrl = parsedPayload.actions[0].value; | |
switch (action) { | |
case 'refresh': | |
return fetchGithubPrAndRespond(req.webtaskContext.secrets, prUrl, res, false); | |
case 'bump': | |
return fetchGithubPrAndRespond(req.webtaskContext.secrets, prUrl, res, true); | |
default: | |
return res.status(500).json({error: "Invalid action type"}); | |
} | |
}); | |
function verifyToken(token, req) { | |
return token === req.webtaskContext.secrets.SLACK_TOKEN; | |
} | |
function parsePRUrl(url) { | |
var parsedUrl = urlParse(url); | |
if (parsedUrl.host === 'github.com') { | |
return parsePathname(parsedUrl.pathname); | |
} | |
return null; | |
} | |
function parsePathname(pathname) { | |
var sections = pathname.split('/'); | |
return { | |
org: sections[1], | |
repo: sections[2], | |
pr: sections[4], | |
}; | |
// TODO: input validation | |
} | |
function fetchGithubPrAndRespond(secrets, prUrl, res, isBump) { | |
var gUrl = parsePRUrl(prUrl); | |
fetchGithubPr(secrets, gUrl.org, gUrl.repo, gUrl.pr) | |
.then(response => { | |
var parsed = JSON.parse(response); | |
res.json(buildPrResponse(parsed, isBump)); | |
}).catch(error => { | |
console.log('ERROR: ' + error); | |
res.status(500).json({error: error}); | |
}); | |
} | |
function fetchGithubPr(secrets, org, repo, pr) { | |
var username = secrets.GITHUB_USERNAME; | |
var password = secrets.GITHUB_PASSWORD; | |
var githubApiUrl = "https://" + username + ":" + password + "@api.github.com/repos/" + org + "/" + repo + "/pulls/" + pr; | |
var options = { | |
url: githubApiUrl, | |
headers: { | |
'User-Agent': 'GetReview' | |
} | |
}; | |
return rp(options); | |
} | |
function buildPrResponse(parsedResponse, isBump) { | |
var title = parsedResponse.title + " [+" + parsedResponse.additions + "/-" + parsedResponse.deletions + "]"; | |
var text = truncateText(parsedResponse.body, 250); | |
return { | |
replace_original: isBump ? false : true, | |
response_type: "in_channel", | |
text: isBump ? "*Bump:*" : "", | |
mrkdwn: true, | |
attachments: [ | |
{ | |
author_name: parsedResponse.user.login, | |
author_link: parsedResponse.user.url, | |
author_icon: parsedResponse.user.avatar_url, | |
title: title, | |
title_link: parsedResponse.html_url, | |
text: text, | |
callback_id: "update", | |
fallback: "Review this PR", | |
attachment_type: "default", | |
actions: [ | |
{ | |
name: "refresh", | |
text: "Refresh", | |
type: "button", | |
value: parsedResponse.html_url | |
}, | |
{ | |
name: "bump", | |
text: "Bump", | |
type: "button", | |
style: "danger", | |
value: parsedResponse.html_url | |
} | |
] | |
} | |
] | |
}; | |
} | |
function truncateText(text, limit) { | |
return text.substring(0, limit) + "..."; | |
} | |
module.exports = Webtask.fromExpress(app); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment