From 7d549ce2f3295315e8d294fa4c22b79651cfff5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20=C5=81yp?= Date: Thu, 12 Sep 2024 13:39:21 +0200 Subject: [PATCH] Complete asana_create_action_item --- .../actions/asana_add_comment_action.rb | 10 +- .../asana_create_action_item_action.rb | 118 ++++++++++++++++++ .../templates/appcast_failed_hotfix.yml | 34 +++++ .../helper/ddg_apple_automation_helper.rb | 8 ++ spec/asana_add_comment_action_spec.rb | 18 --- spec/ddg_apple_automation_helper_spec.rb | 38 ++++++ 6 files changed, 199 insertions(+), 27 deletions(-) create mode 100644 lib/fastlane/plugin/ddg_apple_automation/actions/asana_create_action_item_action.rb create mode 100644 lib/fastlane/plugin/ddg_apple_automation/assets/asana_create_action_item/templates/appcast_failed_hotfix.yml diff --git a/lib/fastlane/plugin/ddg_apple_automation/actions/asana_add_comment_action.rb b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_add_comment_action.rb index d41420c..f327ba0 100644 --- a/lib/fastlane/plugin/ddg_apple_automation/actions/asana_add_comment_action.rb +++ b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_add_comment_action.rb @@ -33,7 +33,7 @@ def self.run(params) template_content = Helper::DdgAppleAutomationHelper.load_file(template_file) return unless template_content - html_text = process_template_content(template_content) + html_text = Helper::DdgAppleAutomationHelper.sanitize_and_replace_env_vars(template_content) create_story(asana_access_token, task_id, html_text: html_text) end end @@ -110,14 +110,6 @@ def self.create_story(asana_access_token, task_id, text: nil, html_text: nil) UI.user_error!("Failed to post comment: #{e}") end end - - def self.process_template_content(template_content) - template_content.gsub(/\$\{(\w+)\}/) { ENV.fetch($1, '') } # replace environment variables - .gsub(/\s+/, ' ') # replace multiple whitespaces with a single space - .gsub(/>\s+<') # remove spaces between HTML tags - .strip # remove leading and trailing whitespaces - .gsub(%r{}, "\n") # replace
tags with newlines - end end end end diff --git a/lib/fastlane/plugin/ddg_apple_automation/actions/asana_create_action_item_action.rb b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_create_action_item_action.rb new file mode 100644 index 0000000..3f56c66 --- /dev/null +++ b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_create_action_item_action.rb @@ -0,0 +1,118 @@ +require "fastlane/action" +require "fastlane_core/configuration/config_item" +require "asana" +require "yaml" +require_relative "../helper/ddg_apple_automation_helper" +require_relative "../helper/github_actions_helper" +require_relative "asana_add_comment_action" +require_relative "asana_get_release_automation_subtask_id_action" +require_relative "asana_get_user_id_for_github_handle_action" +require_relative "asana_extract_task_id_action" +require_relative "asana_extract_task_assignee_action" + +module Fastlane + module Actions + class AsanaCreateActionItemAction < Action + def self.run(params) + token = params[:asana_access_token] + task_url = params[:task_url] + task_name = params[:task_name] + notes = params[:notes] + html_notes = params[:html_notes] + template_name = params[:template_name] + is_scheduled_release = params[:is_scheduled_release] + github_handle = params[:github_handle] + + task_id = AsanaExtractTaskIdAction.run(task_url: task_url) + if is_scheduled_release + assignee_id = AsanaExtractTaskAssigneeAction.run(task_id: task_id, asana_access_token: token) + else + if github_handle.to_s.empty? + UI.user_error!("Github handle cannot be empty for manual release") + return + end + assignee_id = AsanaGetUserIdForGithubHandleAction.run(github_handle: github_handle, asana_access_token: token) + end + + Helper::GitHubActionsHelper.set_output("asana_assignee_id", assignee_id) + + asana_client = Asana::Client.new do |c| + c.authentication(:access_token, token) + end + + if template_name + template_file = Helper::DdgAppleAutomationHelper.path_for_asset_file("asana_create_action_item/templates/#{template_name}.yml") + template_content = Helper::DdgAppleAutomationHelper.load_file(template_file) + template_content = YAML.safe_load(template_content) + + task_name = Helper::DdgAppleAutomationHelper.sanitize_and_replace_env_vars(template_content["name"]) + html_notes = Helper::DdgAppleAutomationHelper.sanitize_and_replace_env_vars(template_content["html_notes"]) + subtask = asana_client.tasks.create_subtask_for_task(task_gid: task_id, assignee: assignee_id, name: task_name, html_notes: html_notes) + elsif notes + subtask = asana_client.tasks.create_subtask_for_task(task_gid: task_id, assignee: assignee_id, name: task_name, notes: notes) + elsif html_notes + subtask = asana_client.tasks.create_subtask_for_task(task_gid: task_id, assignee: assignee_id, name: task_name, html_notes: html_notes) + end + + puts(subtask&.gid) + Helper::GitHubActionsHelper.set_output("new_task_id", subtask.gid) + end + + def self.description + "Add a subtask to Asana Release Automation Task" + end + + def self.authors + ["DuckDuckGo"] + end + + def self.return_value + "" + end + + def self.details + "Adds a task with an action item to the Asana release task's 'Automation' subtask" + end + + def self.available_options + [ + FastlaneCore::ConfigItem.asana_access_token, + FastlaneCore::ConfigItem.new(key: :task_url, + description: "Asana release task URL", + optional: false, + type: String), + FastlaneCore::ConfigItem.new(key: :task_name, + description: "Task name", + optional: true, + type: String), + FastlaneCore::ConfigItem.new(key: :notes, + description: "Task notes", + optional: true, + type: String), + FastlaneCore::ConfigItem.new(key: :html_notes, + description: "Task HTML notes", + optional: true, + type: String), + FastlaneCore::ConfigItem.new(key: :template_name, + description: "Name of a template file (without extension) for the task content. Templates can be found in assets/asana_create_action_item/templates subdirectory. + The file is processed before being sent to Asana", + optional: true, + type: String), + FastlaneCore::ConfigItem.new(key: :github_handle, + description: "Github user handle", + optional: true, + type: String), + FastlaneCore::ConfigItem.new(key: :is_scheduled_release, + description: "Indicates whether the release was scheduled or started manually", + optional: true, + type: Boolean, + default_value: false) + ] + end + + def self.is_supported?(platform) + true + end + end + end +end diff --git a/lib/fastlane/plugin/ddg_apple_automation/assets/asana_create_action_item/templates/appcast_failed_hotfix.yml b/lib/fastlane/plugin/ddg_apple_automation/assets/asana_create_action_item/templates/appcast_failed_hotfix.yml new file mode 100644 index 0000000..a843e97 --- /dev/null +++ b/lib/fastlane/plugin/ddg_apple_automation/assets/asana_create_action_item/templates/appcast_failed_hotfix.yml @@ -0,0 +1,34 @@ +name: Generate appcast2.xml for ${TAG} hotfix release and upload assets to S3 +html_notes: | + + Publishing ${TAG} hotfix release failed in CI. Please follow the steps to generate the appcast file and upload files to S3 from your local machine. + +
    +
  1. Create a new file called release-notes.txt on your disk. +
      +
    • Add each release note as a separate line and don't add bullet points (•) – the script will add them automatically.
    • +
  2. +
  3. Run appcastManager: +
      +
    • ./scripts/appcast_manager/appcastManager.swift --release-hotfix-to-public-channel --dmg ~/Downloads/${DMG_NAME} --release-notes release-notes.txt
    • +
  4. +
  5. Verify that the new build is in the appcast file with the latest release notes and no internal channel tag. The phased rollout tag should not be present: +
      +
    • <sparkle:phasedRolloutInterval>43200</sparkle:phasedRolloutInterval>
    • +
  6. +
  7. Run upload_to_s3.sh script: +
      +
    • ./scripts/upload_to_s3/upload_to_s3.sh --run --overwrite-duckduckgo-dmg ${VERSION}
    • +
  8. +
+ When done, please verify that "Check for Updates" works correctly: +
    +
  1. Launch a debug version of the app with an old version number.
  2. +
  3. Make sure you're not identified as an internal user in the app.
  4. +
  5. Go to Main Menu → DuckDuckGo → Check for Updates...
  6. +
  7. Verify that you're being offered to update to ${TAG}.
  8. +
  9. Verify that the update works.
  10. +

+ 🔗 Workflow URL: ${WORKFLOW_URL}. + + \ No newline at end of file diff --git a/lib/fastlane/plugin/ddg_apple_automation/helper/ddg_apple_automation_helper.rb b/lib/fastlane/plugin/ddg_apple_automation/helper/ddg_apple_automation_helper.rb index f027f3c..362e994 100644 --- a/lib/fastlane/plugin/ddg_apple_automation/helper/ddg_apple_automation_helper.rb +++ b/lib/fastlane/plugin/ddg_apple_automation/helper/ddg_apple_automation_helper.rb @@ -27,6 +27,14 @@ def self.load_file(file) rescue StandardError UI.user_error!("Error: The file '#{file}' does not exist.") end + + def self.sanitize_and_replace_env_vars(content) + content.gsub(/\$\{(\w+)\}/) { ENV.fetch($1, '') } # replace environment variables + .gsub(/\s+/, ' ') # replace multiple whitespaces with a single space + .gsub(/>\s+<') # remove spaces between HTML tags + .strip # remove leading and trailing whitespaces + .gsub(%r{}, "\n") # replace
tags with newlines + end end end end diff --git a/spec/asana_add_comment_action_spec.rb b/spec/asana_add_comment_action_spec.rb index f5fc15c..cd9d31f 100644 --- a/spec/asana_add_comment_action_spec.rb +++ b/spec/asana_add_comment_action_spec.rb @@ -54,24 +54,6 @@ test_action(task_id: "123", template_name: "non-existing") end - it "correctly substitutes all variables" do - template_content = "

${ASSIGNEE_ID} is publishing ${TAG} hotfix release

" - ClimateControl.modify( - ASSIGNEE_ID: '12345', - TAG: 'v1.0.0' - ) do - result = Fastlane::Actions::AsanaAddCommentAction.process_template_content(template_content) - expected_output = "

12345 is publishing v1.0.0 hotfix release

" - expect(result).to eq(expected_output) - end - end - - it "removes newlines and leading/trailing spaces" do - template_content = " \nHello, \n\n World!\n This is a test. \n" - result = Fastlane::Actions::AsanaAddCommentAction.process_template_content(template_content) - expect(result).to eq("Hello, World! This is a test.") - end - it "correctly builds html_text payload" do allow(File).to receive(:read).and_return(" \nHello, \n World!\n This is a test. \n") allow(@asana_client_stories).to receive(:create_story_for_task) diff --git a/spec/ddg_apple_automation_helper_spec.rb b/spec/ddg_apple_automation_helper_spec.rb index e80f24f..c27af42 100644 --- a/spec/ddg_apple_automation_helper_spec.rb +++ b/spec/ddg_apple_automation_helper_spec.rb @@ -1,3 +1,5 @@ +require "climate_control" + describe Fastlane::Helper::DdgAppleAutomationHelper do describe "#asana_task_url" do it "constructs Asana task URL" do @@ -15,4 +17,40 @@ def asana_task_url(task_id) Fastlane::Helper::DdgAppleAutomationHelper.asana_task_url(task_id) end end + + describe "#sanitize_and_replace_env_vars" do + it "substitutes all env variables" do + content = "

${ASSIGNEE_ID} is publishing ${TAG} hotfix release

" + ClimateControl.modify( + ASSIGNEE_ID: '12345', + TAG: 'v1.0.0' + ) do + expect(sanitize_and_replace_env_vars(content)).to eq("

12345 is publishing v1.0.0 hotfix release

") + end + end + + it "removes newlines and leading/trailing spaces" do + content = " \nHello, \n\n World!\n This is a test. \n" + expect(sanitize_and_replace_env_vars(content)).to eq("Hello, World! This is a test.") + end + + it "removes spaces between html tags" do + content = "

Hello, World! This is a test.

" + expect(sanitize_and_replace_env_vars(content)).to eq("

Hello, World! This is a test.

") + end + + it "replaces multiple whitespaces with a single space" do + content = "

Hello, World! This is a test.

" + expect(sanitize_and_replace_env_vars(content)).to eq("

Hello, World! This is a test.

") + end + + it "replaces
tags with new lines" do + content = "

Hello, World!
This is a test.

" + expect(sanitize_and_replace_env_vars(content)).to eq("

Hello, World!\n This is a test.

") + end + + def sanitize_and_replace_env_vars(content) + Fastlane::Helper::DdgAppleAutomationHelper.sanitize_and_replace_env_vars(content) + end + end end