Skip to content

Instantly share code, notes, and snippets.

@compwron
Last active February 22, 2016 18: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 compwron/cb00c2dd48712b089390 to your computer and use it in GitHub Desktop.
Save compwron/cb00c2dd48712b089390 to your computer and use it in GitHub Desktop.
gem maintenance evaluator
require 'git'
require 'bundler'
require 'json'
require 'pry'
def gem_freshness_map(lockfile)
{}.tap do |gem_freshness|
uris = lockfile.specs.each do |spec|
clazz = spec.source.class
puts "Evaluating #{spec.name}"
if clazz == Bundler::Source::Rubygems
gem_freshness.merge!(rubygem_latest_version_date(spec))
elsif clazz == Bundler::Source::Git
gem_freshness.merge!(git_gem_latest_version_date(spec))
else
puts clazz
end
end
end
end
def rubygem_latest_version_date(spec)
gem_name = spec.name
gem_info_file = "/tmp/rubygems_version_info_#{gem_name}.json"
unless File.exist? gem_info_file
gem_json = `curl -q https://rubygems.org/api/v1/versions/#{gem_name}.json > #{gem_info_file}`
end
begin
gem_version_json = JSON.parse(File.read(gem_info_file))
most_recent_version_date = gem_version_json.map { |version| Time.parse(version['built_at']) }.sort.last
{gem_name => most_recent_version_date}
rescue JSON::ParserError => e
p e.message
{gem_name => Time.now} # can't tell because it's probably an internal gem
end
end
def git_gem_latest_version_date(spec)
gem_name = spec.source.name
{gem_name => date_of_last_commit(spec.source.uri, gem_name)}
end
def date_of_last_commit(uri, name)
gem_copy_directory = "/tmp/checkout_#{name}_#{Time.now.strftime("%Y-%m-%d")}"
return Time.now if name == 'parallel_tests' # 60 sec instead of < 1 sec
if Dir.exist? gem_copy_directory
g = Git.open(gem_copy_directory + "/#{name}")
else
g = Git.clone(uri, name, :path => gem_copy_directory, depth: 1)
end
g.log.first.date
end
def _pretty(freshness_map)
max_display_length = freshness_map.keys.map { |k| k.length }.max
freshness_map.sort_by { |k, v| v }.to_h.map { |k, v|
"#{k}#{' ' * (max_display_length - k.length)}last updated: #{v}"
}
end
lockfile = Bundler::LockfileParser.new(Bundler.read_file("Gemfile.lock"))
freshness_map = gem_freshness_map(lockfile)
count_to_show = ARGV[0] || 5
puts "These are not how old our gems are; this is how old our gems would be if we updated all of them."
puts "Oldest #{count_to_show}:"
puts _pretty(freshness_map)[0..count_to_show.to_i]
# ruby up_to_date_gemfinder.rb 10
# These are not how old our gems are; this is how old our gems would be if we updated all of them.
# Oldest 10:
# capistrano-ext last updated: 2008-06-14 06:00:00 UTC
# colored last updated: 2010-02-10 08:00:00 UTC
# vegas last updated: 2010-10-11 07:00:00 UTC
# erubis last updated: 2011-04-01 15:00:00 UTC
# rack-cache last updated: 2012-03-05 00:00:00 UTC
# sql_queries_count last updated: 2012-04-02 00:00:00 UTC
# journey last updated: 2012-06-14 00:00:00 UTC
# pbkdf256 last updated: 2012-09-27 00:00:00 UTC
# fssm last updated: 2013-01-27 00:00:00 UTC
# net-ssh-gateway last updated: 2013-02-06 00:00:00 UTC
# trackless_triggers last updated: 2013-03-05 00:00:00 UTC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment