Last active
May 10, 2017 06:48
-
-
Save petertseng/460b93436817ee02f34a919216566966 to your computer and use it in GitHub Desktop.
Exercism teams
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
require 'set' | |
# Create a personal access token at https://github.com/settings/tokens | |
# It needs only one scope: read:org ("Read org and team membership"). | |
TOKEN_FILE = 'secrets/token.txt'.freeze | |
SLEEP_TIME = 2 | |
global_name = 'track-maintainers'.freeze | |
language_names = Set.new(%w( | |
bash | |
c | |
ceylon | |
clojure | |
coffeescript | |
coldfusion | |
cpp | |
crystal | |
csharp | |
dlang | |
elixir | |
elm | |
erlang | |
factor | |
fsharp | |
golang | |
groovy | |
haskell | |
haxe | |
idris | |
java | |
javascript | |
julia | |
kotlin | |
lisp | |
lua | |
mips | |
nim | |
objective-c | |
ocaml | |
pascal | |
perl | |
php | |
plsql | |
pony | |
powershell | |
prolog | |
purescript | |
python | |
r | |
racket | |
ruby | |
rust | |
scala | |
smalltalk | |
swift | |
tcl | |
teco | |
vb-net | |
)).freeze | |
not_language_names = Set.new(%w( | |
alumni | |
analysis | |
api | |
cli-committers | |
contributors | |
ember | |
gui | |
io | |
product-design | |
project-management | |
proofs | |
rikki | |
styleguide | |
synopsis | |
triage | |
windows-installer | |
xruby | |
)).freeze | |
CACHE = 'cache'.freeze | |
Dir.mkdir(CACHE) unless File.exist?(CACHE) | |
LAST_REQUEST = [0] | |
def req(url) | |
cache = "#{CACHE}/#{url.gsub(/\W/, ?_)}" | |
if File.exist?(cache) | |
res = File.read(cache) | |
else | |
if Time.now.to_i - LAST_REQUEST.first < SLEEP_TIME | |
puts "#{url}: sleeping to not overload." | |
Kernel.sleep(SLEEP_TIME) | |
end | |
LAST_REQUEST[0] = Time.now.to_i | |
tok = File.read(TOKEN_FILE).chomp | |
res = `curl -H "Authorization: token #{tok}" #{url}` | |
File.open(cache, ?w) { |f| f.puts(res) } | |
end | |
JSON.parse(res) | |
rescue => e | |
puts res | |
puts "No parse: #{e}" | |
end | |
def req_members(team) | |
members = req(team['members_url'].split(?{).first + '?per_page=100') | |
team[:members] = members.freeze | |
end | |
teams = req('https://api.github.com/orgs/exercism/teams?per_page=100') | |
new_teams = [] | |
language_teams = [] | |
global_teams = [] | |
teams.each { |t| | |
slug = t['slug'] | |
if slug == global_name | |
global_teams << t | |
elsif language_names.include?(slug) | |
language_teams << t | |
elsif !not_language_names.include?(slug) | |
new_teams << t | |
end | |
} | |
unless new_teams.empty? | |
puts "There are #{new_teams.size} new teams! Let's classify them." | |
puts new_teams | |
exit 1 | |
end | |
unless global_teams.size == 1 | |
puts "There were #{global_teams.size} global teams! How did this happen?" | |
puts global_teams | |
exit 1 | |
end | |
global_team = global_teams.first | |
unseen_languages = language_names - language_teams.map { |t| t['slug'] } | |
puts "#{teams.size} teams" | |
puts "#{language_teams.size} language teams (#{unseen_languages.size} unseen: #{unseen_languages.to_a})" | |
global_members = req_members(global_team) | |
global_usernames = Set.new(global_members.map { |u| u['login'] }) | |
people = Hash.new { |h, k| h[k] = [] } | |
union_usernames = Set.new | |
language_teams.each { |lt| | |
members = req_members(lt) | |
union_usernames |= members.map { |u| u['login'] } | |
members.each { |m| people[m['login']] << lt['slug'] } | |
} | |
puts "Global maintainers who aren't in any track: #{(global_usernames - union_usernames).to_a}" | |
puts "Track maintainers who aren't in global: #{(union_usernames - global_usernames).to_a}" | |
people.map { |name, tracks| [name, tracks, tracks.size] }.sort_by(&:last).reverse_each { |p| | |
puts '%1$20s: %3$d %2$s' % p | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment