diff --git a/dev/lib/product_taxonomy.rb b/dev/lib/product_taxonomy.rb index abb50a12..0a34fae6 100644 --- a/dev/lib/product_taxonomy.rb +++ b/dev/lib/product_taxonomy.rb @@ -34,3 +34,4 @@ def data_path = DATA_PATH require_relative "product_taxonomy/commands/generate_dist_command" require_relative "product_taxonomy/commands/find_unmapped_external_categories_command" require_relative "product_taxonomy/commands/generate_docs_command" +require_relative "product_taxonomy/commands/generate_release_command" diff --git a/dev/lib/product_taxonomy/cli.rb b/dev/lib/product_taxonomy/cli.rb index 221c0156..e112e3d4 100644 --- a/dev/lib/product_taxonomy/cli.rb +++ b/dev/lib/product_taxonomy/cli.rb @@ -32,5 +32,12 @@ def unmapped_external_categories(name_and_version) def docs GenerateDocsCommand.new(options).run end + + desc "release", "Generate a release" + option :version, type: :string, desc: "The version of the release to generate" + option :locales, type: :array, default: ["en"], desc: "The locales to generate" + def release + GenerateReleaseCommand.new(options).run + end end end diff --git a/dev/lib/product_taxonomy/commands/command.rb b/dev/lib/product_taxonomy/commands/command.rb index 74139b3c..bc31ebc0 100644 --- a/dev/lib/product_taxonomy/commands/command.rb +++ b/dev/lib/product_taxonomy/commands/command.rb @@ -20,6 +20,9 @@ def run(...) execute(...) end logger.info("Completed in #{elapsed.round(2)} seconds") + rescue => e + logger.error("\e[1;31mError:\e[0m #{e.message}") + exit(1) end def execute(...) @@ -27,6 +30,8 @@ def execute(...) end def load_taxonomy + return if ProductTaxonomy::Category.all.any? + ProductTaxonomy::Value.load_from_source(YAML.load_file(File.expand_path( "values.yml", ProductTaxonomy.data_path, @@ -54,5 +59,14 @@ def validate_and_sanitize_version!(version) sanitized_version end + + def version_file_path + File.expand_path("../VERSION", ProductTaxonomy.data_path) + end + + def locales_defined_in_data_path + glob = Dir.glob(File.expand_path("localizations/categories/*.yml", ProductTaxonomy.data_path)) + glob.map { File.basename(_1, ".yml") } + end end end diff --git a/dev/lib/product_taxonomy/commands/generate_dist_command.rb b/dev/lib/product_taxonomy/commands/generate_dist_command.rb index 69fd5ae3..f861d5b4 100644 --- a/dev/lib/product_taxonomy/commands/generate_dist_command.rb +++ b/dev/lib/product_taxonomy/commands/generate_dist_command.rb @@ -7,7 +7,7 @@ class GenerateDistCommand < Command def initialize(options) super - @version = options[:version] || File.read(File.expand_path("../../../../VERSION", __dir__)).strip + @version = options[:version] || File.read(version_file_path).strip @locales = if options[:locales] == ["all"] glob = Dir.glob(File.expand_path("localizations/categories/*.yml", ProductTaxonomy.data_path)) glob.map { File.basename(_1, ".yml") } diff --git a/dev/lib/product_taxonomy/commands/generate_release_command.rb b/dev/lib/product_taxonomy/commands/generate_release_command.rb new file mode 100644 index 00000000..7f9c4d45 --- /dev/null +++ b/dev/lib/product_taxonomy/commands/generate_release_command.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module ProductTaxonomy + class GenerateReleaseCommand < Command + def initialize(options) + super + + @version = options[:version] || File.read(version_file_path).strip + @locales = if options[:locales] == ["all"] + locales_defined_in_data_path + else + options[:locales] + end + end + + def execute + logger.info("Generating release for version: #{@version}") + + logger.info("Generating distribution files...") + GenerateDistCommand.new(version: @version, locales: @locales).execute + + logger.info("Generating documentation files...") + GenerateDocsCommand.new(version: @version, locales: @locales).execute + + logger.info("Updating VERSION file...") + File.write(version_file_path, @version) + + logger.info("Creating git tag...") + system("git", "tag", "v#{@version}") + + logger.info("Updating README.md...") + update_readme + end + + private + + def update_readme + readme_path = File.expand_path("../dist/README.md", ProductTaxonomy.data_path) + content = File.read(readme_path) + content.gsub!(%r{badge/Version-.*?-blue\.svg}) do + badge_version = @version.gsub("-", "--") + "badge/Version-#{badge_version}-blue.svg" + end + File.write(readme_path, content) + end + end +end diff --git a/dev/test/commands/generate_release_command_test.rb b/dev/test/commands/generate_release_command_test.rb new file mode 100644 index 00000000..8b672d5b --- /dev/null +++ b/dev/test/commands/generate_release_command_test.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require "test_helper" +require "tmpdir" + +module ProductTaxonomy + class GenerateReleaseCommandTest < TestCase + setup do + @tmp_base_path = Dir.mktmpdir + @version = "2024-01" + @version_file_path = File.expand_path("VERSION", @tmp_base_path) + + # Create test files and directories + FileUtils.mkdir_p(File.expand_path("dist", @tmp_base_path)) + File.write(@version_file_path, "2023-12") + File.write( + File.expand_path("dist/README.md", @tmp_base_path), + 'Version', + ) + + # Stub dependencies + Command.any_instance.stubs(:version_file_path).returns(@version_file_path) + Command.any_instance.stubs(:load_taxonomy) + GenerateDistCommand.any_instance.stubs(:execute) + GenerateDocsCommand.any_instance.stubs(:execute) + ProductTaxonomy.stubs(:data_path).returns("#{@tmp_base_path}/data") + end + + teardown do + FileUtils.remove_entry(@tmp_base_path) + end + + test "initialize sets version from options if provided" do + command = GenerateReleaseCommand.new(version: @version) + assert_equal @version, command.instance_variable_get(:@version) + end + + test "initialize reads version from file if not provided in options" do + command = GenerateReleaseCommand.new({}) + assert_equal "2023-12", command.instance_variable_get(:@version) + end + + test "initialize sets all locales when 'all' is specified" do + Command.any_instance.stubs(:locales_defined_in_data_path).returns(["en", "fr", "es"]) + command = GenerateReleaseCommand.new(locales: ["all"]) + assert_equal ["en", "fr", "es"], command.instance_variable_get(:@locales) + end + + test "initialize sets specific locales when provided" do + command = GenerateReleaseCommand.new(locales: ["en", "fr"]) + assert_equal ["en", "fr"], command.instance_variable_get(:@locales) + end + + test "execute performs all required steps in order" do + command = GenerateReleaseCommand.new(version: @version, locales: ["en"]) + + # Set up expectations + GenerateDistCommand.any_instance.expects(:execute) + GenerateDocsCommand.any_instance.expects(:execute) + command.expects(:system).with("git", "tag", "v#{@version}") + + command.execute + + # Verify VERSION file was updated + assert_equal @version, File.read(@version_file_path) + end + + test "execute updates README.md version badge" do + command = GenerateReleaseCommand.new(version: @version) + + command.execute + + readme_content = File.read(File.expand_path("dist/README.md", @tmp_base_path)) + assert_equal 'Version', readme_content + end + end +end