discourse/lib/tasks/release_note.rake

136 lines
3.8 KiB
Ruby

# frozen_string_literal: true
desc "generate a release note from the important commits"
task "release_note:generate", :from, :to, :repo do |t, args|
repo = args[:repo] || "."
from = args[:from] || `git -C #{repo} describe --tags --abbrev=0`.strip
to = args[:to] || "HEAD"
bug_fixes = Set.new
new_features = Set.new
ux_changes = Set.new
sec_changes = Set.new
perf_changes = Set.new
a11y_changes = Set.new
out = `git -C #{repo} log --pretty="tformat:%s" '#{from}..#{to}'`
next "Status #{$?.exitstatus} running git log\n#{out}" if !$?.success?
out.each_line do |comment|
next if comment =~ /^\s*Revert/
split_comments(comment).each do |line|
if line =~ /^FIX:/
bug_fixes << better(line)
elsif line =~ /^FEATURE:/
new_features << better(line)
elsif line =~ /^UX:/
ux_changes << better(line)
elsif line =~ /^SECURITY:/
sec_changes << better(line)
elsif line =~ /^PERF:/
perf_changes << better(line)
elsif line =~ /^A11Y:/
a11y_changes << better(line)
end
end
end
print_changes("New Features", new_features)
print_changes("Bug Fixes", bug_fixes)
print_changes("UX Changes", ux_changes)
print_changes("Security Changes", sec_changes)
print_changes("Performance", perf_changes)
print_changes("Accessibility", a11y_changes)
if [bug_fixes, new_features, ux_changes, sec_changes, perf_changes, a11y_changes].all?(&:empty?)
puts "(no changes)", ""
end
end
# To use with all-the-plugins:
# 1. Make sure you have a local, up-to-date clone of https://github.com/discourse/all-the-plugins
# 2. In all-the-plugins, `git submodule update --init --recursive --remote`
# 3. Change back to your discourse directory
# 4. rake "release_note:plugins:generate[ HEAD@{2021-06-01} , HEAD@{now} , /path/to/all-the-plugins/plugins/* , discourse ]"
desc "generate release notes for all official plugins in a directory"
task "release_note:plugins:generate", :from, :to, :plugin_glob, :org do |t, args|
from = args[:from]
to = args[:to]
plugin_glob = args[:plugin_glob] || "./plugins/*"
git_org = args[:org]
all_repos = Dir.glob(plugin_glob).filter { |f| File.directory?(f) && File.exists?("#{f}/.git") }
if git_org
all_repos = all_repos.filter { |dir| `git -C #{dir} remote get-url origin`.match?(/github.com[\/:]#{git_org}\//) }
end
all_repos.each do |dir|
puts "## #{File.basename(dir)}\n\n"
Rake::Task["release_note:generate"].invoke(from, to, dir)
Rake::Task["release_note:generate"].reenable
puts "---", ""
end
end
def print_changes(heading, changes)
return if changes.length == 0
puts "### #{heading}", ""
puts changes.to_a, ""
end
def better(line)
line = remove_prefix(line)
line = escape_brackets(line)
line = remove_pull_request(line)
line[0] = '\#' if line[0] == '#'
if line[0]
line[0] = line[0].capitalize
"- " + line
else
nil
end
end
def remove_prefix(line)
line.gsub(/^(FIX|FEATURE|UX|SECURITY|PERF|A11Y):/, "").strip
end
def escape_brackets(line)
line.gsub("<", "`<")
.gsub(">", ">`")
.gsub("[", "`[")
.gsub("]", "]`")
end
def remove_pull_request(line)
line.gsub(/ \(\#\d+\)$/, "")
end
def split_comments(text)
text = normalize_terms(text)
terms = ["FIX:", "FEATURE:", "UX:", "SECURITY:" , "PERF:" , "A11Y:"]
terms.each do |term|
text = text.gsub(/(#{term})+/i, term)
text = newlines_at_term(text, term)
end
text.split("\n")
end
def normalize_terms(text)
text = text.gsub(/(BUGFIX|FIX|BUG):/i, "FIX:")
text = text.gsub(/FEATURE:/i, "FEATURE:")
text = text.gsub(/(UX|UI):/i, "UX:")
text = text.gsub(/(SECURITY):/i, "SECURITY:")
text = text.gsub(/(PERF):/i, "PERF:")
text = text.gsub(/(A11Y):/i, "A11Y:")
end
def newlines_at_term(text, term)
if text.include?(term)
text = text.split(term).map { |l| l.strip }.join("\n#{term} ")
end
text
end