Created
February 28, 2025 13:19
-
-
Save Thomascountz/cf4b956dc295414bf6451369594c2755 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 "open-uri" | |
require "date" | |
## DESCRIPTION: | |
# This script reads the Gemfile.lock of a Rails project and extracts the Rails | |
# version from each commit that updated the activerecord gem. It then uses the | |
# endoflife.date API to get the EOL date for each Rails version, and computes | |
# the number of days until EOL for each commit. Finally, it groups the results | |
# by year and prints the max, min, and avg "days until EOL" for each year. | |
## USAGE: | |
# ruby eol_hist.rb [repo_path] | |
# Pass repo path as first argument; default to current directory. | |
repo_path = ARGV[0] || "." | |
# 1. Get Rails EOL dates via endoflife.date API. | |
api_url = "https://endoflife.date/api/rails.json" | |
eol_entries = JSON.parse(URI.open(api_url).read) | |
eol_map = {} | |
eol_entries.each do |entry| | |
eol_map[entry["cycle"]] = Date.parse(entry["eol"]) | |
end | |
# 2. Use git to get commits that updated activerecord in Gemfile.lock. | |
# We use the -C option to run git in the specified repo. | |
log_cmd = "git -C #{repo_path} log -G '^ activerecord ' --pretty=format:'%H %ad' --date=short -- Gemfile.lock" | |
git_log = `#{log_cmd}` | |
commits = git_log.lines.map do |line| | |
sha, date_str = line.split(" ", 2) | |
{ sha: sha, date: Date.parse(date_str.strip) } | |
end | |
# 3. For each commit, extract the new rails version from the diff. | |
results = [] | |
commits.each do |commit| | |
diff = `git -C #{repo_path} show #{commit[:sha]} -- Gemfile.lock` | |
new_line = diff.each_line.find { |l| l.start_with?("+") && l.include?("activerecord") } | |
next unless new_line | |
if new_line =~ /\+ *activerecord\s+\(([^)]+)\)/ | |
version_str = $1.strip | |
segments = version_str.split(".") | |
cycle = segments[0,2].join(".") | |
if eol_map[cycle] | |
days_until_eol = (eol_map[cycle] - commit[:date]).to_i | |
results << { year: commit[:date].year, days_until_eol: days_until_eol } | |
end | |
end | |
end | |
# 4. Group the results by year, then compute and print the max and min "days until EOL" for each year. | |
puts "Yearly stats for days until Rails EOL" | |
puts "-----------------------------------------" | |
grouped = results.group_by { |r| r[:year] } | |
header = sprintf("%-6s %10s %10s %10s %10s", "Year", "Max", "Min", "Med", "Avg") | |
puts header | |
puts "-" * header.size | |
grouped.keys.sort.each do |year| | |
values = grouped[year].map { |r| r[:days_until_eol] } | |
med = values.sum / values.size | |
avg = values.sum.to_f / values.size | |
puts sprintf("%-6d %10d %10d %10d %10.2f", year, values.max, values.min, med, avg) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment