diff --git a/CHANGELOG.md b/CHANGELOG.md index c567330f8..b0c8f3e67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ _None_ ### Bug Fixes -_None_ +- Added optional `next_version` parameter to `android_update_release_notes` and `ios_update_release_notes` actions, allowing callers to provide the next version directly instead of relying on the built-in calculator that assumes minor version caps at 9. This fixes incorrect version bumps (e.g., 8.9 → 9.0 instead of 8.10) for apps using semantic versioning. [#706] ### Internal Changes diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb index 9b20e8762..177736242 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb @@ -10,8 +10,11 @@ def self.run(params) require_relative '../../helper/release_notes_helper' require_relative '../../helper/git_helper' + UI.user_error!('You must provide a non-empty value for either `next_version` or `new_version`') if params[:next_version].to_s.strip.empty? && params[:new_version].to_s.strip.empty? + path = params[:release_notes_file_path] - next_version = Fastlane::Helper::Android::VersionHelper.calc_next_release_short_version(params[:new_version]) + next_version = params[:next_version]&.strip + next_version = Fastlane::Helper::Android::VersionHelper.calc_next_release_short_version(params[:new_version]) if next_version.nil? || next_version.empty? Fastlane::Helper::ReleaseNotesHelper.add_new_section(path: path, section_title: next_version) Fastlane::Helper::GitHelper.commit(message: "Release Notes: add new section for next version (#{next_version})", files: path) @@ -36,6 +39,18 @@ def self.available_options FastlaneCore::ConfigItem.new(key: :new_version, env_name: 'FL_ANDROID_UPDATE_RELEASE_NOTES_VERSION', description: 'The version we are currently freezing; An empty entry for the _next_ version after this one will be added to the release notes', + deprecated: 'Deprecated in favor of `next_version`. ' \ + 'The `new_version` parameter computes the next version using a built-in calculator ' \ + 'that assumes the minor version rolls over to the next major at 9, which is incorrect for apps using semantic versioning', + optional: true, + conflicting_options: [:next_version], + type: String), + FastlaneCore::ConfigItem.new(key: :next_version, + description: 'The next version to use as the section title in the release notes. ' \ + 'This value is used directly as the section title. ' \ + 'Use this if your app does not follow the default versioning convention (minor capped at 9)', + optional: true, + conflicting_options: [:new_version], type: String), FastlaneCore::ConfigItem.new(key: :release_notes_file_path, env_name: 'FL_ANDROID_UPDATE_RELEASE_NOTES_FILE_PATH', diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb index c64c95707..670175b66 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb @@ -10,8 +10,11 @@ def self.run(params) require_relative '../../helper/release_notes_helper' require_relative '../../helper/git_helper' + UI.user_error!('You must provide a non-empty value for either `next_version` or `new_version`') if params[:next_version].to_s.strip.empty? && params[:new_version].to_s.strip.empty? + path = params[:release_notes_file_path] - next_version = Fastlane::Helper::Ios::VersionHelper.calc_next_release_version(params[:new_version]) + next_version = params[:next_version]&.strip + next_version = Fastlane::Helper::Ios::VersionHelper.calc_next_release_version(params[:new_version]) if next_version.nil? || next_version.empty? Fastlane::Helper::ReleaseNotesHelper.add_new_section(path: path, section_title: next_version) Fastlane::Helper::GitHelper.commit(message: "Release Notes: add new section for next version (#{next_version})", files: path) @@ -36,6 +39,18 @@ def self.available_options FastlaneCore::ConfigItem.new(key: :new_version, env_name: 'FL_IOS_UPDATE_RELEASE_NOTES_VERSION', description: 'The version we are currently freezing; An empty entry for the _next_ version after this one will be added to the release notes', + deprecated: 'Deprecated in favor of `next_version`. ' \ + 'The `new_version` parameter computes the next version using a built-in calculator ' \ + 'that assumes the minor version rolls over to the next major at 9, which is incorrect for apps using semantic versioning', + optional: true, + conflicting_options: [:next_version], + type: String), + FastlaneCore::ConfigItem.new(key: :next_version, + description: 'The next version to use as the section title in the release notes. ' \ + 'This value is used directly as the section title. ' \ + 'Use this if your app does not follow the default versioning convention (minor capped at 9)', + optional: true, + conflicting_options: [:new_version], type: String), FastlaneCore::ConfigItem.new(key: :release_notes_file_path, env_name: 'FL_IOS_UPDATE_RELEASE_NOTES_FILE_PATH', diff --git a/spec/android_update_release_notes_spec.rb b/spec/android_update_release_notes_spec.rb index 7967c181f..da02e64e8 100644 --- a/spec/android_update_release_notes_spec.rb +++ b/spec/android_update_release_notes_spec.rb @@ -61,5 +61,75 @@ expect(File.read(changelog_md)).to eq(new_section + content) end end + + it 'uses next_version directly when provided' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + expected_section = <<~CONTENT + 8.10 + ----- + + + CONTENT + + # Act + run_described_fastlane_action( + next_version: '8.10' + ) + + # Assert + expect(File.read(release_notes_txt)).to eq(expected_section + content) + end + end + + it 'raises an error when both new_version and next_version are provided' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + # Act & Assert + expect do + run_described_fastlane_action( + new_version: '8.9', + next_version: '8.10' + ) + end.to raise_error(FastlaneCore::Interface::FastlaneError, /Unresolved conflict between options/) + end + end + + it 'raises an error when neither new_version nor next_version is provided' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + # Act & Assert + expect do + run_described_fastlane_action( + release_notes_file_path: release_notes_txt + ) + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'You must provide a non-empty value for either `next_version` or `new_version`') + end + end + + it 'raises an error when next_version is an empty string' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + # Act & Assert + expect do + run_described_fastlane_action( + next_version: '', + release_notes_file_path: release_notes_txt + ) + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'You must provide a non-empty value for either `next_version` or `new_version`') + end + end end end diff --git a/spec/ios_update_release_notes_spec.rb b/spec/ios_update_release_notes_spec.rb index 6c5734f0c..1e7a70608 100644 --- a/spec/ios_update_release_notes_spec.rb +++ b/spec/ios_update_release_notes_spec.rb @@ -61,5 +61,75 @@ expect(File.read(changelog_md)).to eq(new_section + content) end end + + it 'uses next_version directly when provided' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + expected_section = <<~CONTENT + 8.10 + ----- + + + CONTENT + + # Act + run_described_fastlane_action( + next_version: '8.10' + ) + + # Assert + expect(File.read(release_notes_txt)).to eq(expected_section + content) + end + end + + it 'raises an error when both new_version and next_version are provided' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + # Act & Assert + expect do + run_described_fastlane_action( + new_version: '8.9', + next_version: '8.10' + ) + end.to raise_error(FastlaneCore::Interface::FastlaneError, /Unresolved conflict between options/) + end + end + + it 'raises an error when neither new_version nor next_version is provided' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + # Act & Assert + expect do + run_described_fastlane_action( + release_notes_file_path: release_notes_txt + ) + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'You must provide a non-empty value for either `next_version` or `new_version`') + end + end + + it 'raises an error when next_version is an empty string' do + in_tmp_dir do |tmp_dir| + # Arrange + release_notes_txt = File.join(tmp_dir, 'RELEASE-NOTES.txt') + File.write(release_notes_txt, content) + + # Act & Assert + expect do + run_described_fastlane_action( + next_version: '', + release_notes_file_path: release_notes_txt + ) + end.to raise_error(FastlaneCore::Interface::FastlaneError, 'You must provide a non-empty value for either `next_version` or `new_version`') + end + end end end