Using GitHub for planning

By: on October 20, 2012

An important part of delivering software is knowing how long it will take to deliver some piece of functionality. Today we will see a small GitHub hack to help control estimation.

It’s all very well knowing the parts we need to implement some system. We need to know how long it will take to build. To that end, several of LShift’s GitHub-hosted projects use numeric tags to indicate the size of a task – maybe it’s in perfect engineering days, or abstract points. Regardless, with a large number of tickets, we can’t easily see how much work we’ve signed up for.

Something that would really help in understanding how much work is left in a milestone is simply totalling up the estimates. Given 5 tasks of 0.5 days each, and 2 tasks of 1 day each, it’d be nice to see at a glance that we have 5 × 0.5 + 2 × 1 = 4.5 days’ worth of work left.

Handily, Chrome makes it really easy to write an extension to augment GitHub’s pages.

A manifest tells Chrome about the extension, including where to find any scripts:

  "name": "GitHub Planning Helper",
  "version": "1.0",
  "manifest_version": 1,
  "description": "Display the total estimate for your GitHub milestones.",
  "content_scripts": [
      "matches": [
      "js": ["src/add-numeric-tags.js"]

And a simple little script does the work:

// Find all the labels
var labels = document.getElementsByClassName('filter-item');
var total = 0.0;
for (var i = 0; i < labels.length; i++) {
  var element = labels[i];
  var scale = element.querySelector('.name');
  var count = element.querySelector('.count');
  if (scale && count) {
    scale = parseFloat(scale.innerHTML);
    count = parseInt(count.innerHTML);
    // Filter out any non-numeric labels.
    // Also, protect against with non-numeric counts (which shouldn't
    // happen, but...).
    if (!isNaN(scale) && !isNaN(count)) {
      total += scale * count;

var hangPoint = document.querySelector('.info-secondary');
var totalDescription = "Total estimate: " + total.toString();

if (!hangPoint) {
  var progBar = document.querySelector('.sidebar-milestone-widget');
  var fakeInfo = document.createElement('div');
  fakeInfo.className = 'info-secondary';
  hangPoint = fakeInfo;
} else {
  totalDescription = "| " + totalDescription;

var display = document.createElement('span');
display.innerHTML = totalDescription;
display.className = 'open';

It’s not perfect – it currently only works on page loads (and GitHub likes their partial page loads) – but it does the job.

You can find the extension hosted, naturally enough, on GitHub.


Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>