Skip to content

Instantly share code, notes, and snippets.

@btoews
Created April 22, 2014 11:09
Show Gist options
  • Save btoews/11174489 to your computer and use it in GitHub Desktop.
Save btoews/11174489 to your computer and use it in GitHub Desktop.
Parse Gemfiles for all repositories belonging to a GitHub organization
require 'octokit'
require 'parser/current'
Octokit.auto_paginate = true
Octokit.connection_options[:request] ||= {}
Octokit.connection_options[:request][:timeout] = 240
API = Octokit::Client.new :access_token => ENV['GITHUB_ACCESS_TOKEN']
def get_gems_for_org_repos(org)
notice "Finding repos in the '#{org}' org."
repos = API.org_repos(org, :type => 'all')
repos.each_with_object({}) do |repo, hash|
name = repo.full_name
hash[name] = get_gems_for_repo(name)
end
end
def get_gems_for_repo(repo)
if ast = get_gemfile_ast(repo)
notice "Found a gemfile for the '#{repo}' repo."
traverse_gemfile ast
else
notice "No gemfile for the '#{repo}' repo."
nil
end
end
def get_gemfile_ast(repo)
begin
res = API.contents repo, :path => 'Gemfile'
rescue Octokit::NotFound
return nil
end
b64 = res.content.split("\n").join
raw = Base64.strict_decode64 b64
ast = Parser::CurrentRuby.parse raw
end
def traverse_gemfile(node, gems = {})
if call?(node) && node.children[1] == :gem
name = node.children[2].children[0]
if node.children[3] && node.children[3].type == :str
version = node.children[3].children[0]
end
gems[name] = version
elsif node?(node)
node.children.each { |c| traverse_gemfile c, gems }
end
gems
end
def call?(node)
node?(node) && node.type == :send
end
def node?(node)
node.is_a? Parser::AST::Node
end
def notice(msg)
STDERR.puts msg
end
if __FILE__ == $0
require 'json'
org = $1 || 'github'
gems = get_gems_for_org_repos org
puts JSON.pretty_generate gems
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment