From bf9fbe2c5f594a907561fc1fea32636a01cb9aba Mon Sep 17 00:00:00 2001 From: Ian Maia Date: Mon, 17 Nov 2025 18:03:41 -0300 Subject: [PATCH 1/5] Improve hotfix lane to work when there's no release tag --- fastlane/Fastfile | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index b168c2b5b..c8387da5f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -82,9 +82,18 @@ platform :android do previous_version = VERSION_FORMATTER.release_version( VERSION_CALCULATOR.previous_patch_version(version: VERSION_FORMATTER.parse(new_version)) ) + previous_release_branch = release_branch_name(release_version: previous_version) UI.user_error!("The version `#{new_version}` tag already exists!") if git_tag_exists(tag: new_version) - UI.user_error!("Version #{previous_version} is not tagged! A hotfix branch cannot be created.") unless git_tag_exists(tag: previous_version) + + # Determine the base for the hotfix branch: either a tag or a release branch + base_ref_for_hotfix = if git_tag_exists(tag: previous_version) + previous_version + elsif Fastlane::Helper::GitHelper.branch_exists_on_remote?(branch_name: previous_release_branch) + previous_release_branch + else + UI.user_error!("Neither tag #{previous_version} nor branch #{previous_release_branch} exists! A hotfix branch cannot be created.") + end message = <<~MESSAGE Hotfix release: @@ -94,14 +103,14 @@ platform :android do - Current build code: #{build_code_current} - New build code: #{version_code_new} - Branching from tag: #{previous_version} + Branching from #{base_ref_for_hotfix} MESSAGE UI.important(message) UI.user_error!("Terminating as requested. Don't forget to run the remainder of this automation manually.") unless skip_confirm || UI.confirm('Do you want to continue?') - UI.message('Creating hotfix branch...') - Fastlane::Helper::GitHelper.create_branch(release_branch_name(release_version: new_version), from: previous_version) + UI.message("Creating hotfix branch from #{base_ref_for_hotfix}...") + Fastlane::Helper::GitHelper.create_branch(release_branch_name(release_version: new_version), from: base_ref_for_hotfix) UI.success("Done! New hotfix branch is: #{git_branch}") UI.message('Bumping hotfix version and build code...') From 1c322468bb1d4cec4def66370a7866c2d176ca46 Mon Sep 17 00:00:00 2001 From: Ian Maia Date: Mon, 17 Nov 2025 19:54:30 -0300 Subject: [PATCH 2/5] Add log when there's no release tag --- fastlane/Fastfile | 1 + 1 file changed, 1 insertion(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index c8387da5f..d318595a0 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -90,6 +90,7 @@ platform :android do base_ref_for_hotfix = if git_tag_exists(tag: previous_version) previous_version elsif Fastlane::Helper::GitHelper.branch_exists_on_remote?(branch_name: previous_release_branch) + UI.message("ℹ️ Tag #{previous_version} not found. Using release branch #{previous_release_branch} as the base for hotfix instead.") previous_release_branch else UI.user_error!("Neither tag #{previous_version} nor branch #{previous_release_branch} exists! A hotfix branch cannot be created.") From 33b93030506ee5cb40032651548ec73dd81d3352 Mon Sep 17 00:00:00 2001 From: Ian Maia Date: Wed, 19 Nov 2025 11:40:35 -0300 Subject: [PATCH 3/5] Add hotfix version validation and check tags on remote --- fastlane/Fastfile | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index d318595a0..cda36ad63 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -79,21 +79,24 @@ platform :android do new_version = version_name version_code_new = version_code + # Validate that this is a hotfix version (must have a patch component > 0) + parsed_version = VERSION_FORMATTER.parse(new_version) + UI.user_error!("Invalid hotfix version '#{new_version}'. Must include a patch number.") unless parsed_version.patch.to_i.positive? previous_version = VERSION_FORMATTER.release_version( - VERSION_CALCULATOR.previous_patch_version(version: VERSION_FORMATTER.parse(new_version)) + VERSION_CALCULATOR.previous_patch_version(version: parsed_version) ) previous_release_branch = release_branch_name(release_version: previous_version) - UI.user_error!("The version `#{new_version}` tag already exists!") if git_tag_exists(tag: new_version) + UI.user_error!("Version '#{new_version}' already exists on the remote! Abort!") if git_tag_exists(tag: new_version, remote: true) # Determine the base for the hotfix branch: either a tag or a release branch - base_ref_for_hotfix = if git_tag_exists(tag: previous_version) + base_ref_for_hotfix = if git_tag_exists(tag: previous_version, remote: true) previous_version elsif Fastlane::Helper::GitHelper.branch_exists_on_remote?(branch_name: previous_release_branch) - UI.message("ℹ️ Tag #{previous_version} not found. Using release branch #{previous_release_branch} as the base for hotfix instead.") + UI.message("ℹ️ Tag '#{previous_version}' not found on the remote. Using release branch '#{previous_release_branch}' as the base for hotfix instead.") previous_release_branch else - UI.user_error!("Neither tag #{previous_version} nor branch #{previous_release_branch} exists! A hotfix branch cannot be created.") + UI.user_error!("Neither tag '#{previous_version}' nor branch '#{previous_release_branch}' exists on the remote! A hotfix branch cannot be created.") end message = <<~MESSAGE @@ -110,9 +113,9 @@ platform :android do UI.user_error!("Terminating as requested. Don't forget to run the remainder of this automation manually.") unless skip_confirm || UI.confirm('Do you want to continue?') - UI.message("Creating hotfix branch from #{base_ref_for_hotfix}...") + UI.message("Creating hotfix branch from '#{base_ref_for_hotfix}'...") Fastlane::Helper::GitHelper.create_branch(release_branch_name(release_version: new_version), from: base_ref_for_hotfix) - UI.success("Done! New hotfix branch is: #{git_branch}") + UI.success("Done! New hotfix branch is: '#{git_branch}'") UI.message('Bumping hotfix version and build code...') VERSION_FILE.write_version( @@ -121,7 +124,7 @@ platform :android do ) commit_version_bump # Print computed version and build to let user double-check outcome in logs - UI.success("Done! New release version: #{release_version_current}. New build code: #{build_code_current}.") + UI.success("Done! New release version: '#{release_version_current}'. New build code: '#{build_code_current}'.") UI.important('Pushing new hotfix branch to remote...') push_to_git_remote(tags: false) From e3b2f102436f50bdf8d2aee40f4b189f291ad94d Mon Sep 17 00:00:00 2001 From: Ian Maia Date: Wed, 19 Nov 2025 18:23:45 -0300 Subject: [PATCH 4/5] Update to fetch base ref to ensure it's available locally --- fastlane/Fastfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index cda36ad63..1a2293bae 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -113,6 +113,9 @@ platform :android do UI.user_error!("Terminating as requested. Don't forget to run the remainder of this automation manually.") unless skip_confirm || UI.confirm('Do you want to continue?') + # Fetch the base ref to ensure it's available locally + sh('git', 'fetch', 'origin', base_ref_for_hotfix) + UI.message("Creating hotfix branch from '#{base_ref_for_hotfix}'...") Fastlane::Helper::GitHelper.create_branch(release_branch_name(release_version: new_version), from: base_ref_for_hotfix) UI.success("Done! New hotfix branch is: '#{git_branch}'") From 49a9a4e551854648b7120afb778eed1dba4a5570 Mon Sep 17 00:00:00 2001 From: Ian Maia Date: Fri, 21 Nov 2025 18:20:00 -0300 Subject: [PATCH 5/5] Update code to ensure the new hotfix branch doesn't exist --- fastlane/Fastfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 1a2293bae..c628e80b2 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -116,8 +116,11 @@ platform :android do # Fetch the base ref to ensure it's available locally sh('git', 'fetch', 'origin', base_ref_for_hotfix) + hotfix_branch = release_branch_name(release_version: new_version) + ensure_branch_does_not_exist!(hotfix_branch) + UI.message("Creating hotfix branch from '#{base_ref_for_hotfix}'...") - Fastlane::Helper::GitHelper.create_branch(release_branch_name(release_version: new_version), from: base_ref_for_hotfix) + Fastlane::Helper::GitHelper.create_branch(hotfix_branch, from: base_ref_for_hotfix) UI.success("Done! New hotfix branch is: '#{git_branch}'") UI.message('Bumping hotfix version and build code...')