Skip to content

Instantly share code, notes, and snippets.

@rmg
Last active August 29, 2015 13:57
Show Gist options
  • Save rmg/9594980 to your computer and use it in GitHub Desktop.
Save rmg/9594980 to your computer and use it in GitHub Desktop.
GitHub Commits Report

Simple Ruby script for getting stats on commit activity.

Uses octokit for GitHub API access and terminal-table for output formatting:

$ gem install octokit terminal-table faraday-http-cache activesupport

You'll also need a GitHub API token stored in your ~/.gitconfig. Go to https://github.com/settings/tokens/new and generate a new token (will need repo and user access). Once you have your token, save it:

$ git config github.token <token>

And then just let it run! (takes about 30 seconds for me)

$ ruby sred.rb 2013
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment