diff --git a/lib/fastlane/plugin/ddg_apple_automation/actions/tag_release_action.rb b/lib/fastlane/plugin/ddg_apple_automation/actions/tag_release_action.rb index d0f14f0..2ae3c1a 100644 --- a/lib/fastlane/plugin/ddg_apple_automation/actions/tag_release_action.rb +++ b/lib/fastlane/plugin/ddg_apple_automation/actions/tag_release_action.rb @@ -28,24 +28,20 @@ def self.setup_constants(platform) end def self.run(params) - platform = params[:platform] || Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] - setup_constants(platform) - other_action.ensure_git_branch(branch: "^(:?release|hotfix)/.*$") Helper::GitHelper.setup_git_user + params[:platform] ||= Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] + setup_constants(params[:platform]) + tag_and_release_output = create_tag_and_github_release(params[:is_prerelease], params[:github_token]) Helper::GitHubActionsHelper.set_output("tag", tag_and_release_output[:tag]) begin - if params[:is_prerelease] - Helper::GitHelper.merge_branch(@constants[:repo_name], params[:branch], params[:base_branch], params[:github_elevated_permissions_token] || params[:github_token]) - else - Helper::GitHelper.delete_branch(@constants[:repo_name], params[:branch], params[:github_token]) - end - tag_and_release_output[:merge_or_delete_failed] = false + merge_or_delete_branch(params) + tag_and_release_output[:merge_or_delete_successful] = true rescue StandardError - tag_and_release_output[:merge_or_delete_failed] = true + tag_and_release_output[:merge_or_delete_successful] = false end report_status(params.values.merge(tag_and_release_output)) @@ -53,18 +49,16 @@ def self.run(params) def self.create_tag_and_github_release(is_prerelease, github_token) tag, promoted_tag = Helper::DdgAppleAutomationHelper.compute_tag(is_prerelease) - tag_created = false begin other_action.add_git_tag(tag: tag) other_action.push_git_tags(tag: tag) - tag_created = true rescue StandardError => e UI.important("Failed to create and push tag: #{e}") return { tag: tag, promoted_tag: promoted_tag, - tag_created: tag_created + tag_created: false } end @@ -77,7 +71,6 @@ def self.create_tag_and_github_release(is_prerelease, github_token) # Octokit doesn't provide the API to generate release notes for a specific tag # So we need to use the GitHub API directly generate_release_notes = other_action.github_api( - server_url: "https://api.github.com", api_bearer: github_token, http_method: "POST", path: "/repos/#{@constants[:repo_name]}/releases/generate-notes", @@ -104,11 +97,20 @@ def self.create_tag_and_github_release(is_prerelease, github_token) { tag: tag, promoted_tag: promoted_tag, - tag_created: tag_created, + tag_created: true, latest_public_release_tag: latest_public_release.tag_name } end + def self.merge_or_delete_branch(params) + branch = other_action.git_branch + if params[:is_prerelease] + Helper::GitHelper.merge_branch(@constants[:repo_name], branch, params[:base_branch], params[:github_elevated_permissions_token] || params[:github_token]) + else + Helper::GitHelper.delete_branch(@constants[:repo_name], branch, params[:github_token]) + end + end + def self.report_status(params) template_args = {} template_args['tag'] = params[:tag] @@ -158,7 +160,9 @@ def self.report_status(params) end def self.setup_asana_templates(params) - if params[:merge_or_delete_failed] + if params[:merge_or_delete_successful] + comment_template = params[:is_prerelease] ? "internal-release-ready" : "public-release-tagged" + else case [params[:tag_created], params[:is_prerelease]] when [true, true] task_template = "merge-failed" @@ -173,8 +177,6 @@ def self.setup_asana_templates(params) task_template = "public-release-tag-failed" comment_template = "public-release-tag-failed" end - else - comment_template = params[:is_prerelease] ? "internal-release-ready" : "public-release-tagged" end return task_template, comment_template @@ -211,10 +213,6 @@ def self.available_options optional: true, type: String, default_value: "main"), - FastlaneCore::ConfigItem.new(key: :branch, - description: "Release branch name", - optional: false, - type: String), FastlaneCore::ConfigItem.new(key: :github_handle, description: "Github user handle", optional: true, diff --git a/spec/tag_release_action_spec.rb b/spec/tag_release_action_spec.rb new file mode 100644 index 0000000..519effe --- /dev/null +++ b/spec/tag_release_action_spec.rb @@ -0,0 +1,151 @@ +describe Fastlane::Actions::TagReleaseAction do + before do + @params = { + platform: "macos", + asana_task_url: "https://app.asana.com/0/0/1/f", + is_prerelease: true, + github_token: "github-token" + } + @other_action = double(ensure_git_branch: nil) + @tag_and_release_output = {} + allow(Fastlane::Action).to receive(:other_action).and_return(@other_action) + allow(Fastlane::Helper).to receive(:setup_git_user) + end + + describe "#run" do + before do + allow(Fastlane::Actions::TagReleaseAction).to receive(:create_tag_and_github_release).and_return(@tag_and_release_output) + allow(Fastlane::Actions::TagReleaseAction).to receive(:merge_or_delete_branch) + allow(Fastlane::Actions::TagReleaseAction).to receive(:report_status) + end + + it "creates tag and release, merges branch and reports status" do + test_action(@params) + + expect(@tag_and_release_output[:merge_or_delete_successful]).to be_truthy + # expect(Fastlane::Actions::TagReleaseAction).to have_received(:report_status).with("macos") + end + + it "reports status when merge or delete failed" do + allow(Fastlane::Actions::TagReleaseAction).to receive(:merge_or_delete_branch).and_raise(StandardError) + test_action(@params) + + expect(@tag_and_release_output[:merge_or_delete_successful]).to be_falsy + # expect(Fastlane::Actions::TagReleaseAction).to have_received(:report_status).with("macos") + end + + def test_action(params) + configuration = Fastlane::ConfigurationHelper.parse(Fastlane::Actions::TagReleaseAction, params) + Fastlane::Actions::TagReleaseAction.run(configuration) + end + end + + describe "#create_tag_and_github_release" do + let (:latest_public_release) { double(tag_name: "1.0.0") } + let (:generated_release_notes) { { body: { "name" => "1.1.0", "body" => "Release notes" } } } + + before do + Fastlane::Actions::TagReleaseAction.setup_constants("macos") + allow(Octokit::Client).to receive(:new).and_return(double(latest_release: latest_public_release)) + allow(JSON).to receive(:parse).and_return(generated_release_notes[:body]) + @other_action = double(add_git_tag: nil, push_git_tags: nil, github_api: generated_release_notes, set_github_release: nil) + allow(Fastlane::Action).to receive(:other_action).and_return(@other_action) + allow(Fastlane::UI).to receive(:message) + allow(Fastlane::UI).to receive(:important) + end + + describe "for prerelease" do + before do + @params[:is_prerelease] = true + @tag = "1.1.0-123" + allow(Fastlane::Helper::DdgAppleAutomationHelper).to receive(:compute_tag).and_return([@tag, nil]) + end + + it "creates tag and github release" do + expect(create_tag_and_github_release(@params)).to eq({ + tag: @tag, + promoted_tag: nil, + tag_created: true, + latest_public_release_tag: latest_public_release.tag_name + }) + + expect(Fastlane::UI).to have_received(:message).with("Latest public release: #{latest_public_release.tag_name}").ordered + expect(Fastlane::UI).to have_received(:message).with("Generating duckduckgo/macos-browser release notes for GitHub release for tag: #{@tag}").ordered + + expect(@other_action).to have_received(:add_git_tag).with(tag: @tag) + expect(@other_action).to have_received(:push_git_tags).with(tag: @tag) + + expect(@other_action).to have_received(:github_api).with( + api_bearer: @params[:github_token], + http_method: "POST", + path: "/repos/duckduckgo/macos-browser/releases/generate-notes", + body: { + tag_name: @tag, + previous_tag_name: latest_public_release.tag_name + } + ) + + expect(JSON).to have_received(:parse).with(generated_release_notes[:body]) + + expect(@other_action).to have_received(:set_github_release).with( + repository_name: "duckduckgo/macos-browser", + api_bearer: @params[:github_token], + tag_name: @tag, + name: generated_release_notes[:body]["name"], + description: generated_release_notes[:body]["body"], + is_prerelease: @params[:is_prerelease] + ) + expect(Fastlane::UI).not_to have_received(:important) + end + end + + describe "for public release" do + before do + @params[:is_prerelease] = false + @tag = "1.1.0" + @promoted_tag = "1.1.0-123" + allow(Fastlane::Helper::DdgAppleAutomationHelper).to receive(:compute_tag).and_return([@tag, @promoted_tag]) + end + + it "creates tag and github release" do + expect(create_tag_and_github_release(@params)).to eq({ + tag: @tag, + promoted_tag: @promoted_tag, + tag_created: true, + latest_public_release_tag: latest_public_release.tag_name + }) + + expect(Fastlane::UI).to have_received(:message).with("Latest public release: #{latest_public_release.tag_name}").ordered + expect(Fastlane::UI).to have_received(:message).with("Generating duckduckgo/macos-browser release notes for GitHub release for tag: #{@tag}").ordered + expect(@other_action).to have_received(:add_git_tag).with(tag: @tag) + expect(@other_action).to have_received(:push_git_tags).with(tag: @tag) + + expect(@other_action).to have_received(:github_api).with( + api_bearer: @params[:github_token], + http_method: "POST", + path: "/repos/duckduckgo/macos-browser/releases/generate-notes", + body: { + tag_name: @tag, + previous_tag_name: latest_public_release.tag_name + } + ) + + expect(JSON).to have_received(:parse).with(generated_release_notes[:body]) + + expect(@other_action).to have_received(:set_github_release).with( + repository_name: "duckduckgo/macos-browser", + api_bearer: @params[:github_token], + tag_name: @tag, + name: generated_release_notes[:body]["name"], + description: generated_release_notes[:body]["body"], + is_prerelease: @params[:is_prerelease] + ) + expect(Fastlane::UI).not_to have_received(:important) + end + end + + def create_tag_and_github_release(params) + Fastlane::Actions::TagReleaseAction.create_tag_and_github_release(params[:is_prerelease], params[:github_token]) + end + end +end