Last active
August 26, 2017 16:14
-
-
Save pyokagan/9ddfb783047e737bee98bb613f0ab002 to your computer and use it in GitHub Desktop.
GitHub PR summary generator
This file contains hidden or 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Github PR Commit Summary Generator</title> | |
<meta charset="utf-8"> | |
<script type="text/javascript"> | |
(function() { | |
/** | |
* Promise wrapper around XMLHttpRequest | |
*/ | |
function getJSON(url) { | |
return new Promise(function(resolve, reject) { | |
var xhr = new XMLHttpRequest(); | |
xhr.onload = function() { | |
if (xhr.readyState === 4 && xhr.status === 200) | |
resolve(JSON.parse(xhr.response)); | |
else | |
reject(new Error('Server returned ' + xhr.status + ' ' + xhr.statusText)); | |
}; | |
xhr.onerror = function() { | |
reject(new Error('An error occurred')); | |
}; | |
xhr.onabort = function() { | |
reject(new Error('Request was aborted')); | |
}; | |
xhr.open('GET', url, true); | |
xhr.send(); | |
}); | |
} | |
/** | |
* Parses a URL into its components. | |
*/ | |
function parseURL(url) { | |
var parser = document.createElement('a'); | |
parser.href = url; | |
return { | |
protocol: parser.protocol, // e.g. "http:" | |
hostname: parser.hostname, // e.g. "example.com" | |
port: parser.port, // e.g. "3000" | |
pathname: parser.pathname, // e.g. "/pathname" | |
search: parser.search, // e.g. "?search=test" | |
hash: parser.hash, // e.g. "#hash", | |
host: parser.host, // e.g. "example.com:3000" | |
}; | |
} | |
/** | |
* The Web PR URL is of the format: | |
* https://github.com/:owner/:repo/pull/:number | |
*/ | |
function parseWebPRURL(url) { | |
var comp = parseURL(url); | |
if (comp.host !== 'github.com') | |
throw new RangeError('host must be github.com'); | |
var pattern = /^\/*([^\/]+)\/+([^\/]+)\/+pull\/+(\d+)\/*$/; | |
var match = pattern.exec(comp.pathname); | |
if (!match) | |
throw new RangeError('invalid URL path'); | |
return { | |
owner: match[1], | |
repo: match[2], | |
nr: parseInt(match[3]), | |
}; | |
} | |
function getPRInfo(owner, repo, nr) { | |
var url = 'https://api.github.com/repos/' + owner + '/' + repo + '/pulls/' + nr; | |
return getJSON(url).then(function(r) { | |
return { | |
head: { | |
sha: r.head.sha, | |
owner: r.head.repo.owner.login, | |
repo: r.head.repo.name, | |
}, | |
base: { | |
sha: r.base.sha, | |
owner: r.base.repo.owner.login, | |
repo: r.base.repo.name, | |
}, | |
}; | |
}); | |
} | |
function getFirstLine(message) { | |
var idx = message.indexOf('\n'); | |
return idx >= 0 ? message.substring(0, idx) : message; | |
} | |
function getCommitList(baseOwner, baseRepo, baseSHA, headOwner, headSHA) { | |
var url = 'https://api.github.com/repos/' + baseOwner + '/' + baseRepo | |
+ '/compare/' + baseOwner + ':' + baseSHA + '...' + headOwner | |
+ ':' + headSHA; | |
return getJSON(url).then(function(r) { | |
var commits = r.commits, out = []; | |
for (var i = 0; i < commits.length; i++) { | |
out.push({ | |
subject: getFirstLine(commits[i].commit.message), | |
sha: commits[i].sha, | |
}); | |
} | |
return out; | |
}); | |
} | |
/** | |
* Format commit list in markdown format. | |
*/ | |
function formatCommitList(owner, repo, pullNR, commits) { | |
var out = []; | |
for (var i = 0; i < commits.length; i++) { | |
var commit = commits[i]; | |
var url = 'https://github.com/' + owner + '/' + repo + '/pull/' | |
+ pullNR + '/commits/' + commit.sha; | |
out.push('* [' + (i + 1) + '/' + commits.length + '] [' | |
+ commit.subject + '](' + url + ')\n'); | |
} | |
return out.join(''); | |
} | |
window.addEventListener('load', function() { | |
var form = document.forms['inputform']; | |
var urlInput = form.elements['url']; | |
var result = document.getElementById('result'); | |
form.addEventListener('submit', function(e) { | |
var owner, repo, pullNR; | |
e.preventDefault(); | |
result.value = 'Please wait...'; | |
(new Promise(function(resolve, reject) { | |
resolve(parseWebPRURL(urlInput.value)); | |
})).then(function(r) { | |
owner = r.owner; | |
repo = r.repo; | |
pullNR = r.nr; | |
return getPRInfo(r.owner, r.repo, r.nr); | |
}).then(function(r) { | |
return getCommitList(r.base.owner, r.base.repo, r.base.sha, | |
r.head.owner, r.head.sha); | |
}).then(function(commits) { | |
result.value = formatCommitList(owner, repo, pullNR, commits); | |
}).catch(function(e) { | |
result.value = e.toString(); | |
}); | |
}); | |
}); | |
})(); | |
</script> | |
</head> | |
<body> | |
<h1>Github PR Commit Summary Generator</h1> | |
<form name="inputform"> | |
<label>PR URL: <input name="url" type="text"></label> | |
<input type="submit" value="Generate commit summary"> | |
</form> | |
<textarea id="result" readonly rows="40" style="width: 100%; box-sizing: border-box;"></textarea> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment