Skip to content

Instantly share code, notes, and snippets.

@pyokagan
Last active August 26, 2017 16:14
Show Gist options
  • Save pyokagan/9ddfb783047e737bee98bb613f0ab002 to your computer and use it in GitHub Desktop.
Save pyokagan/9ddfb783047e737bee98bb613f0ab002 to your computer and use it in GitHub Desktop.
GitHub PR summary generator
<!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