diff --git a/.gitignore b/.gitignore index b7e3986..468bd64 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ fastlane/README.md fastlane/report.xml coverage test-results +.DS_Store diff --git a/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_assignee_action.rb b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_assignee_action.rb index 5fd7781..8e78096 100644 --- a/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_assignee_action.rb +++ b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_assignee_action.rb @@ -10,22 +10,18 @@ module Actions class AsanaExtractTaskAssigneeAction < Action def self.run(params) task_id = params[:task_id] - token = Helper::DdgAppleAutomationHelper.fetch_asana_token - url = Helper::DdgAppleAutomationHelper::ASANA_API_URL + "/tasks/#{task_id}?opt_fields=assignee" + token = params[:asana_access_token] + url = Helper::DdgAppleAutomationHelper::ASANA_API_URL + "/tasks/#{task_id}?opt_fields=assignee" response = HTTParty.get(url, headers: { 'Authorization' => "Bearer #{token}" }) if response.success? assignee_id = response.parsed_response.dig('data', 'assignee', 'gid') + Helper::GitHubActionsHelper.set_output("asana_assignee_id", assignee_id) + assignee_id else UI.user_error!("Failed to fetch task assignee: (#{response.code} #{response.message})") end - - if Helper.is_ci? - Helper::GitHubActionsHelper.set_output("asana_assignee_id", assignee_id) - end - - assignee_id end def self.description @@ -47,6 +43,7 @@ def self.details def self.available_options [ + FastlaneCore::ConfigItem.asana_access_token, FastlaneCore::ConfigItem.new(key: :task_id, description: "Asana task ID", optional: false, diff --git a/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_id_action.rb b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_id_action.rb index 8360b38..15dce83 100644 --- a/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_id_action.rb +++ b/lib/fastlane/plugin/ddg_apple_automation/actions/asana_extract_task_id_action.rb @@ -14,11 +14,7 @@ def self.run(params) if (match = task_url.match(TASK_URL_REGEX)) task_id = match[1] - - if Helper.is_ci? - Helper::GitHubActionsHelper.set_output("asana_task_id", task_id) - end - + Helper::GitHubActionsHelper.set_output("asana_task_id", task_id) task_id else UI.user_error!(ERROR_MESSAGE) 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 b4d94cf..0e047f0 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 @@ -1,3 +1,4 @@ +require "fastlane_core/configuration/config_item" require 'fastlane_core/ui/ui' module Fastlane @@ -5,21 +6,24 @@ module Fastlane module Helper class DdgAppleAutomationHelper - # class methods that you define here become available in your action - # as `Helper::DdgAppleAutomationHelper.your_method` - # - ASANA_API_URL = "https://app.asana.com/api/1.0" + ERROR_ASANA_ACCESS_TOKEN_NOT_SET = "ASANA_ACCESS_TOKEN is not set" + end + end +end - def self.show_message - UI.message("Hello from the ddg_apple_automation plugin helper!") - end - - def self.fetch_asana_token - ENV.fetch("ASANA_ACCESS_TOKEN") - rescue KeyError - UI.user_error!("ASANA_ACCESS_TOKEN is not set") - end +module FastlaneCore + class ConfigItem + def self.asana_access_token + FastlaneCore::ConfigItem.new(key: :asana_access_token, + env_name: "ASANA_ACCESS_TOKEN", + description: "Asana access token", + optional: false, + sensitive: true, + type: String, + verify_block: proc do |value| + UI.user_error!(Fastlane::Helper::DdgAppleAutomationHelper::ERROR_ASANA_ACCESS_TOKEN_NOT_SET) if value.to_s.length == 0 + end) end end end diff --git a/lib/fastlane/plugin/ddg_apple_automation/helper/github_actions_helper.rb b/lib/fastlane/plugin/ddg_apple_automation/helper/github_actions_helper.rb index fdfe3d9..eaf8378 100644 --- a/lib/fastlane/plugin/ddg_apple_automation/helper/github_actions_helper.rb +++ b/lib/fastlane/plugin/ddg_apple_automation/helper/github_actions_helper.rb @@ -7,7 +7,13 @@ module Fastlane module Helper class GitHubActionsHelper def self.set_output(key, value) - Action.sh("echo '#{key}=#{value}' >> #{ENV.fetch('GITHUB_OUTPUT', '/dev/null')}") + return unless Helper.is_ci? + + if key.to_s.length == 0 + UI.user_error!("Key cannot be empty") + elsif value.to_s.length > 0 + Action.sh("echo '#{key}=#{value}' >> #{ENV.fetch('GITHUB_OUTPUT', '/dev/null')}") + end end end end diff --git a/spec/asana_extract_task_assignee_action_spec.rb b/spec/asana_extract_task_assignee_action_spec.rb new file mode 100644 index 0000000..3258a90 --- /dev/null +++ b/spec/asana_extract_task_assignee_action_spec.rb @@ -0,0 +1,57 @@ +describe Fastlane::Actions::AsanaExtractTaskAssigneeAction do + describe "#run" do + it "returns the assignee ID when Asana task is assigned" do + expect(HTTParty).to receive(:get).and_return( + double( + success?: true, + parsed_response: { 'data' => { 'assignee' => { 'gid' => '67890' } } } + ) + ) + + expect(test_action("12345")).to eq("67890") + end + + it "returns nil when Asana task is not assigned" do + expect(HTTParty).to receive(:get).and_return( + double( + success?: true, + parsed_response: { 'data' => { 'assignee' => nil } } + ) + ) + + expect(test_action("12345")).to eq(nil) + end + + it "shows error when failed to fetch task assignee" do + expect(HTTParty).to receive(:get).and_return( + double( + success?: false, + code: 401, + message: "Unauthorized" + ) + ) + + expect(Fastlane::UI).to receive(:user_error!).with("Failed to fetch task assignee: (401 Unauthorized)") + + test_action("12345") + end + + it "sets GHA output" do + allow(Fastlane::Helper::GitHubActionsHelper).to receive(:set_output) + + expect(HTTParty).to receive(:get).and_return( + double( + success?: true, + parsed_response: { 'data' => { 'assignee' => { 'gid' => '67890' } } } + ) + ) + + expect(test_action("12345")).to eq("67890") + expect(Fastlane::Helper::GitHubActionsHelper).to have_received(:set_output).with("asana_assignee_id", "67890") + end + end + + def test_action(task_id) + Fastlane::Actions::AsanaExtractTaskAssigneeAction.run(task_id: task_id) + end +end diff --git a/spec/asana_extract_task_id_action_spec.rb b/spec/asana_extract_task_id_action_spec.rb index 977df2d..427765a 100644 --- a/spec/asana_extract_task_id_action_spec.rb +++ b/spec/asana_extract_task_id_action_spec.rb @@ -20,16 +20,7 @@ expect(test_action("https://app.asana.com/0/0/1234/f")).to eq("1234") end - it "does not set GHA output when not in CI" do - allow(Fastlane::Helper).to receive(:is_ci?).and_return(false) - allow(Fastlane::Helper::GitHubActionsHelper).to receive(:set_output) - - expect(test_action("https://app.asana.com/0/12837864576817392/3465387322")).to eq("3465387322") - expect(Fastlane::Helper::GitHubActionsHelper).not_to have_received(:set_output) - end - - it "sets GHA output in CI" do - allow(Fastlane::Helper).to receive(:is_ci?).and_return(true) + it "sets GHA output" do allow(Fastlane::Helper::GitHubActionsHelper).to receive(:set_output) expect(test_action("https://app.asana.com/0/12837864576817392/3465387322")).to eq("3465387322") diff --git a/spec/github_actions_helper_spec.rb b/spec/github_actions_helper_spec.rb new file mode 100644 index 0000000..56667ef --- /dev/null +++ b/spec/github_actions_helper_spec.rb @@ -0,0 +1,58 @@ +describe Fastlane::Helper::GitHubActionsHelper do + describe "#set_output" do + it "sets output when in CI and value is not empty" do + allow(Fastlane::Helper).to receive(:is_ci?).and_return(true) + allow(Fastlane::Action).to receive(:sh) + allow(ENV).to receive(:fetch).with("GITHUB_OUTPUT", "/dev/null").and_return("/dev/null") + + set_output("foo", "bar") + expect(Fastlane::Action).to have_received(:sh).with("echo 'foo=bar' >> /dev/null") + end + + it "honors GITHUB_OUTPUT environment variable when in CI" do + allow(Fastlane::Helper).to receive(:is_ci?).and_return(true) + allow(Fastlane::Action).to receive(:sh) + allow(ENV).to receive(:fetch).with("GITHUB_OUTPUT", "/dev/null").and_return("/tmp/github_output") + + set_output("foo", "bar") + expect(Fastlane::Action).to have_received(:sh).with("echo 'foo=bar' >> /tmp/github_output") + end + + it "does not set output when in CI and value is empty" do + allow(Fastlane::Helper).to receive(:is_ci?).and_return(true) + allow(Fastlane::Action).to receive(:sh) + + set_output("foo", "") + expect(Fastlane::Action).not_to have_received(:sh) + end + + it "does not set output when in CI and value is nil" do + allow(Fastlane::Helper).to receive(:is_ci?).and_return(true) + allow(Fastlane::Action).to receive(:sh) + + set_output("foo", nil) + expect(Fastlane::Action).not_to have_received(:sh) + end + + it "does not set output when not in CI" do + allow(Fastlane::Helper).to receive(:is_ci?).and_return(false) + allow(Fastlane::Action).to receive(:sh) + + set_output("foo", "bar") + expect(Fastlane::Action).not_to have_received(:sh) + end + + it "fails when key is empty" do + allow(Fastlane::Helper).to receive(:is_ci?).and_return(true) + allow(Fastlane::Action).to receive(:sh) + expect(Fastlane::UI).to receive(:user_error!).with("Key cannot be empty") + + set_output("", "bar") + expect(Fastlane::Action).not_to have_received(:sh) + end + end + + def set_output(key, value) + Fastlane::Helper::GitHubActionsHelper.set_output(key, value) + end +end