Last active
August 14, 2024 11:07
-
-
Save flyerhzm/a82a63ac8ad761af2b60b248c6c39c49 to your computer and use it in GitHub Desktop.
Fetch gem changelogs based on Gemfile.lock diff, you can update gems in Gemfile.lock, then run `bundle exec ruby fetch_gem_changelogs.rb | more`
This file contains 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 'bundler' | |
require 'net/http' | |
require 'json' | |
require 'uri' | |
# Function to fetch gem information from RubyGems.org | |
def fetch_gem_info(gem_name) | |
url = URI("https://rubygems.org/api/v1/gems/#{gem_name}.json") | |
response = Net::HTTP.get_response(url) | |
if response.is_a?(Net::HTTPSuccess) | |
JSON.parse(response.body) | |
else | |
nil | |
end | |
end | |
# Function to extract updated gems from `git diff` | |
def updated_gems | |
diff_output = `git diff Gemfile.lock` | |
gems = {} | |
diff_output.each_line do |line| | |
if line.match(/^\-\s+(\S+)\s+\((\d+\.\d+\.\d+)\)/) | |
gem_name, old_version = line.match(/^\-\s+(\S+)\s+\((\d+\.\d+\.\d+)\)/).captures | |
gems[gem_name] ||= {} | |
gems[gem_name][:old] = old_version | |
elsif line.match(/^\+\s+(\S+)\s+\((\d+\.\d+\.\d+)\)/) | |
gem_name, new_version = line.match(/^\+\s+(\S+)\s+\((\d+\.\d+\.\d+)\)/).captures | |
gems[gem_name] ||= {} | |
gems[gem_name][:new] = new_version | |
end | |
end | |
gems.select { |_, versions| versions[:old] && versions[:new] } | |
end | |
# Function to fetch and display relevant CHANGELOG sections | |
def fetch_and_display_changelog(gem_name, old_version, new_version, changelog_url, source_code_url) | |
# Check if the changelog_url is not on GitHub | |
unless changelog_url.include?('github.com') | |
# If source_code_url is on GitHub, construct the GitHub CHANGELOG URL | |
if source_code_url && source_code_url.include?('github.com') | |
changelog_url = "#{source_code_url}/blob/main/CHANGELOG.md" | |
else | |
puts "#{gem_name}: The changelog is not available on GitHub and no fallback could be constructed." | |
return | |
end | |
end | |
# Convert GitHub URL to raw URL if needed | |
if changelog_url.include?('github.com') && !changelog_url.include?('/raw/') | |
changelog_url = changelog_url.gsub('github.com', 'raw.githubusercontent.com').gsub('/blob/', '/') | |
end | |
uri = URI(changelog_url) | |
response = Net::HTTP.get_response(uri) | |
if response.is_a?(Net::HTTPSuccess) | |
changelog_content = response.body | |
extract_relevant_changelog(gem_name, old_version, new_version, changelog_content) | |
else | |
puts "#{gem_name}: Failed to fetch CHANGELOG from #{changelog_url}" | |
end | |
end | |
# Function to extract relevant section from the CHANGELOG content | |
def extract_relevant_changelog(gem_name, old_version, new_version, changelog_content) | |
puts "\n====================================================\n" | |
puts "#{gem_name} - Changes from version #{old_version} to #{new_version}:\n\n" | |
# Refined regex to match version headers more accurately | |
version_section_regex = /^##?.*\s*v?(\d+\.\d+\.\d+)/i | |
lines = changelog_content.lines | |
relevant_lines = [] | |
capturing = false | |
lines.each do |line| | |
if line.match(version_section_regex) | |
version = line.match(version_section_regex)[1] | |
if Gem::Version.new(version) <= Gem::Version.new(new_version) && Gem::Version.new(version) > Gem::Version.new(old_version) | |
capturing = true | |
elsif Gem::Version.new(version) <= Gem::Version.new(old_version) | |
capturing = false | |
end | |
end | |
relevant_lines << line if capturing | |
end | |
if relevant_lines.empty? | |
puts "No specific changelog entries found between versions #{old_version} and #{new_version}." | |
else | |
puts relevant_lines.join | |
end | |
end | |
# Fetch updated gems list | |
gems_to_check = updated_gems | |
if gems_to_check.empty? | |
puts "No updated gems found in git diff." | |
else | |
gems_to_check.each do |gem_name, versions| | |
gem_info = fetch_gem_info(gem_name) | |
if gem_info | |
changelog_url = gem_info['changelog_uri'] | |
source_code_url = gem_info['source_code_uri'] | |
if changelog_url | |
fetch_and_display_changelog(gem_name, versions[:old], versions[:new], changelog_url, source_code_url) | |
elsif source_code_url && source_code_url.include?('github.com') | |
fetch_and_display_changelog(gem_name, versions[:old], versions[:new], "#{source_code_url}/blob/main/CHANGELOG.md", source_code_url) | |
else | |
puts "#{gem_name}: No changelog or source code URL found on RubyGems.org" | |
end | |
else | |
puts "#{gem_name}: Failed to fetch gem information from RubyGems.org" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment