Skip to content

Instantly share code, notes, and snippets.

@larsiusprime
Last active August 29, 2015 14:18
Show Gist options
  • Save larsiusprime/3d6242d3d57896596bbe to your computer and use it in GitHub Desktop.
Save larsiusprime/3d6242d3d57896596bbe to your computer and use it in GitHub Desktop.
A script for calculating the number of "points" in a Github Milestone (using numeric labels as "points" in issues). Written by Adam Perry (@hoursgoby) for Level Up Labs, LLC. milestones.json is an example of the php output, progress.js is an example of the front-end display code
<?php
define("CLIENT_ID", "REDACTED");
define("CLIENT_SECRET", "REDACTED");
define("GITHUB_URL", "ssl://api.github.com");
define("GITHUB_PATH", "/repos/YOUR-NAME-HERE/YOUR-REPO-HERE/");
define("ISSUESTATE_OPEN", "open");
define("OUTPUT_FILENAME", "/path/to/milestones.json");
$milestones = processIssues(loadIssues());
$fp = fopen(OUTPUT_FILENAME, "w+");
fwrite($fp, json_encode($milestones));
fclose($fp);
echo json_encode($milestones) ."\r\n\r\n";
function loadIssues() {
$i = 1;
$issues = array();
$page = loadIssuePage($i);
while(!empty($page)) {
if (!empty($page["message"])) {
echo "ERROR: API call failed with the following message:\r\n";
echo $page["message"] ."\r\n";
break;
}
$issues = array_merge($issues, $page);
echo "Loaded page $i (". count($page) ." issues)\r\n";
++$i;
$page = loadIssuePage($i);
}
return $issues;
}
function loadIssuePage($i) {
return wget("issues?state=all&page=". intval($i));
}
function processIssues($issues) {
$milestones = array();
foreach($issues as $i => $issue) {
if (empty($issue["milestone"]) || empty($issue["milestone"]["title"])) continue;
$val = 0;
$milestone = $issue["milestone"]["title"];
if (!array_key_exists($milestone, $milestones)) {
$milestones[$milestone] = array();
$milestones[$milestone]["open"] = 0;
$milestones[$milestone]["total"] = 0;
}
$labels = wget("issues/". intval($i) ."/labels");
if (!empty($labels["message"])) {
echo "ERROR: API call for issue $i failed with the following message:\r\n";
echo $labels["message"] ."\r\n";
continue;
}
foreach($labels as $label) {
if (!empty($label["name"]) && intval($label["name"])) {
$val = intval($label["name"]);
}
}
$milestones[$milestone]["total"] += $val;
if (!empty($issue["state"]) && $issue["state"] == ISSUESTATE_OPEN) {
$milestones[$milestone]["open"] += $val;
}
$milestones[$milestone]["milestone_number"] = $issue["milestone"]["number"];
$s = ($val == 1) ? "" : "s";
echo "Assessed issue $i ($milestone: $val point$s)\r\n";
}
return $milestones;
}
function wget($url) {
$out = "";
$fp = fsockopen(GITHUB_URL, 443, $errno, $errstr, 3);
if (!$fp) {
echo "$errstr ($errno)\r\n";
return false;
} else {
$param = "?";
if (strpos($url, "?") !== false) $param = "&";
$param .= "client_id=". CLIENT_ID ."&client_secret=". CLIENT_SECRET;
$url .= $param;
$out = "GET ". GITHUB_PATH . $url ." HTTP/1.1\r\n";
$out.= "Host: api.github.com\r\n";
$out.= "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1)\r\n";
$out.= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while(!feof($fp)) {
$out .= fgets($fp, 128);
}
fclose($fp);
$out = substr($out, strpos($out, "\r\n\r\n", strpos($out, "Content")));
return json_decode($out, true);
}
}
{"Alpha":{"open":83,"total":447,"milestone_number":4},"DQ1 port":{"open":12,"total":109,"milestone_number":6},"3DS Release":{"open":0,"total":3,"milestone_number":10},"DQ Legacy final patch":{"open":0,"total":16,"milestone_number":1},"Pre-Alpha":{"open":0,"total":45,"milestone_number":5}}
<script type="text/javascript">
loadMilestonesByPoints();
function loadMilestonesByPoints()
{
var progress_text = "";
var iURL = "https://github.com/YOUR-NAME-HERE/YOUR-REPO-HERE/issues";
var str = httpGet("http://www.example.com/path/to/milestones.json");
var milestones = JSON.parse(str);
//put your own milestone names in here, needs to match what you have on Github, including case!
var major_milestones = ["Pre-Alpha","Alpha","Beta","PC Release","DQ1 port"];
var closed_milestones = [];
var arrayLength = milestones.length;
var curr_milestone = "";
for(var i = 0; i < major_milestones.length; i++)
{
var mName = major_milestones[i];
var milestone = milestones[mName];
if(milestone != null)
{
var output = "";
var total = milestone["total"];
var closed = total - milestone["open"];
if(total > 5)
{
var percent = Math.floor(((closed/total)*100));
var mi = milestone["milestone_number"];
var closed_issues = "<a href="+iURL+"?milestone="+mi+"&state=closed/>"+closed+"</a>";
var total_issues = "<a href="+iURL+"?milestone="+mi+"&state=open/>"+total;
output += "<B>"+mName+"</B>" + ": " + closed_issues + " / " + total_issues + " points</a>";
if(percent >= 100)
{
output += " -- <B>Complete!</b>";
closed_milestones.push(mName.toLowerCase());
}
output += "<BR>";
progress_text += output;
progress_text += drawProgress((closed/total)*100);
progress_text += "<BR>";
}
}
}
var mmlength = major_milestones.length;
for(var i = 0; i < mmlength; i++)
{
var mName = major_milestones[i].toLowerCase();
var cmlength = closed_milestones.length;
for(var j = 0; j < cmlength; j++)
{
if(closed_milestones[j] == mName)
{
curr_milestone = mName;
}
}
}
var milestone_text = "<b>Current Phase: " + curr_milestone.toUpperCase() + "</b> <a href='https://github.com/larsiusprime/tdrpg-bugs/milestones'><BR>(See all milestones)</a>";
document.write(milestone_text + "<BR><BR>");
document.write("Please note that these bars are only a rough indicator of progress, as when we add new issues, the % completion may appear to shrink<BR><BR>");
document.write(progress_text);
}
//requires you to have the correct image files for the progress bars!
//progress.png -- 1x20 colored green gradient (what I used)
//progress-bkg.png -- 1x20 solid black
function drawProgress(percent)
{
var str = '<div id="container" style="width:100%; height:25px; border:2px solid black; background-size:100% 100%; background-repeat:no-repeat; background-image:url(image/progress-bkg.png);">';
if(percent > 0)
{
str += '<div id="a" style="width:'+percent+'%; height:25px; background-size:100% 100%; background-repeat:no-repeat; background-image:url(image/progress.png);"></div>';
}
str += '</div>';
return (str);
}
function httpGet(theUrl)
{
var xmlHttp = null;
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false );
xmlHttp.send( null );
return xmlHttp.responseText;
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment