|
require 'octokit' |
|
require 'terminal-table' |
|
require 'pp' |
|
|
|
token = `git config github.token`.strip |
|
to, from = nil, nil |
|
|
|
if ARGV.length == 1 |
|
from = "#{ARGV[0]}-01-01" |
|
to = "#{ARGV[0]}-12-31" |
|
elsif ARGV.length >= 2 |
|
from = ARGV[0] |
|
to = ARGV[1] |
|
end |
|
|
|
if from.nil? or to.nil? |
|
puts "Usage:" |
|
puts " ruby #{__FILE__} <year>" |
|
puts " ruby #{__FILE__} <start-date> <end-date>" |
|
end |
|
|
|
if token.empty? |
|
puts 'Please visit https://github.com/settings/tokens/new to generate a token' |
|
puts "Once you have your token, run 'git config github.token <token>'" |
|
end |
|
|
|
exit 1 if from.nil? or to.nil? or token.empty? |
|
|
|
require 'faraday-http-cache' |
|
require 'active_support' |
|
store = ActiveSupport::Cache.lookup_store(:file_store, "/tmp/gh_cache") |
|
stack = Faraday::RackBuilder.new do |builder| |
|
builder.use Faraday::HttpCache, shared_cache: false, store: store, serializer: Marshal |
|
builder.use Octokit::Response::RaiseError |
|
builder.adapter Faraday.default_adapter |
|
end |
|
gh = Octokit::Client.new(access_token: token, auto_paginate: true, middleware: stack) |
|
if not gh.user_authenticated? |
|
puts "Unauthenticated connection to GitHub, private repos will be invisible" |
|
end |
|
starting = gh.rate_limit.remaining |
|
puts "GitHub API: #{gh.rate_limit}" |
|
|
|
user = gh.user(ARGV[2]) |
|
puts "GitHub activity for #{user.login} (#{user.name})" |
|
orgs = ["strongloop", "strongloop-community", "strongloop-forks", "strongloop-internal"] |
|
puts "Using #{orgs.length} orgs: #{orgs}" |
|
repos = orgs.flat_map { |org| gh.org_repos(org, type: 'all') } |
|
puts "Found #{repos.length} repos." |
|
|
|
puts "Processing #{repos.length} repos for commits by #{user.login}..." |
|
repo_commits = repos.reject { |r| |
|
r.full_name == '' or r.full_name == 'strongloop/strongops' |
|
}.map { |repo| |
|
Thread.new do |
|
repo.commits = gh.commits(repo.full_name, :author => user.login, :since => from, :until => to) rescue [] |
|
repo |
|
end |
|
} |
|
|
|
puts 'gathering strongops repos (agent and non-agent)' |
|
strongops = gh.repo('strongloop/strongops') |
|
strongops.full_name += ' (non-agent)' |
|
agent = gh.repo('strongloop/strongops') |
|
agent.full_name += ' (agent)' |
|
puts 'gathering strongops commits (agent and non-agent)' |
|
agent.commits = gh.commits_between(agent.id, from, to, path: 'agent', author: user.login) |
|
agent_shas = agent.commits.map(&:sha) |
|
strongops.commits = gh.commits_between(strongops.id, from, to, author: user.login).reject { |c| |
|
agent_shas.include? c.sha |
|
} |
|
|
|
puts 'waiting for threads...' |
|
repo_commits = repo_commits.map(&:value) << strongops << agent |
|
puts 'crunching numbers...' |
|
total_commits = repo_commits.map(&:commits).map(&:length).reduce(&:+) |
|
current = 0 |
|
|
|
puts "GitHub API: used #{starting - gh.rate_limit.remaining} requests" |
|
|
|
stats_table = Terminal::Table.new do |t| |
|
t << [ total_commits, '100%', '0%', '*/*', '**' ] |
|
repo_commits.reject{|r| r.commits.empty? }.sort_by{|r| r.commits.length }.reverse.each do |r| |
|
count = r.commits.length |
|
current += count |
|
perc = "#{(count.to_f / total_commits * 100).round(1)}%" |
|
acc_perc = "#{(current.to_f / total_commits * 100).round(1)}%" |
|
t << [ count, perc, acc_perc, r.full_name, (r[:private] ? '*' : '') ] |
|
end |
|
t.headings = [ 'Commits', '% of Total', 'Acc. %', 'Repository', 'Private' ] |
|
end |
|
puts stats_table |