-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from deptofdefense/updates
Slight refactor handler.js
- Loading branch information
Showing
2 changed files
with
107 additions
and
92 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,63 @@ | ||
'use strict'; | ||
|
||
const https = require('https'); | ||
const crypto = require('crypto'); | ||
const url = require('url'); | ||
|
||
// Commentary and postComment func adopted from | ||
// Commentary and postComment func adopted from | ||
// https://github.com/christo4ferris/dco-check-bot/blob/master/bot.js (Apache 2.0) | ||
const dco_not_found = '\n\nPlease submit commits with a Signed-off-by statement in order to allow us to process your pull request.'; | ||
const dnf_tail1 =' For example a comment on the last line of your request like this:\n`Signed-off-by: Bob Bobertown <[email protected]>`'; | ||
const dnf_tail2 ='\n\nEnsure you supply a valid e-mail with the comment. These commands may be useful:'; | ||
const dnf_tail3 ='\n```git commit --amend --signoff```\nor\n```git filter-branch -f --commit-filter \'git commit-tree -S "$@"\' HEAD```' | ||
const dnf_tail =` For example a comment on the last line of your request like this: | ||
\`Signed-off-by: Bob Boberton <[email protected]>\` | ||
Ensure you supply a valid e-mail with the comment. These commands may be useful: | ||
\`\`\` | ||
git commit --amend --signoff | ||
\`\`\` | ||
or | ||
\`\`\` | ||
git filter-branch -f --commit-filter 'git commit-tree -S "$@"' HEAD | ||
\`\`\` | ||
`; | ||
const dco_found = '\n\nI can confirm that a sign-off has been included. It is okay to process this pull request.'; | ||
const greeting = 'Hi '; | ||
const thanks = ',\n\nThanks for submitting this pull request!'; | ||
const signature = '\n\ndco-bot'; | ||
|
||
const regex = /^Signed-off-by: .*<[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}>$/im; | ||
const regex = /Signed-off-by: .*<[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}>$/im; | ||
const regexPath = /[^/]*$/; | ||
|
||
var goodChain = true; | ||
var optionsTemplate = { | ||
hostname: 'api.github.com', | ||
method: 'POST', | ||
headers: { | ||
'User-Agent': 'dco-bot', | ||
'Authorization': "token " + process.env.GITHUB_SECRET | ||
} | ||
const optionsTemplate = { | ||
hostname: 'api.github.com', | ||
method: 'POST', | ||
headers: { | ||
'User-Agent': 'dco-bot', | ||
Authorization: `token ${process.env.GITHUB_SECRET}`, | ||
}, | ||
}; | ||
function deleteComments(payload,callback){ | ||
var options = Object.assign({},optionsTemplate,{ | ||
function deleteComments(payload, callback) { | ||
const options = Object.assign({}, optionsTemplate, { | ||
path: url.parse(payload.pull_request.comments_url).pathname, | ||
method: 'GET' | ||
method: 'GET', | ||
}); | ||
var req = https.request(options, function(res) { | ||
var comments = ''; | ||
res.on('data', function (chunk) { | ||
const req = https.request(options, (res) => { | ||
let comments = ''; | ||
res.on('data', (chunk) => { | ||
comments += chunk; | ||
}); | ||
res.on('end',function(){ | ||
var commentsObj = JSON.parse(comments); | ||
commentsObj = commentsObj.filter(function(a){ | ||
var body = a.body.split('\n'); | ||
return body[body.length-1] == 'dco-bot'; | ||
res.on('end', () => { | ||
let commentsObj = JSON.parse(comments); | ||
commentsObj = commentsObj.filter((a) => { | ||
const body = a.body.split('\n'); | ||
return body[body.length - 1] === 'dco-bot'; | ||
}); | ||
|
||
for(var i = 0 ; i < commentsObj.length ; i++ ){ | ||
var options = Object.assign({},optionsTemplate,{ | ||
path: url.parse(commentsObj[i].url).pathname, | ||
method: 'DELETE' | ||
}); | ||
var req2 = https.request(options); | ||
req2.end(); | ||
for (const comment of commentsObj) { | ||
const options2 = Object.assign({}, optionsTemplate, { | ||
path: url.parse(comment.url).pathname, | ||
method: 'DELETE', | ||
}); | ||
const req2 = https.request(options2); | ||
req2.end(); | ||
} | ||
callback(); | ||
}); | ||
|
@@ -57,28 +66,28 @@ function deleteComments(payload,callback){ | |
} | ||
|
||
function postComment(payload, msg, callback) { | ||
var tmp = {}; | ||
const tmp = {}; | ||
tmp.body = greeting + payload.pull_request.user.login + thanks + msg + signature; | ||
var postData = JSON.stringify(tmp); | ||
var options = Object.assign({},optionsTemplate,{ | ||
const postData = JSON.stringify(tmp); | ||
const options = Object.assign({}, optionsTemplate, { | ||
path: url.parse(payload.pull_request.comments_url).pathname, | ||
}); | ||
console.log('posting to: ' + payload.pull_request.comments_url + ' data: ' + postData); | ||
var req = https.request(options, function(res) { | ||
console.log('STATUS: ' + res.statusCode); | ||
if (res.statusCode != 201) { | ||
console.log('HEADERS: ' + JSON.stringify(res.headers)); | ||
console.log(`posting to: ${payload.pull_request.comments_url} data: ${postData}`); | ||
const req = https.request(options, (res) => { | ||
console.log(`STATUS: ${res.statusCode}`); | ||
if (res.statusCode !== 201) { | ||
console.log(`HEADERS: ${JSON.stringify(res.headers)}`); | ||
} | ||
res.on('end',function(){ | ||
console.log("Returning callback"); | ||
callback(null, | ||
{statusCode: 200, | ||
body:"Comment complete: " + payload.pull_request.comments_url }); | ||
res.on('end', () => { | ||
console.log('Returning callback'); | ||
callback(null, | ||
{ statusCode: 200, | ||
body: `Comment complete: ${payload.pull_request.comments_url}` }); | ||
}); | ||
}); | ||
req.on('error', function(e) { | ||
console.log('unable to post comment: ' + e.message); | ||
errMsg = '[502] Unable to post comment: ' + e.message; | ||
req.on('error', (e) => { | ||
console.log(`unable to post comment: ${e.message}`); | ||
const errMsg = `[502] Unable to post comment: ${e.message}`; | ||
callback(new Error(errMsg)); | ||
}); | ||
req.end(postData); | ||
|
@@ -87,74 +96,75 @@ function postComment(payload, msg, callback) { | |
// Used as inspiration (CC) | ||
// http://www.slideshare.net/jsquyres/fun-with-github-webhooks-verifying-signedoffby | ||
function getCommits(payload, msg, callback) { | ||
var options = Object.assign({},optionsTemplate,{ | ||
let goodChain = true; | ||
const options = Object.assign({}, optionsTemplate, { | ||
path: url.parse(payload.pull_request.commits_url).pathname, | ||
method: 'GET' | ||
method: 'GET', | ||
}); | ||
console.log('COMMITS: ' + payload.pull_request.commits_url); | ||
var req = https.get(options, function (res) { | ||
var commitBody = ''; | ||
console.log('STATUS: ' + res.statusCode); | ||
if (res.statusCode != 200) { | ||
console.log('HEADERS: ' + JSON.stringify(res.headers)); | ||
console.log(`COMMITS: ${payload.pull_request.commits_url}`); | ||
const req = https.get(options, (res) => { | ||
let commitBody = ''; | ||
console.log(`STATUS: ${res.statusCode}`); | ||
if (res.statusCode !== 200) { | ||
console.log(`HEADERS: ${JSON.stringify(res.headers)}`); | ||
} | ||
res.setEncoding('utf8'); | ||
res.on('data', function (chunk) { | ||
res.on('data', (chunk) => { | ||
commitBody += chunk; | ||
}); | ||
res.on('end', function(){ | ||
var commits = JSON.parse(commitBody); | ||
var body = { | ||
"target_url": "https://github.com/deptofdefense/code.mil", | ||
"description": "All commits up to this point been signed off.", | ||
"context": "DCO" | ||
res.on('end', () => { | ||
const commits = JSON.parse(commitBody); | ||
const body = { | ||
target_url: 'https://github.com/deptofdefense/code.mil', | ||
description: 'All commits up to this point been signed off.', | ||
context: 'DCO', | ||
}; | ||
var badSha; | ||
const path = url.parse(payload.pull_request.statuses_url).pathname.replace(regexPath,''); | ||
for(var i = 0 ; i < commits.length ; i++){ | ||
var sha = commits[i].sha; | ||
var options = Object.assign({},optionsTemplate,{path:path + sha}); | ||
var bodyLines = commits[i].commit.message.split('\n'); | ||
var sigLine = bodyLines[bodyLines.length-1]; // Perhaps it can occur anywhere? | ||
var req2 = https.request(options,function(res2){ | ||
req2.on('error',function(e){console.log("error: ",e)}); | ||
let badSha; | ||
const path = url.parse(payload.pull_request.statuses_url).pathname.replace(regexPath, ''); | ||
for (const commit of commits) { | ||
const options2 = Object.assign({}, optionsTemplate, { path: path + commit.sha }); | ||
const bodyLines = commit.commit.message.split('\n'); | ||
const sigLine = bodyLines[bodyLines.length - 1]; // Perhaps it can occur anywhere? | ||
const req2 = https.request(options2, () => { | ||
req2.on('error', (e) => { console.log('error: ', e); }); | ||
}); | ||
if (regex.test(sigLine) && (goodChain || (i != (commits.length - 1)))){ | ||
console.log("Setting ",sha," to success."); | ||
body.state = "success"; | ||
if (regex.test(sigLine) && (goodChain || (commit !== commits[commits.length - 1]))){ | ||
console.log('Setting ', commit.sha, ' to success.'); | ||
body.state = 'success'; | ||
} else { | ||
goodChain = false; | ||
badSha = badSha || sha; | ||
console.log("Setting ",sha," to error."); | ||
body.state = "error"; | ||
body.description = "A commit (" + badSha + ") is not signed off." | ||
goodChain = false; | ||
badSha = badSha || commit.sha; | ||
console.log('Setting ', commit.sha, ' to error.'); | ||
body.state = 'error'; | ||
body.description = `A commit (${badSha}) is not signed off.`; | ||
} | ||
req2.end(JSON.stringify(body)); | ||
} | ||
if (goodChain){ | ||
|
||
if (goodChain) { | ||
postComment( | ||
payload, | ||
dco_found, callback); | ||
} else { | ||
postComment( | ||
payload, | ||
dco_not_found+dnf_tail1+dnf_tail2+dnf_tail3, callback); | ||
dco_not_found + dnf_tail, callback); | ||
} | ||
}); | ||
}); | ||
req.on('error', function(e) { | ||
console.log('[502]: Unable to retrieve commits: ' + e.message); | ||
req.on('error', (e) => { | ||
console.log(`[502]: Unable to retrieve commits: ${e.message}`); | ||
}); | ||
} | ||
|
||
function signRequestBody(key, body) { | ||
return `sha1=${crypto.createHmac("sha1", key).update(JSON.stringify(body)).digest("hex")}`; | ||
return `sha1=${crypto.createHmac('sha1', key).update(JSON.stringify(body)).digest('hex')}`; | ||
} | ||
|
||
module.exports.dcobot = (event, context, callback) => { | ||
// Mangled and adopted (unknown license) from | ||
// Mangled and adopted (unknown license) from | ||
// https://raw.githubusercontent.com/serverless/examples/master/aws-node-github-webhook-listener/handler.js | ||
var errMsg; | ||
let errMsg; | ||
const token = process.env.GITHUB_WEBHOOK_SECRET; | ||
const headers = event.headers; | ||
const sig = headers['X-Hub-Signature']; | ||
|
@@ -184,13 +194,13 @@ module.exports.dcobot = (event, context, callback) => { | |
// event.body = JSON.parse(event.body); Not needed with serverless libraries. | ||
console.log(`Github-Event: "${githubEvent}" with action: "${event.body.action}"`); | ||
|
||
if (event.body.action != 'opened' && event.body.action != 'reopened' && event.body.action != 'synchronize'){ | ||
errMsg = '[202] No action required for ' + event.body.action; | ||
if (event.body.action !== 'opened' && event.body.action !== 'reopened' && event.body.action !== 'synchronize') { | ||
errMsg = `[202] No action required for ${event.body.action}`; | ||
return callback(new Error(errMsg)); | ||
} | ||
deleteComments(event.body,function(){ | ||
getCommits(event.body,'',callback); | ||
deleteComments(event.body, () => { | ||
getCommits(event.body, '', callback); | ||
}); | ||
return callback(null, {statusCode:200,body:'Success: ' + JSON.stringify(event.body)}); | ||
return callback(null, { statusCode: 200, body: `Success: ${JSON.stringify(event.body)}` }); | ||
}; | ||
|
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