Last active
August 3, 2021 09:51
-
-
Save mrcook/b9a43419331d3f324db1974222ab52e0 to your computer and use it in GitHub Desktop.
Ruby script to generate a CHANGELOG from git commits
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
#!/usr/bin/env ruby | |
# Generate a changelog for a git repository | |
# | |
# Usage: | |
# | |
# $ cd app_dir | |
# $ ruby /path/to/changelog.rb | |
CHANGELOG_FILENAME = 'CHANGELOG.new.md' | |
if !Dir.exists?(File.join(Dir.pwd, '.git')) | |
puts "FATAL: not a git repository" | |
return | |
end | |
def project_name | |
Dir.pwd.split('/').last.gsub(/[_-]/, ' ').split(' ').map { |word| word.capitalize }.join(' ') | |
end | |
def clean_tag(str) | |
tag = str&.match(/tag: v?(\d+(\.\d+)*)/) | |
if !tag.nil? && tag.size >= 2 | |
return tag[1] # return matched version | |
end | |
'x.x.x' | |
end | |
def clean_message(msg) | |
return 'MERGE COMMIT' if msg.match(/\AMerge pull request/) | |
# perform any other clean you find useful | |
# msg.sub!(/\ACloses? #?(\d+)?/i, '') | |
msg.sub!(/ *\(#\d+\)\z/, '') | |
msg | |
end | |
# | |
# run the pipeline | |
# | |
Commit = Struct.new(:date, :tag, :message) | |
commits = [] | |
# 3 passes to easily get the needed data...it's not so slow. | |
`git log --format='%cs'`.split("\n").each do |l| | |
commit = Commit.new | |
commit.date = l | |
commits << commit | |
end | |
`git log --format='%D'`.split("\n").each_with_index do |l, i| | |
commits[i].tag = l | |
end | |
`git log --format='%s'`.split("\n").each_with_index do |l, i| | |
commits[i].message = l | |
end | |
# fix up the commits | |
commits.each do |c| | |
c.tag = clean_tag(c.tag) | |
c.message = clean_message(c.message) | |
end | |
# create the changelog | |
filename = "#{Dir.pwd}/#{CHANGELOG_FILENAME}" | |
File.open(filename, 'w') do |f| | |
f.write "# #{project_name} changelog\n\n\n" | |
f.write "## HEAD\n" | |
commits.each do |c| | |
next if c.message == 'MERGE COMMIT' && c.tag == 'x.x.x' | |
f.write "\n\n" | |
f.write "\n" unless c.tag == "x.x.x" | |
f.write "## #{c.tag} (#{c.date})\n\n" | |
f.write "* #{c.message}" | |
end | |
f.write "\n" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment