# frozen_string_literal: true module GFSM module Commands class Changelog < BaseCommand NEXT_ENTRY_MARKER = "" def self.help cli_info = GFSM::Tools::VersionBumperSettings.cli_info <<~HELP Usage: gfsm changelog [help|generate] [--output-file ] [--no-incremental] #{cli_info[:usage]} Commands: help # Prints this help generate # Generate the changelog for the current version Options: --output-file # Path to the output changelog file. Defaults to 'CHANGELOG.md'. If not specified, the generate changelog content will be written to stdout --no-incremental # When provided, the generated changelog won't look for an existing changelog file. When outputting to stdout the changelog will never be incremental --only-new-entries # When provided, the generated changelog won't look for an existing changelog file and will contain only the new entries for the current version, without the Changelog or version headings #{cli_info[:options]} Environment variables: OUTPUT_FILE # Equivalent to --output-file NO_INCREMENTAL # Equivalent to --no-incremental ONLY_NEW_ENTRIES # Equivalent to --only-new-entries #{cli_info[:environment_variables]} HELP end def run(args = []) case args.shift when 'help' GFSM::Output.puts(GFSM::Commands::Changelog.help) when 'generate' no_incremental = ENV.has_key?("NO_INCREMENTAL") || args.include?("--no-incremental") only_new_entries = ENV.has_key?("ONLY_NEW_ENTRIES") || args.include?("--only-new-entries") output_file_path = get_output_file_path(args) changelog_section = compute_this_version_section(args, only_new_entries) if only_new_entries GFSM::Output.puts changelog_section elsif !output_file_path GFSM::Output.puts <<~CHANGELOG # Changelog #{changelog_section} CHANGELOG else if File.file?(output_file_path) && !no_incremental existing_content = File.read(output_file_path) file_content = existing_content.gsub(/#{Regexp.quote(NEXT_ENTRY_MARKER)}/i, changelog_section) File.open(output_file_path, 'w') { |file| file.write file_content } else File.open(output_file_path, 'w') do |file| file.write <<~CHANGELOG # Changelog #{changelog_section} CHANGELOG end end end else GFSM::Output.warn(GFSM::Commands::Version.help) end true end private def compute_this_version_section(args, only_new_entries) settings = GFSM::Tools::VersionBumperSettings.new(args) version_bumper = GFSM::Tools::VersionBumper.new(settings) version = version_bumper.execute subdivisions = version_bumper.subdivisions.to_a subdivisions.sort_by! { |subdivision_data| subdivision_data[0].priority }.reverse! changelog_entries = "" subdivisions.each do |subdivision_data| change_type = subdivision_data[0] commits = subdivision_data[1] changelog_entries += "#{change_type.to_changelog_entry}\n\n" commits.each do |commit| changelog_entries += "- #{commit.to_changelog_entry}\n" end changelog_entries += "\n" end changelog_entries = changelog_entries[0...-1] unless changelog_entries.empty? return changelog_entries if only_new_entries section = "#{NEXT_ENTRY_MARKER}\n## #{version}" return section if !subdivisions || subdivisions.empty? "#{section}\n\n#{changelog_entries}" end def extract_switch_value_if_present(args, switch, default_value, env_name) return ENV.fetch(env_name) if ENV.has_key?(env_name) switch_index = args.find_index(switch) return nil unless switch_index return default_value unless (switch_index + 1) < args.length args[switch_index + 1] end def get_output_file_path(args) extract_switch_value_if_present(args, "--output-file", "./CHANGELOG.md", "OUTPUT_FILE") end end end end