Skip to content

Instantly share code, notes, and snippets.

@rudionrails
Last active October 11, 2015 04:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rudionrails/3803999 to your computer and use it in GitHub Desktop.
Save rudionrails/3803999 to your computer and use it in GitHub Desktop.
Generate changelog from git based on tags
#!/usr/bin/env ruby
#
# This file generates a full changelog from your git history based on your tags.
#
# @example
# ruby changelog.rb
#
# @example Write to file
# ruby changelog.rb > CHANGELOG.md
require 'time'
class Changelog
FORMAT = "%ci [%an] : %s"
def initialize(depth = 3)
@depth = depth
@tags = `git for-each-ref refs/tags --sort=authordate --format='%(refname) | %(authordate)'`
@tags = @tags.gsub( "refs/tags/", '' ).split("\n").reverse
end
def output
changelog = []
previous = nil
tags.each do |tag|
current, date = tag.split(' | ')
unless previous.nil?
# Get the commits between the current and previous tag
commits = `git log --pretty="format:#{FORMAT}" #{current}...#{previous}`
commits = commits.split("\n")
# compose the changelog
diff = ["# #{current} (#{Time.parse(date) rescue nil})", *commits, "\n"]
changelog += diff
end
previous = current
end
changelog
end
def each(&block)
output.each(&block)
end
private
def tags
@tags[0, @depth]
end
end
class Tickets
TICKET_REGEX = /([FBC]).*\[\#(\w+-\d+)\]\s*(.*)$/
def initialize(changelog)
@changelog = changelog
end
def output
tickets.keys.sort.map do |id|
ticket = tickets[id]
# "%-7s [%s]\n %s" % [id, ticket[:type], ticket[:messages].join("\n ")]
# "%s [%s]\n %s" % [ticket[:type], id, ticket[:messages].join("\n ")]
"%s [%s]" % [ticket[:type], id]
end
end
private
def tickets
list = {}
@changelog.each do |log|
match = log.match(TICKET_REGEX)
next if match.nil?
# line.match(/(?:\w+\/|#)(\d+)/)[1] rescue nil
# line.match(/\#([0-9A-Z\-]+)/)[1] rescue nil
type, id, message = match.captures
if list.key?(id)
list[id][:messages] << message.strip
else
list[id] = {type: type, messages: [message.strip]}
end
end
list
end
end
changelog = Changelog.new
puts changelog.output
tickets = Tickets.new(changelog)
puts *tickets.output
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment