Skip to content

Instantly share code, notes, and snippets.

@JeffCohen
Last active November 7, 2024 12:25
Show Gist options
  • Save JeffCohen/7d1da3c83db96a5e37244e7fb8fed4be to your computer and use it in GitHub Desktop.
Save JeffCohen/7d1da3c83db96a5e37244e7fb8fed4be to your computer and use it in GitHub Desktop.
Generates a unified CHANGELOG.md for Rails releases.
# This script generates unified CHANGELOG output in Markdown
# of all Rails changes between two versions of Rails.
#
# By default, it shows the latest changes in the specified version only.
#
# You can also pass the "since earlier" version you're interested in.
#
# Usage: ruby rails_changes.rb {latest_version} [since_version]
#
# Examples:
#
# $ ruby rails_changes.rb 5.2.2.rc1
#
# Generates a unified CHANGELOG to stdout of changes in 5.2.2.rc1 since
# previous released version.
#
#
# $ ruby rails_changes.rb 5.2.2.rc1 5.2.1
#
# Generates a unified CHANGELOG to stdout of changes in Rails since
# 5.2.1 was released, up to and including the changesin 5.2.2.rc1
#
require 'open-uri'
def generate_unified_changelog(version, since_previous_version)
changelog, new_version, since_version = read_all_change_logs(version, since_previous_version)
puts
puts "## New in Rails #{new_version} since #{since_version}:"
puts
changelog.each do |line|
puts line
end
end
# Returns a list of Markdown-formatted lines.
def read_all_change_logs(latest_version, since_version)
unified_changelog = { }
path_template = "https://raw.githubusercontent.com/rails/rails/v#{latest_version}/*/CHANGELOG.md"
libs = %w|actioncable actionmailer actionpack actionview activejob activemodel activerecord
activestorage activesupport railties|
versions = []
current_version = nil
libs.each do |lib|
open(path_template.sub('*', lib)).readlines.each do |line|
if line =~ /\# Rails (\S+)/
current_version = $1
versions.push(current_version) unless versions.index(current_version)
unified_changelog[current_version] ||= []
elsif current_version && line =~ /^\*+\s+(.+)$/
commit_title = $1
unified_changelog[current_version].push([lib, commit_title]) unless commit_title =~ /No changes/i
end
end
end
new_version ||= versions.first
since_version ||= (version.count > 1 ? versions[1] : current_version)
new_version_index = versions.index(new_version)
since_version_index = versions.index(since_version)
versions = versions.slice(new_version_index, since_version_index-new_version_index)
changelog = versions.map do |version|
unified_changelog[version].map do |lib, commit|
"* [#{version}] [#{lib}] #{commit}"
end
end.flatten
return [changelog, new_version, since_version]
end
if ARGV[0]
generate_unified_changelog ARGV[0], ARGV[1]
else
puts "Usage: ruby rails_changes.rb {released_version} [since_version]"
puts
puts " Examples:"
puts
puts " $ ruby rails_changes.rb 5.2.2.rc1"
puts
puts " Generates a unified CHANGELOG to stdout of changes in 5.2.2.rc1 since"
puts " the previous released version."
puts
puts
puts " $ ruby rails_changes.rb 5.2.2.rc1 5.2.1"
puts
puts " Generates a unified CHANGELOG to stdout of changes in Rails since"
puts " 5.2.1 was released, up to and including the changes in 5.2.2.rc1."
puts
end
@knarewski
Copy link

Note

The script above works only within a single major Rails version (changelogs for different major Rails versions are separate files)

This script worked for me on Ruby 3.2 after making a couple adjustments:

  • replace open to URI.open (seems like Kernel.open used to support URLs but it doesn't now?)
  • replace version.count with versions.count (seems like a typo)

I also adjusted versions.slice to versions.slice(new_version_index, since_version_index-new_version_index + 1) to make it include the changes from the oldest version, but it may break other stuff

Nice script BTW, thanks for sharing :-)

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