diff --git a/fastlane/lanes/release.rb b/fastlane/lanes/release.rb index c9d706eab..474fcbb11 100644 --- a/fastlane/lanes/release.rb +++ b/fastlane/lanes/release.rb @@ -183,6 +183,59 @@ end end + lane :publish_release do |skip_confirm: false| + ensure_git_status_clean + ensure_git_branch_is_release_branch! + + version_number = release_version_current + + current_branch = release_branch_name(release_version: version_number) + next_release_branch = release_branch_name(release_version: release_version_next) + + UI.important <<~PROMPT + Publish the #{version_number} release. This will: + - Publish the existing draft `#{version_number}` release on GitHub + - Which will also have GitHub create the associated Git tag, pointing to the tip of #{current_branch} + - If the release branch for the next version `#{next_release_branch}` already exists, backmerge `#{current_branch}` into it + - If needed, backmerge `#{current_branch}` back into `#{DEFAULT_BRANCH}` + - Delete the `#{current_branch}` branch + PROMPT + 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.important "Publishing release #{version_number} on GitHub..." + + publish_github_release( + repository: GITHUB_REPO, + name: version_number + ) + + pr_urls = create_backmerge_prs! + + # It's possible that no backmerge was created when: + # + # - there are no hotfixes in development and the next release code freeze has not been started + # - nothing changes in the current release branch since release finalization + # + # As a matter of fact, in the context of Simplenote Android, the above is the most likely scenario. + style, message = if pr_urls.empty? + ['info', 'No backmerge PR was required'] + else + [ + 'success', <<~MESSAGE + The following backmerge PR#{pr_urls.length > 1 ? '(s) were' : ' was'} created: + #{pr_urls.map { |url| "- #{url}" }} + MESSAGE + ] + end + buildkite_annotate(style: style, context: 'backmerge-prs-outcome', message: message) if is_ci + UI.success(message) + + # At this point, an intermediate branch has been created by creating a backmerge PR to a hotfix or the next version release branch. + # This allows us to safely delete the `release/*` branch. + # Note that if a hotfix or new release branches haven't been created, the backmerge PR won't be created as well. + delete_remote_git_branch!(current_branch) + end + lane :trigger_beta_build do |branch_to_build:| trigger_buildkite_release_build(branch: branch_to_build, beta: true) end @@ -335,3 +388,11 @@ def delete_old_changelogs_and_commit(version:) allow_nothing_to_commit: true ) end + +# Delete a branch from the GitHub remote, after having removed any GitHub branch protection. +# +def delete_remote_git_branch!(branch_name, remote: 'origin') + remove_branch_protection(repository: GITHUB_REPO, branch: branch_name) + + Git.open(Dir.pwd).push(remote, branch_name, delete: true) +end