Skip to content

Instantly share code, notes, and snippets.

@ixti
Last active December 28, 2022 18:47
Show Gist options
  • Save ixti/3680c400850e8fefe52ceeb94dac8b03 to your computer and use it in GitHub Desktop.
Save ixti/3680c400850e8fefe52ceeb94dac8b03 to your computer and use it in GitHub Desktop.
Small script that to print CSV that can be used to plan gem upgrades
# frozen_string_literal: true
require "bundler/inline"
require "csv"
STDOUT.sync = STDERR.sync = true
gemfile do
source "https://rubygems.org"
gem "http"
end
lockfile = Bundler.read_file(ARGV[1] || Bundler.default_lockfile)
lockfile = Bundler::LockfileParser.new(lockfile)
class Infotainment
class RubygemsAPI
class Version
attr_reader :number
attr_reader :created_at
attr_reader :platform
def initialize(data)
@number = data.fetch("number")
@created_at = data.fetch("created_at").split("T", 2).first
@platform = data.fetch("platform")
end
def ruby?
"ruby" == @platform
end
alias to_s number
def ==(other)
@number == other.to_s
end
end
BASE_URI = "https://rubygems.org/api/v1"
def self.open
HTTP.persistent(BASE_URI) { |http| yield new http }
end
def initialize(http = HTTP)
@http = http
end
def latest(name)
get("#{BASE_URI}/versions/#{name}/latest.json").fetch("version")
end
def versions(name)
get("#{BASE_URI}/versions/#{name}.json").map { |data| Version.new data }
end
private
def get(url)
5.times do
res = @http.get(url).flush
return res.parse(:json) if res.status.ok?
sleep 1
end
raise "Failed to fetch #{url}"
end
end
class Info
attr_reader :name
def initialize(name, latest, versions)
@name = name
@latest = latest
@versions = versions.select(&:ruby?)
end
def latest
self[@latest]
end
def [](lookup)
@versions.find { |v| v == lookup }
end
end
def self.open
RubygemsAPI.open { |api| yield new api }
end
def initialize(api = RubygemsAPI.new)
@info = {}
@api = api
end
def call(name)
@info[name] ||= Info.new(name, @api.latest(name), @api.versions(name))
end
end
CSV do |csv|
Infotainment.open do |lookup|
csv << ["direct dependency", "gem name", "version", "released at", "latest version", "released at"]
lockfile.specs.each do |spec|
next unless spec.source.is_a? Bundler::Source::Rubygems
info = lookup.call(spec.name)
current = info[spec.version.to_s]
latest = info.latest
csv << [
lockfile.dependencies.key?(spec.name) ? "Y" : "N",
spec.name,
current.number,
current.created_at,
latest.number,
latest.created_at
]
end
end
end
@ixti
Copy link
Author

ixti commented Sep 4, 2019

Somewhat similar to bundle outdated but prints out data in spreadsheet format and provides info about release date

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment