Skip to content

Instantly share code, notes, and snippets.

@bkeepers
Last active August 29, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bkeepers/dcbe02de43056ab6ebdb to your computer and use it in GitHub Desktop.
Save bkeepers/dcbe02de43056ab6ebdb to your computer and use it in GitHub Desktop.

Issue and Pull Request Age

#!/usr/bin/env ruby
# Usage: GITHUB_TOKEN=yourtoken data.rb owner/repo
require 'fileutils'
require 'csv'
def fetch(*parts, &block)
key = File.join("tmp/cache", *parts)
Marshal.load(File.read(key))
rescue
FileUtils.mkdir_p File.dirname(key)
block.call.tap do |result|
File.write key, Marshal.dump(result)
end
end
class Issues < Array
def open_on(date)
Issues.new(select do |issue|
issue.created_at.to_date <= date && (!issue.closed_at || issue.closed_at.to_date >= date)
end)
end
end
def age(issues, date)
values = issues.map do |issue|
date - issue.created_at.to_date
end
values.reduce(:+).to_i
end
require "octokit"
client = Octokit::Client.new(:access_token => ENV["GITHUB_TOKEN"], :auto_paginate => true)
issues = Issues.new(fetch(ARGV[0], 'all-issues') { client.issues(ARGV[0], :state => 'all') })
pulls = Issues.new(fetch(ARGV[0], 'all-pulls') { client.pulls(ARGV[0], :state => 'all') })
tsv = CSV.generate(:col_sep => "\t") do |csv|
csv << ["date", "Issues", "Pull Requests"]
((Date.today - 180)..Date.today).each do |date|
csv << [date, age(issues.open_on(date), date), age(pulls.open_on(date), date)]
end
end
File.write 'data.tsv', tsv
date Issues Pull Requests
2014-05-15 19158 4223
2014-05-16 19321 4271
2014-05-17 19488 4321
2014-05-18 19656 4372
2014-05-19 19825 4423
2014-05-20 19997 4475
2014-05-21 20172 4528
2014-05-22 20325 4576
2014-05-23 20498 4628
2014-05-24 20674 4682
2014-05-25 20850 4736
2014-05-26 21027 4791
2014-05-27 21207 4847
2014-05-28 21388 4904
2014-05-29 21570 4961
2014-05-30 21754 5019
2014-05-31 21801 4939
2014-06-01 21950 4960
2014-06-02 22106 5010
2014-06-03 22267 5059
2014-06-04 22155 5081
2014-06-05 22030 4837
2014-06-06 22194 4882
2014-06-07 22112 4681
2014-06-08 22279 4729
2014-06-09 22449 4778
2014-06-10 22611 4817
2014-06-11 22783 4866
2014-06-12 22954 4913
2014-06-13 23127 4962
2014-06-14 23300 5011
2014-06-15 23474 5060
2014-06-16 23649 5109
2014-06-17 23820 5152
2014-06-18 23962 5202
2014-06-19 23909 5251
2014-06-20 24060 5280
2014-06-21 23309 4459
2014-06-22 23080 4108
2014-06-23 23231 4136
2014-06-24 23334 4114
2014-06-25 23497 4154
2014-06-26 23665 4196
2014-06-27 23824 4229
2014-06-28 23994 4270
2014-06-29 24167 4313
2014-06-30 24343 4357
2014-07-01 24519 4401
2014-07-02 24690 4436
2014-07-03 24857 4467
2014-07-04 24961 4509
2014-07-05 25100 4510
2014-07-06 25278 4552
2014-07-07 25461 4594
2014-07-08 25432 4424
2014-07-09 25523 4465
2014-07-10 25552 4508
2014-07-11 25380 4527
2014-07-12 25557 4570
2014-07-13 25732 4613
2014-07-14 25908 4659
2014-07-15 26086 4705
2014-07-16 26267 4754
2014-07-17 26451 4804
2014-07-18 26637 4854
2014-07-19 26823 4904
2014-07-20 27010 4955
2014-07-21 27193 5001
2014-07-22 27383 5053
2014-07-23 27573 5105
2014-07-24 27760 5155
2014-07-25 27952 5208
2014-07-26 28147 5264
2014-07-27 28346 5321
2014-07-28 28548 5380
2014-07-29 28736 5443
2014-07-30 28935 5504
2014-07-31 29135 5567
2014-08-01 29343 5632
2014-08-02 29555 5700
2014-08-03 29768 5769
2014-08-04 29982 5839
2014-08-05 30174 5887
2014-08-06 29705 5943
2014-08-07 29913 6012
2014-08-08 30106 6082
2014-08-09 30314 6152
2014-08-10 30522 6222
2014-08-11 30730 6292
2014-08-12 30940 6363
2014-08-13 31154 6435
2014-08-14 31146 6284
2014-08-15 31153 6148
2014-08-16 31289 6160
2014-08-17 31486 6213
2014-08-18 31683 6266
2014-08-19 31849 6287
2014-08-20 32047 6339
2014-08-21 32198 6392
2014-08-22 32336 6386
2014-08-23 32535 6439
2014-08-24 32736 6493
2014-08-25 32937 6547
2014-08-26 33138 6601
2014-08-27 33340 6656
2014-08-28 33479 6711
2014-08-29 33665 6752
2014-08-30 33865 6805
2014-08-31 34070 6861
2014-09-01 34271 6913
2014-09-02 34477 6968
2014-09-03 34683 7023
2014-09-04 34270 7017
2014-09-05 34427 7041
2014-09-06 34617 7092
2014-09-07 34809 7145
2014-09-08 35001 7198
2014-09-09 35195 7251
2014-09-10 35210 7304
2014-09-11 35405 7358
2014-09-12 35590 7402
2014-09-13 35789 7458
2014-09-14 35937 7463
2014-09-15 36137 7520
2014-09-16 36258 7572
2014-09-17 36029 7457
2014-09-18 36215 7515
2014-09-19 36325 7484
2014-09-20 36524 7542
2014-09-21 36719 7596
2014-09-22 36919 7654
2014-09-23 37119 7711
2014-09-24 37321 7770
2014-09-25 35974 6452
2014-09-26 36055 6500
2014-09-27 36245 6548
2014-09-28 36436 6597
2014-09-29 36627 6646
2014-09-30 36814 6690
2014-10-01 37000 6733
2014-10-02 37195 6782
2014-10-03 37347 6832
2014-10-04 36660 6520
2014-10-05 36844 6562
2014-10-06 37037 6609
2014-10-07 37148 6656
2014-10-08 37342 6703
2014-10-09 37537 6750
2014-10-10 37730 6797
2014-10-11 37548 6838
2014-10-12 37741 6884
2014-10-13 37936 6931
2014-10-14 37816 6667
2014-10-15 38010 6713
2014-10-16 38205 6760
2014-10-17 38399 6804
2014-10-18 33334 6095
2014-10-19 33176 6135
2014-10-20 33342 6177
2014-10-21 33506 6214
2014-10-22 33141 6256
2014-10-23 33047 6299
2014-10-24 33008 6135
2014-10-25 33052 6179
2014-10-26 33222 6224
2014-10-27 33278 6268
2014-10-28 33447 6311
2014-10-29 33620 6357
2014-10-30 29752 6403
2014-10-31 25969 6444
2014-11-01 14811 5750
2014-11-02 14436 5787
2014-11-03 14524 5830
2014-11-04 14599 5859
2014-11-05 14598 5812
2014-11-06 14687 5853
2014-11-07 14780 5899
2014-11-08 14872 5942
2014-11-09 14917 5934
2014-11-10 15015 5979
2014-11-11 15106 6020
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<script>
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.age); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.tsv("data.tsv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var types = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, age: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(types, function(c) { return d3.min(c.values, function(v) { return v.age; }); }),
d3.max(types, function(c) { return d3.max(c.values, function(v) { return v.age; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Age (days)");
var type = svg.selectAll(".type")
.data(types)
.enter().append("g")
.attr("class", "type");
type.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
type.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.age) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment