Skip to content

Instantly share code, notes, and snippets.

@mrcook
Last active August 3, 2021 09:51
Show Gist options
  • Save mrcook/b9a43419331d3f324db1974222ab52e0 to your computer and use it in GitHub Desktop.
Save mrcook/b9a43419331d3f324db1974222ab52e0 to your computer and use it in GitHub Desktop.
Ruby script to generate a CHANGELOG from git commits
#!/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