Add a bin/changelog script
This commit is contained in:
parent
490776517c
commit
03b932df19
1 changed files with 163 additions and 0 deletions
163
bin/changelog
Executable file
163
bin/changelog
Executable file
|
@ -0,0 +1,163 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# Generate a changelog entry file in the correct location.
|
||||
#
|
||||
# Automatically stages the file and amends the previous commit if the `--amend`
|
||||
# argument is used.
|
||||
|
||||
require 'optparse'
|
||||
require 'yaml'
|
||||
|
||||
Options = Struct.new(
|
||||
:amend,
|
||||
:author,
|
||||
:dry_run,
|
||||
:merge_request,
|
||||
:title
|
||||
)
|
||||
|
||||
class ChangelogOptionParser
|
||||
def self.parse(argv)
|
||||
options = Options.new
|
||||
|
||||
parser = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: #{__FILE__} [options]"
|
||||
|
||||
# Note: We do not provide a shorthand for this in order to match the `git
|
||||
# commit` interface
|
||||
opts.on('--amend', 'Amend the previous commit') do |value|
|
||||
options.amend = value
|
||||
end
|
||||
|
||||
opts.on('-m', '--merge-request [integer]', Integer, 'Merge Request ID') do |value|
|
||||
options.merge_request = value
|
||||
end
|
||||
|
||||
opts.on('-n', '--dry-run', "Don't actually write anything, just print") do |value|
|
||||
options.dry_run = value
|
||||
end
|
||||
|
||||
opts.on('-u', '--git-username', 'Use Git user.name configuration as the author') do |value|
|
||||
options.author = git_user_name if value
|
||||
end
|
||||
|
||||
opts.on('-h', '--help', 'Print help message') do
|
||||
puts opts
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
parser.parse!(argv)
|
||||
|
||||
# Title is everything that remains, but let's clean it up a bit
|
||||
options.title = argv.join(' ').strip.squeeze(' ').tr("\r\n", '')
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def self.git_user_name
|
||||
%x{git config user.name}.strip
|
||||
end
|
||||
end
|
||||
|
||||
class ChangelogEntry
|
||||
attr_reader :options
|
||||
|
||||
def initialize(options)
|
||||
@options = options
|
||||
|
||||
assert_feature_branch!
|
||||
assert_new_file!
|
||||
assert_title!
|
||||
|
||||
$stdout.puts "\e[32mcreate\e[0m #{file_path}"
|
||||
$stdout.puts contents
|
||||
unless options.dry_run
|
||||
write
|
||||
amend_commit if options.amend
|
||||
end
|
||||
end
|
||||
|
||||
def contents
|
||||
YAML.dump(
|
||||
'title' => title,
|
||||
'merge_request' => options.merge_request,
|
||||
'author' => options.author
|
||||
)
|
||||
end
|
||||
|
||||
def write
|
||||
File.write(file_path, contents)
|
||||
end
|
||||
|
||||
def amend_commit
|
||||
%x{git add #{file_path}}
|
||||
exec("git commit --amend")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fail_with(message)
|
||||
$stderr.puts "\e[31merror\e[0m #{message}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
def assert_feature_branch!
|
||||
return unless branch_name == 'master'
|
||||
|
||||
fail_with "Create a branch first!"
|
||||
end
|
||||
|
||||
def assert_new_file!
|
||||
return unless File.exist?(file_path)
|
||||
|
||||
fail_with "#{file_path} already exists!"
|
||||
end
|
||||
|
||||
def assert_title!
|
||||
return if options.title.length > 0 || options.amend
|
||||
|
||||
fail_with "Provide a title for the changelog entry or use `--amend`" \
|
||||
" to use the title from the previous commit."
|
||||
end
|
||||
|
||||
def title
|
||||
if options.title.empty?
|
||||
last_commit_subject
|
||||
else
|
||||
options.title
|
||||
end
|
||||
end
|
||||
|
||||
def last_commit_subject
|
||||
%x{git log --format="%s" -1}.strip
|
||||
end
|
||||
|
||||
def file_path
|
||||
File.join(
|
||||
unreleased_path,
|
||||
branch_name.gsub(/[^\w-]/, '-') << '.yml'
|
||||
)
|
||||
end
|
||||
|
||||
def unreleased_path
|
||||
File.join('changelogs', 'unreleased').tap do |path|
|
||||
path << '-ee' if ee?
|
||||
end
|
||||
end
|
||||
|
||||
def ee?
|
||||
@ee ||= File.exist?(File.expand_path('../CHANGELOG-EE.md', __dir__))
|
||||
end
|
||||
|
||||
def branch_name
|
||||
@branch_name ||= %x{git symbolic-ref HEAD}.strip.sub(%r{\Arefs/heads/}, '')
|
||||
end
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
options = ChangelogOptionParser.parse(ARGV)
|
||||
ChangelogEntry.new(options)
|
||||
end
|
||||
|
||||
# vim: ft=ruby
|
Loading…
Reference in a new issue