From 83cdc082dae6fbe48a72d8a86511676c3bbaf830 Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 8 Sep 2022 07:12:21 +0900 Subject: [PATCH 01/69] Use altool instead of using iTMSTransporter for Xcode 14 --- deliver/lib/deliver/runner.rb | 14 +- .../lib/fastlane_core/itunes_transporter.rb | 149 +++++++++++++++++- pilot/lib/pilot/build_manager.rb | 8 +- 3 files changed, 153 insertions(+), 18 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 20460538466..678ea39d9ff 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -206,7 +206,7 @@ def upload_binary pkg_path = options[:pkg] platform = options[:platform] - transporter = transporter_for_selected_team + transporter = transporter_for_selected_team(true) case platform when "ios", "appletvos" @@ -216,7 +216,7 @@ def upload_binary package_path: "/tmp", platform: platform ) - result = transporter.upload(package_path: package_path, asset_path: ipa_path) + result = transporter.upload(package_path: package_path, asset_path: ipa_path, platform: platform) when "osx" package_path = FastlaneCore::PkgUploadPackageBuilder.new.generate( app_id: Deliver.cache[:app].id, @@ -224,7 +224,7 @@ def upload_binary package_path: "/tmp", platform: platform ) - result = transporter.upload(package_path: package_path, asset_path: pkg_path) + result = transporter.upload(package_path: package_path, asset_path: pkg_pat, platform: "macos") else UI.user_error!("No suitable file found for upload for platform: #{options[:platform]}") end @@ -270,17 +270,17 @@ def submit_for_review # If itc_provider was explicitly specified, use it. # If there are multiple teams, infer the provider from the selected team name. # If there are fewer than two teams, don't infer the provider. - def transporter_for_selected_team + def transporter_for_selected_team(upload = false) # Use JWT auth api_token = Spaceship::ConnectAPI.token unless api_token.nil? api_token.refresh! if api_token.expired? - return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text) + return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: upload) end tunes_client = Spaceship::ConnectAPI.client.tunes_client - generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider]) + generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: upload) return generic_transporter unless options[:itc_provider].nil? && tunes_client.teams.count > 1 begin @@ -288,7 +288,7 @@ def transporter_for_selected_team name = team['name'] provider_id = generic_transporter.provider_ids[name] UI.verbose("Inferred provider id #{provider_id} for team #{name}.") - return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id) + return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: upload) rescue => ex UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.") return generic_transporter diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index cde8a51d7d8..bbb96eda831 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -180,9 +180,137 @@ def additional_upload_parameters end end + # Generates commands and executes the altool. + class AltoolTransporterExecutor < TransporterExecutor + ERROR_REGEX = /.*\*\*\*\sError:\s+(.+)/ + + private_constant :ERROR_REGEX + + def execute(command, hide_output) + if Helper.test? + yield(nil) if block_given? + return command + end + + @errors = [] + @warnings = [] + @all_lines = [] + + if hide_output + # Show a one time message instead + UI.success("Waiting for App Store Connect transporter to be finished.") + UI.success("Application Loader progress... this might take a few minutes...") + end + + begin + exit_status = FastlaneCore::FastlanePty.spawn(command) do |command_stdout, command_stdin, pid| + begin + command_stdout.each do |line| + @all_lines << line + parse_line(line, hide_output) # this is where the parsing happens + end + end + end + rescue => ex + # FastlanePty adds exit_status on to StandardError so every error will have a status code + exit_status = ex.exit_status + @errors << ex.to_s + end + + unless exit_status.zero? + @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." + end + + if @warnings.count > 0 + UI.important(@warnings.join("\n")) + end + + if @errors.count > 0 && @all_lines.count > 0 + # Print out the last 18 lines, this is key for non-verbose mode + @all_lines.last(18).each do |line| + UI.important("[altool] #{line}") + end + UI.message("Application Loader output above ^") + UI.error(@errors.join("\n")) + end + + yield(@all_lines) if block_given? + return exit_status.zero? + end + + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil) + use_jwt = !jwt.to_s.empty? + [ + "xcrun altool", + "--upload-app", + ("-u #{username.shellescape}" unless use_jwt), + ("-p #{password.shellescape}" unless use_jwt), + ("--appKey #{jwt}" if use_jwt), + "-t #{platform}", + file_upload_option(source), + additional_upload_parameters, + "-k 100000", + ].compact.join(' ') + end + + def additional_upload_parameters + env_deliver_additional_params = ENV["DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS"] + if env_deliver_additional_params.to_s.strip.empty? + return nil + end + + return env_deliver_additional_params.to_s.strip + end + + def file_upload_option(source) + return "-f #{source.shellescape}" + end + + def handle_error(password) + UI.error("Could not download/upload from App Store Connect!") + end + + def displayable_errors + @errors.map { |error| "[Application Loader Error Output]: #{error}" }.join("\n").gsub!(/"/, "") + end + + private + + def parse_line(line, hide_output) + output_done = false + + re = Regexp.union(SKIP_ERRORS) + if line.match(re) + # Those lines will not be handled like errors or warnings + + elsif line =~ ERROR_REGEX + UI.message("catched #{$1}") + @errors << $1 + + # Check if it's a login error + if $1.include?("Failed to get authorization for username") + + unless Helper.test? + CredentialsManager::AccountManager.new(user: @user).invalid_credentials + UI.error("Please run this tool again to apply the new password") + end + end + + output_done = true + end + + if !hide_output && line =~ OUTPUT_REGEX + # General logging for debug purposes + unless output_done + UI.verbose("[altool]: #{$1}") + end + end + end + end + # Generates commands and executes the iTMSTransporter through the shell script it provides by the same name class ShellScriptTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil) use_jwt = !jwt.to_s.empty? [ '"' + Helper.transporter_path + '"', @@ -278,7 +406,7 @@ def shell_escaped_password(password) # Generates commands and executes the iTMSTransporter by invoking its Java app directly, to avoid the crazy parameter # escaping problems in its accompanying shell script. class JavaTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil) use_jwt = !jwt.to_s.empty? if !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(11) [ @@ -476,7 +604,7 @@ def self.hide_transporter_output? # see: https://github.com/fastlane/fastlane/issues/1524#issuecomment-196370628 # for more information about how to use the iTMSTransporter to list your provider # short names - def initialize(user = nil, password = nil, use_shell_script = false, provider_short_name = nil, jwt = nil) + def initialize(user = nil, password = nil, use_shell_script = false, provider_short_name = nil, jwt = nil, upload: false) # Xcode 6.x doesn't have the same iTMSTransporter Java setup as later Xcode versions, so # we can't default to using the newer direct Java invocation strategy for those versions. use_shell_script ||= Helper.is_mac? && Helper.xcode_version.start_with?('6.') @@ -490,7 +618,14 @@ def initialize(user = nil, password = nil, use_shell_script = false, provider_sh @jwt = jwt - @transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new + if !use_shell_script && upload && !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(14) + UI.verbose("Use altool as transporter.") + @transporter_executor = AltoolTransporterExecutor.new + else + UI.verbose("Use iTMSTransporter as transporter") + @transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new + end + @provider_short_name = provider_short_name end @@ -539,7 +674,7 @@ def download(app_id, dir = nil) # @return (Bool) True if everything worked fine # @raise [Deliver::TransporterTransferError] when something went wrong # when transferring - def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil) + def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform: nil) raise "app_id and dir are required or package_path or asset_path is required" if (app_id.nil? || dir.nil?) && package_path.nil? && asset_path.nil? # Transport can upload .ipa, .dmg, and .pkg files directly with -assetFile @@ -569,8 +704,8 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil) password_placeholder = @jwt.nil? ? 'YourPassword' : nil jwt_placeholder = @jwt.nil? ? nil : 'YourJWT' - command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt) - UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder)) + command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform) + UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform)) begin result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?) diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index bb5ce5ecee2..9e610b54c53 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -47,7 +47,7 @@ def upload(options) end transporter = transporter_for_selected_team(options) - result = transporter.upload(package_path: package_path, asset_path: asset_path) + result = transporter.upload(package_path: package_path, asset_path: asset_path, platform: platform == "osx" ? "macos" : platform) unless result transporter_errors = transporter.displayable_errors @@ -391,13 +391,13 @@ def transporter_for_selected_team(options) api_token = Spaceship::ConnectAPI.token unless api_token.nil? api_token.refresh! if api_token.expired? - return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text) + return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: true) end # Otherwise use username and password tunes_client = Spaceship::ConnectAPI.client ? Spaceship::ConnectAPI.client.tunes_client : nil - generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider]) + generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: true) return generic_transporter if options[:itc_provider] || tunes_client.nil? return generic_transporter unless tunes_client.teams.count > 1 @@ -406,7 +406,7 @@ def transporter_for_selected_team(options) name = team['name'] provider_id = generic_transporter.provider_ids[name] UI.verbose("Inferred provider id #{provider_id} for team #{name}.") - return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id) + return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: true) rescue => ex STDERR.puts(ex.to_s) UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.") From ec4cfee622437005dbfd72ff6ea33ea4a6cc6052 Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 8 Sep 2022 07:34:57 +0900 Subject: [PATCH 02/69] fix linter error --- fake testers_file_path | 1 + .../lib/fastlane_core/itunes_transporter.rb | 15 ++------------- 2 files changed, 3 insertions(+), 13 deletions(-) create mode 100644 fake testers_file_path diff --git a/fake testers_file_path b/fake testers_file_path new file mode 100644 index 00000000000..189e0e7b1c7 --- /dev/null +++ b/fake testers_file_path @@ -0,0 +1 @@ +First,Last,Email,Groups,Installed Version,Install Date diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index bbb96eda831..1f864949553 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -141,13 +141,6 @@ def parse_line(line, hide_output) UI.success("iTunes Transporter successfully finished its job") end end - - if !hide_output && line =~ OUTPUT_REGEX - # General logging for debug purposes - unless output_done - UI.verbose("[Transporter]: #{$1}") - end - end end def file_upload_option(source) @@ -249,7 +242,7 @@ def build_upload_command(username, password, source = "/tmp", provider_short_nam "-t #{platform}", file_upload_option(source), additional_upload_parameters, - "-k 100000", + "-k 100000" ].compact.join(' ') end @@ -279,11 +272,7 @@ def displayable_errors def parse_line(line, hide_output) output_done = false - re = Regexp.union(SKIP_ERRORS) - if line.match(re) - # Those lines will not be handled like errors or warnings - - elsif line =~ ERROR_REGEX + if line =~ ERROR_REGEX UI.message("catched #{$1}") @errors << $1 From f1e057564b504fa0d0cc7a7897ed0b446b4d2e86 Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 8 Sep 2022 07:42:40 +0900 Subject: [PATCH 03/69] fix linter error --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 1f864949553..9f7d12b7937 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -141,6 +141,13 @@ def parse_line(line, hide_output) UI.success("iTunes Transporter successfully finished its job") end end + + if !hide_output && line =~ OUTPUT_REGEX + # General logging for debug purposes + unless output_done + UI.verbose("[Transporter]: #{$1}") + end + end end def file_upload_option(source) @@ -288,7 +295,7 @@ def parse_line(line, hide_output) output_done = true end - if !hide_output && line =~ OUTPUT_REGEX + if !hide_output # General logging for debug purposes unless output_done UI.verbose("[altool]: #{$1}") From c3a66db7380795640dc6cfa4388659d47550883b Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 8 Sep 2022 07:50:30 +0900 Subject: [PATCH 04/69] fix linter error --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 9f7d12b7937..a025564b6d8 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -280,7 +280,6 @@ def parse_line(line, hide_output) output_done = false if line =~ ERROR_REGEX - UI.message("catched #{$1}") @errors << $1 # Check if it's a login error @@ -295,7 +294,7 @@ def parse_line(line, hide_output) output_done = true end - if !hide_output + unless hide_output # General logging for debug purposes unless output_done UI.verbose("[altool]: #{$1}") From 39c919efbff110b90e4217501f4ec541b6ff8a5f Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Fri, 9 Sep 2022 13:46:21 +0900 Subject: [PATCH 05/69] use keyword function for transporter_for_selected_team Co-authored-by: Kohki Miki --- deliver/lib/deliver/runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 678ea39d9ff..b65905a8a2a 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -270,7 +270,7 @@ def submit_for_review # If itc_provider was explicitly specified, use it. # If there are multiple teams, infer the provider from the selected team name. # If there are fewer than two teams, don't infer the provider. - def transporter_for_selected_team(upload = false) + def transporter_for_selected_team(upload: false) # Use JWT auth api_token = Spaceship::ConnectAPI.token unless api_token.nil? From 74f681d776abcc6bde4384f3797dc355e84baa57 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 15:25:19 +0900 Subject: [PATCH 06/69] fix typo and move platform string handling --- deliver/lib/deliver/runner.rb | 2 +- .../lib/fastlane_core/itunes_transporter.rb | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index b65905a8a2a..1a68cb2d24b 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -224,7 +224,7 @@ def upload_binary package_path: "/tmp", platform: platform ) - result = transporter.upload(package_path: package_path, asset_path: pkg_pat, platform: "macos") + result = transporter.upload(package_path: package_path, asset_path: pkg_path, platform: platform) else UI.user_error!("No suitable file found for upload for platform: #{options[:platform]}") end diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index a025564b6d8..c0f148ef11a 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -246,7 +246,7 @@ def build_upload_command(username, password, source = "/tmp", provider_short_nam ("-u #{username.shellescape}" unless use_jwt), ("-p #{password.shellescape}" unless use_jwt), ("--appKey #{jwt}" if use_jwt), - "-t #{platform}", + platform_option(platform), file_upload_option(source), additional_upload_parameters, "-k 100000" @@ -262,10 +262,6 @@ def additional_upload_parameters return env_deliver_additional_params.to_s.strip end - def file_upload_option(source) - return "-f #{source.shellescape}" - end - def handle_error(password) UI.error("Could not download/upload from App Store Connect!") end @@ -276,6 +272,14 @@ def displayable_errors private + def file_upload_option(source) + "-f #{source.shellescape}" + end + + def platform_option(platform) + "-t #{platform == "osx" ? "macox": platform}" + end + def parse_line(line, hide_output) output_done = false From 6d10343cde1946c290875aec8363c391c3da5310 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 15:25:35 +0900 Subject: [PATCH 07/69] remove unecessary return --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index c0f148ef11a..e0180500491 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -189,7 +189,7 @@ class AltoolTransporterExecutor < TransporterExecutor def execute(command, hide_output) if Helper.test? yield(nil) if block_given? - return command + command end @errors = [] @@ -235,7 +235,7 @@ def execute(command, hide_output) end yield(@all_lines) if block_given? - return exit_status.zero? + exit_status.zero? end def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil) From ce9b12db9675b8e45edcbd6ec9384f2531a0f42e Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 15:40:54 +0900 Subject: [PATCH 08/69] create should_use_altool --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index e0180500491..ff72c731f11 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -617,7 +617,7 @@ def initialize(user = nil, password = nil, use_shell_script = false, provider_sh @jwt = jwt - if !use_shell_script && upload && !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(14) + if should_use_altool(upload, use_shell_script) UI.verbose("Use altool as transporter.") @transporter_executor = AltoolTransporterExecutor.new else @@ -791,6 +791,12 @@ def provider_ids TWO_FACTOR_ENV_VARIABLE = "FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD" + # Returns whether altool should be used or ItunesTransporter should be used + def should_use_altool(upload, use_shell_script) + # Xcode 14 no longer supports iTMSTransporter. Use altool instead + !use_shell_script && upload && !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(14) + end + # Returns the password to be used with the transporter def load_password_for_transporter # 3 different sources for the password From 40337e3e9e7cae5ac8bb632bea55fbe47f1e3446 Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Fri, 9 Sep 2022 15:44:18 +0900 Subject: [PATCH 09/69] fix to use unless to make code one line Co-authored-by: Kohki Miki --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index ff72c731f11..b5a63de208e 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -221,9 +221,7 @@ def execute(command, hide_output) @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." end - if @warnings.count > 0 - UI.important(@warnings.join("\n")) - end + UI.important(@warnings.join("\n")) unless @warnings.empty? if @errors.count > 0 && @all_lines.count > 0 # Print out the last 18 lines, this is key for non-verbose mode From 0f2a3d4e596d9b8d344a5b68270ab03d3daba0ab Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Fri, 9 Sep 2022 15:52:41 +0900 Subject: [PATCH 10/69] make code oneline by using unless Co-authored-by: Kohki Miki --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index b5a63de208e..bdc2c16c650 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -217,9 +217,7 @@ def execute(command, hide_output) @errors << ex.to_s end - unless exit_status.zero? - @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." - end + @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero? UI.important(@warnings.join("\n")) unless @warnings.empty? From d6755514d85ba28a28f2dedbf43a30670d093b28 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 16:40:26 +0900 Subject: [PATCH 11/69] improve error message --- .../lib/fastlane_core/itunes_transporter.rb | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index bdc2c16c650..225bdbf0eae 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -182,7 +182,7 @@ def additional_upload_parameters # Generates commands and executes the altool. class AltoolTransporterExecutor < TransporterExecutor - ERROR_REGEX = /.*\*\*\*\sError:\s+(.+)/ + ERROR_REGEX = /\sNSLocalizedFailureReason\s=\s"+(.+)"/ private_constant :ERROR_REGEX @@ -263,7 +263,7 @@ def handle_error(password) end def displayable_errors - @errors.map { |error| "[Application Loader Error Output]: #{error}" }.join("\n").gsub!(/"/, "") + @errors.map { |error| "[Application Loader Error Output]: #{error}" }.join("\n") end private @@ -281,16 +281,6 @@ def parse_line(line, hide_output) if line =~ ERROR_REGEX @errors << $1 - - # Check if it's a login error - if $1.include?("Failed to get authorization for username") - - unless Helper.test? - CredentialsManager::AccountManager.new(user: @user).invalid_credentials - UI.error("Please run this tool again to apply the new password") - end - end - output_done = true end From fa388c7db71b6b788aa2aa225f3b4d519c4c7250 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 18:51:35 +0900 Subject: [PATCH 12/69] fix to support apple connect api key --- deliver/lib/deliver/runner.rb | 8 +++--- .../lib/fastlane_core/itunes_transporter.rb | 28 ++++++++++++------- pilot/lib/pilot/build_manager.rb | 6 ++-- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 1a68cb2d24b..c91c2507337 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -206,7 +206,7 @@ def upload_binary pkg_path = options[:pkg] platform = options[:platform] - transporter = transporter_for_selected_team(true) + transporter = transporter_for_selected_team(upload: true) case platform when "ios", "appletvos" @@ -275,12 +275,12 @@ def transporter_for_selected_team(upload: false) api_token = Spaceship::ConnectAPI.token unless api_token.nil? api_token.refresh! if api_token.expired? - return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: upload) + return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: upload, api_key: options[:api_key]) end tunes_client = Spaceship::ConnectAPI.client.tunes_client - generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: upload) + generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: upload, api_key: options[:api_key]) return generic_transporter unless options[:itc_provider].nil? && tunes_client.teams.count > 1 begin @@ -288,7 +288,7 @@ def transporter_for_selected_team(upload: false) name = team['name'] provider_id = generic_transporter.provider_ids[name] UI.verbose("Inferred provider id #{provider_id} for team #{name}.") - return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: upload) + return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: upload, api_key: options[:api_key]) rescue => ex UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.") return generic_transporter diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 225bdbf0eae..e00da1b534a 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -234,14 +234,16 @@ def execute(command, hide_output) exit_status.zero? end - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_jwt = !jwt.to_s.empty? [ + ("API_PRIVATE_KEYS_DIR=#{api_key[:key_filepath]}" if use_jwt && api_key), "xcrun altool", "--upload-app", - ("-u #{username.shellescape}" unless use_jwt), - ("-p #{password.shellescape}" unless use_jwt), - ("--appKey #{jwt}" if use_jwt), + ("-u #{username.shellescape}" unless api_key), + ("-p #{password.shellescape}" unless api_key), + ("--apiKey #{api_key[:key_id]}" if api_key), + ("--apiIssuer #{api_key[:issuer_id]}" if api_key), platform_option(platform), file_upload_option(source), additional_upload_parameters, @@ -295,7 +297,7 @@ def parse_line(line, hide_output) # Generates commands and executes the iTMSTransporter through the shell script it provides by the same name class ShellScriptTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_jwt = !jwt.to_s.empty? [ '"' + Helper.transporter_path + '"', @@ -391,7 +393,7 @@ def shell_escaped_password(password) # Generates commands and executes the iTMSTransporter by invoking its Java app directly, to avoid the crazy parameter # escaping problems in its accompanying shell script. class JavaTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_jwt = !jwt.to_s.empty? if !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(11) [ @@ -589,7 +591,7 @@ def self.hide_transporter_output? # see: https://github.com/fastlane/fastlane/issues/1524#issuecomment-196370628 # for more information about how to use the iTMSTransporter to list your provider # short names - def initialize(user = nil, password = nil, use_shell_script = false, provider_short_name = nil, jwt = nil, upload: false) + def initialize(user = nil, password = nil, use_shell_script = false, provider_short_name = nil, jwt = nil, upload: false, api_key: nil) # Xcode 6.x doesn't have the same iTMSTransporter Java setup as later Xcode versions, so # we can't default to using the newer direct Java invocation strategy for those versions. use_shell_script ||= Helper.is_mac? && Helper.xcode_version.start_with?('6.') @@ -602,6 +604,7 @@ def initialize(user = nil, password = nil, use_shell_script = false, provider_sh end @jwt = jwt + @api_key = api_key if should_use_altool(upload, use_shell_script) UI.verbose("Use altool as transporter.") @@ -688,9 +691,14 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform password_placeholder = @jwt.nil? ? 'YourPassword' : nil jwt_placeholder = @jwt.nil? ? nil : 'YourJWT' - - command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform) - UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform)) + api_key_plaseholder = @api_key.nil? ? nil : { + key_id: "YourKeyID", + issuer_id: "YourIssuerID", + key_filepath: "YourKeyFilepath" + } + + command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key) + UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_plaseholder)) begin result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?) diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index 9e610b54c53..b85628d658c 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -391,13 +391,13 @@ def transporter_for_selected_team(options) api_token = Spaceship::ConnectAPI.token unless api_token.nil? api_token.refresh! if api_token.expired? - return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: true) + return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: true, api_key: options[:api_key]) end # Otherwise use username and password tunes_client = Spaceship::ConnectAPI.client ? Spaceship::ConnectAPI.client.tunes_client : nil - generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: true) + generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: true, api_key: options[:api_key]) return generic_transporter if options[:itc_provider] || tunes_client.nil? return generic_transporter unless tunes_client.teams.count > 1 @@ -406,7 +406,7 @@ def transporter_for_selected_team(options) name = team['name'] provider_id = generic_transporter.provider_ids[name] UI.verbose("Inferred provider id #{provider_id} for team #{name}.") - return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: true) + return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: true, api_key: options[:api_key]) rescue => ex STDERR.puts(ex.to_s) UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.") From dcb97a87103530399423677a02a2791db20a06d5 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 18:53:01 +0900 Subject: [PATCH 13/69] fix jwt check --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index e00da1b534a..f232242aab2 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -237,7 +237,7 @@ def execute(command, hide_output) def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_jwt = !jwt.to_s.empty? [ - ("API_PRIVATE_KEYS_DIR=#{api_key[:key_filepath]}" if use_jwt && api_key), + ("API_PRIVATE_KEYS_DIR=#{api_key[:key_filepath]}" if api_key), "xcrun altool", "--upload-app", ("-u #{username.shellescape}" unless api_key), From 5bd7d3f62686f8b15f36162099daa630d1e289d9 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 18:54:52 +0900 Subject: [PATCH 14/69] fix to set? for boolean function --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index f232242aab2..df11907e5e6 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -606,7 +606,7 @@ def initialize(user = nil, password = nil, use_shell_script = false, provider_sh @jwt = jwt @api_key = api_key - if should_use_altool(upload, use_shell_script) + if should_use_altool?(upload, use_shell_script) UI.verbose("Use altool as transporter.") @transporter_executor = AltoolTransporterExecutor.new else @@ -786,7 +786,7 @@ def provider_ids TWO_FACTOR_ENV_VARIABLE = "FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD" # Returns whether altool should be used or ItunesTransporter should be used - def should_use_altool(upload, use_shell_script) + def should_use_altool?(upload, use_shell_script) # Xcode 14 no longer supports iTMSTransporter. Use altool instead !use_shell_script && upload && !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(14) end From 2023aa8ae80afc611c30ddfc6960b0fd82b13867 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 19:48:53 +0900 Subject: [PATCH 15/69] fix rubocup issue --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index df11907e5e6..e29cccc96a6 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -235,7 +235,6 @@ def execute(command, hide_output) end def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) - use_jwt = !jwt.to_s.empty? [ ("API_PRIVATE_KEYS_DIR=#{api_key[:key_filepath]}" if api_key), "xcrun altool", @@ -275,7 +274,7 @@ def file_upload_option(source) end def platform_option(platform) - "-t #{platform == "osx" ? "macox": platform}" + "-t #{platform == 'osx' ? 'macox' : platform}" end def parse_line(line, hide_output) @@ -691,11 +690,8 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform password_placeholder = @jwt.nil? ? 'YourPassword' : nil jwt_placeholder = @jwt.nil? ? nil : 'YourJWT' - api_key_plaseholder = @api_key.nil? ? nil : { - key_id: "YourKeyID", - issuer_id: "YourIssuerID", - key_filepath: "YourKeyFilepath" - } + api_key_plaseholder = nil unless @api_key.nil? + api_key_plaseholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_filepath: "YourKeyFilepath" } if @api_key.nil? command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key) UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_plaseholder)) From 7a13c485005df190367485d1fd9d4b868ba18308 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 19:49:31 +0900 Subject: [PATCH 16/69] fix rubocup issue --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index e29cccc96a6..b68b1919ea5 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -217,7 +217,7 @@ def execute(command, hide_output) @errors << ex.to_s end - @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero? + @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero? UI.important(@warnings.join("\n")) unless @warnings.empty? From 8df955990a51391ebb324b6a350e97edb43ab4a7 Mon Sep 17 00:00:00 2001 From: freddi Date: Fri, 9 Sep 2022 19:51:21 +0900 Subject: [PATCH 17/69] fix test --- deliver/spec/runner_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deliver/spec/runner_spec.rb b/deliver/spec/runner_spec.rb index 1fcd03e2de8..00c07f69616 100644 --- a/deliver/spec/runner_spec.rb +++ b/deliver/spec/runner_spec.rb @@ -63,7 +63,7 @@ def provider_ids expect_any_instance_of(FastlaneCore::IpaUploadPackageBuilder).to receive(:generate) .with(app_id: 'YI8C2AS', ipa_path: 'ACME.ipa', package_path: '/tmp', platform: 'ios') .and_return('path') - expect(transporter).to receive(:upload).with(package_path: 'path', asset_path: 'ACME.ipa').and_return(true) + expect(transporter).to receive(:upload).with(package_path: 'path', asset_path: 'ACME.ipa', platform: 'ios').and_return(true) runner.upload_binary end end @@ -77,7 +77,7 @@ def provider_ids expect_any_instance_of(FastlaneCore::IpaUploadPackageBuilder).to receive(:generate) .with(app_id: 'YI8C2AS', ipa_path: 'ACME.ipa', package_path: '/tmp', platform: 'appletvos') .and_return('path') - expect(transporter).to receive(:upload).with(package_path: 'path', asset_path: 'ACME.ipa').and_return(true) + expect(transporter).to receive(:upload).with(package_path: 'path', asset_path: 'ACME.ipa', platform: 'appletvos').and_return(true) runner.upload_binary end end @@ -93,7 +93,7 @@ def provider_ids expect_any_instance_of(FastlaneCore::PkgUploadPackageBuilder).to receive(:generate) .with(app_id: 'YI8C2AS', pkg_path: 'ACME.pkg', package_path: '/tmp', platform: 'osx') .and_return('path') - expect(transporter).to receive(:upload).with(package_path: 'path', asset_path: 'ACME.pkg').and_return(true) + expect(transporter).to receive(:upload).with(package_path: 'path', asset_path: 'ACME.pkg', platform: 'osx').and_return(true) runner.upload_binary end end From ed28c906445c0d2f88a825983bb723b8e0774854 Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Fri, 9 Sep 2022 20:13:48 +0900 Subject: [PATCH 18/69] fix to call upload without replacement --- pilot/lib/pilot/build_manager.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index b85628d658c..d3d38c169cb 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -47,7 +47,7 @@ def upload(options) end transporter = transporter_for_selected_team(options) - result = transporter.upload(package_path: package_path, asset_path: asset_path, platform: platform == "osx" ? "macos" : platform) + result = transporter.upload(package_path: package_path, asset_path: asset_path, platform: platform) unless result transporter_errors = transporter.displayable_errors From 375f9511eb8f77fa6180f113e4a834436f218236 Mon Sep 17 00:00:00 2001 From: freddi Date: Sat, 10 Sep 2022 07:05:43 +0900 Subject: [PATCH 19/69] fix typo --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index b68b1919ea5..5d231af6f0c 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -690,11 +690,11 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform password_placeholder = @jwt.nil? ? 'YourPassword' : nil jwt_placeholder = @jwt.nil? ? nil : 'YourJWT' - api_key_plaseholder = nil unless @api_key.nil? - api_key_plaseholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_filepath: "YourKeyFilepath" } if @api_key.nil? + api_key_placeholder = nil unless @api_key.nil? + api_key_placeholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_filepath: "YourKeyFilepath" } if @api_key.nil? command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key) - UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_plaseholder)) + UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder)) begin result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?) From 711eb3cd3835eb6068a7b2a4bc29680c6650b7ab Mon Sep 17 00:00:00 2001 From: freddi Date: Sat, 10 Sep 2022 07:35:07 +0900 Subject: [PATCH 20/69] fix checking apikey available or not --- .../lib/fastlane_core/itunes_transporter.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 5d231af6f0c..3b16e6f5c27 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -235,14 +235,15 @@ def execute(command, hide_output) end def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) + use_api_key = !api_key.nil? [ - ("API_PRIVATE_KEYS_DIR=#{api_key[:key_filepath]}" if api_key), + ("API_PRIVATE_KEYS_DIR=#{api_key[:key_filepath]}" if use_api_key), "xcrun altool", "--upload-app", - ("-u #{username.shellescape}" unless api_key), - ("-p #{password.shellescape}" unless api_key), - ("--apiKey #{api_key[:key_id]}" if api_key), - ("--apiIssuer #{api_key[:issuer_id]}" if api_key), + ("-u #{username.shellescape}" unless use_api_key), + ("-p #{password.shellescape}" unless use_api_key), + ("--apiKey #{api_key[:key_id]}" if use_api_key), + ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), platform_option(platform), file_upload_option(source), additional_upload_parameters, @@ -690,8 +691,8 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform password_placeholder = @jwt.nil? ? 'YourPassword' : nil jwt_placeholder = @jwt.nil? ? nil : 'YourJWT' - api_key_placeholder = nil unless @api_key.nil? - api_key_placeholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_filepath: "YourKeyFilepath" } if @api_key.nil? + api_key_placeholder = nil unless !@api_key.nil? + api_key_placeholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_filepath: "YourKeyFilepath" } if !@api_key.nil? command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key) UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder)) From 747178f1ed4cd5866a218f2eecfedfb1dd68d119 Mon Sep 17 00:00:00 2001 From: freddi Date: Sat, 10 Sep 2022 09:12:57 +0900 Subject: [PATCH 21/69] fix to generate p8 file for every calling altool --- .../lib/fastlane_core/itunes_transporter.rb | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 3b16e6f5c27..da533e00b56 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -237,7 +237,7 @@ def execute(command, hide_output) def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_api_key = !api_key.nil? [ - ("API_PRIVATE_KEYS_DIR=#{api_key[:key_filepath]}" if use_api_key), + ("API_PRIVATE_KEYS_DIR=#{Dir.tmpdir}" if use_api_key), "xcrun altool", "--upload-app", ("-u #{username.shellescape}" unless use_api_key), @@ -691,8 +691,19 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform password_placeholder = @jwt.nil? ? 'YourPassword' : nil jwt_placeholder = @jwt.nil? ? nil : 'YourJWT' - api_key_placeholder = nil unless !@api_key.nil? - api_key_placeholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_filepath: "YourKeyFilepath" } if !@api_key.nil? + + # Handle AppStore Connect API + use_api_key = !@api_key.nil? + api_key_placeholder = nil unless use_api_key + api_key_placeholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID" } if use_api_key + + if use_api_key + # Specified p8 needs to be generated to call altool + tmp_p8_file_path = File.join(Dir.tmpdir, "AuthKey_#{@api_key[:key_id]}.p8") + p8 = File.open(tmp_p8_file_path, "w") + p8.write(@api_key[:key]) + p8.close + end command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key) UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder)) @@ -702,6 +713,11 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform rescue TransporterRequiresApplicationSpecificPasswordError => ex handle_two_step_failure(ex) return upload(app_id, dir, package_path: package_path, asset_path: asset_path) + ensure + if use_api_key + tmp_p8_file_path = File.join(Dir.tmpdir, "AuthKey_#{@api_key[:key_id]}.p8") + FileUtils.rm_f(tmp_p8_file_path) + end end if result From 13afc8ccf98878de690b5568ea33de7a3c226dae Mon Sep 17 00:00:00 2001 From: Manish Rathi Date: Sat, 10 Sep 2022 15:17:19 +0200 Subject: [PATCH 22/69] PR review fixes (Remove unused file, autogenerated by uni-tests + improved verbose logs) --- fake testers_file_path | 1 - fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 fake testers_file_path diff --git a/fake testers_file_path b/fake testers_file_path deleted file mode 100644 index 189e0e7b1c7..00000000000 --- a/fake testers_file_path +++ /dev/null @@ -1 +0,0 @@ -First,Last,Email,Groups,Installed Version,Install Date diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index da533e00b56..e08010084ab 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -607,10 +607,10 @@ def initialize(user = nil, password = nil, use_shell_script = false, provider_sh @api_key = api_key if should_use_altool?(upload, use_shell_script) - UI.verbose("Use altool as transporter.") + UI.verbose("Using altool as transporter.") @transporter_executor = AltoolTransporterExecutor.new else - UI.verbose("Use iTMSTransporter as transporter") + UI.verbose("Using iTMSTransporter as transporter.") @transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new end From d36bf23402b6d4c6b4681fc73f355a7b6819f95e Mon Sep 17 00:00:00 2001 From: Manish Rathi Date: Sat, 10 Sep 2022 16:00:46 +0200 Subject: [PATCH 23/69] Fix itunes_transporter_spec.rb which was failing in Xcode14 https://github.com/fastlane/fastlane/pull/20631/files#r967653482 --- fastlane_core/spec/itunes_transporter_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index 0d7faaa1326..dc85b9dc02e 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -1110,6 +1110,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) describe "with `FASTLANE_ITUNES_TRANSPORTER_USE_SHELL_SCRIPT` set" do before(:each) do ENV["FASTLANE_ITUNES_TRANSPORTER_USE_SHELL_SCRIPT"] = "1" + allow(FastlaneCore::Helper).to receive(:itms_path).and_return('/tmp') allow(File).to receive(:exist?).with("C:/Program Files (x86)/itms").and_return(true) if FastlaneCore::Helper.windows? end @@ -1139,6 +1140,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) describe "with no special configuration" do before(:each) do + allow(FastlaneCore::Helper).to receive(:itms_path).and_return('/tmp') allow(File).to receive(:exist?).and_return(true) unless FastlaneCore::Helper.mac? ENV.delete("FASTLANE_ITUNES_TRANSPORTER_USE_SHELL_SCRIPT") end @@ -1273,6 +1275,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) describe "with simulated no-test environment" do before(:each) do allow(FastlaneCore::Helper).to receive(:test?).and_return(false) + allow(FastlaneCore::Helper).to receive(:itms_path).and_return('/tmp') @transporter = FastlaneCore::ItunesTransporter.new(email, password, false) end From e4e44ac18ed8a8b959d7383d157dd2e065087c02 Mon Sep 17 00:00:00 2001 From: Manish Rathi Date: Sat, 10 Sep 2022 16:49:11 +0200 Subject: [PATCH 24/69] Fix helper_spec.rb which was failing in Xcode14 https://github.com/fastlane/fastlane/pull/20631/files#r967653482 --- fastlane_core/spec/helper_spec.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fastlane_core/spec/helper_spec.rb b/fastlane_core/spec/helper_spec.rb index def7af07be3..31f80be8ef6 100644 --- a/fastlane_core/spec/helper_spec.rb +++ b/fastlane_core/spec/helper_spec.rb @@ -144,7 +144,9 @@ end it "#transporter_path", requires_xcode: true do - expect(FastlaneCore::Helper.transporter_path).to match(%r{/Applications/Xcode.*.app/Contents/Applications/Application Loader.app/Contents/itms/bin/iTMSTransporter|/Applications/Xcode.*.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Versions/A/itms/bin/iTMSTransporter}) + unless FastlaneCore::Helper.xcode_at_least?("14") + expect(FastlaneCore::Helper.transporter_path).to match(%r{/Applications/Xcode.*.app/Contents/Applications/Application Loader.app/Contents/itms/bin/iTMSTransporter|/Applications/Xcode.*.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Versions/A/itms/bin/iTMSTransporter}) + end end it "#xcode_version", requires_xcode: true do @@ -178,7 +180,13 @@ context "#itms_path" do it "default", requires_xcode: true do stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => nil }) - expect(FastlaneCore::Helper.itms_path).to match(/itms/) + + if FastlaneCore::Helper.xcode_at_least?("14") + expect(FastlaneCore::UI).to receive(:user_error!).with(/Could not find transporter/) + FastlaneCore::Helper.itms_path + else + expect(FastlaneCore::Helper.itms_path).to match(/itms/) + end end it "uses FASTLANE_ITUNES_TRANSPORTER_PATH", requires_xcode: true do From 4f677a6e6e99134ee6ca603b85d2dac582e4a1be Mon Sep 17 00:00:00 2001 From: freddi Date: Sun, 11 Sep 2022 01:24:54 +0900 Subject: [PATCH 25/69] support base64 key_content for using altool with appstore connect apikey --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index e08010084ab..0a04a76cded 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -701,7 +701,8 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform # Specified p8 needs to be generated to call altool tmp_p8_file_path = File.join(Dir.tmpdir, "AuthKey_#{@api_key[:key_id]}.p8") p8 = File.open(tmp_p8_file_path, "w") - p8.write(@api_key[:key]) + key_content = @api_key[:is_key_content_base64] ? Base64.decode64(@api_key[:key]) : @api_key[:key] + p8.write(key_content) p8.close end From 9988e33aecedff313164c4a441f80760a95d42f6 Mon Sep 17 00:00:00 2001 From: freddi Date: Sun, 11 Sep 2022 06:57:15 +0900 Subject: [PATCH 26/69] fix typo --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 0a04a76cded..eaf976a2275 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -275,7 +275,7 @@ def file_upload_option(source) end def platform_option(platform) - "-t #{platform == 'osx' ? 'macox' : platform}" + "-t #{platform == 'osx' ? 'macos' : platform}" end def parse_line(line, hide_output) From 4ebf0092ebcfbf627c1ea65630c03af48ada7aa5 Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Sun, 11 Sep 2022 07:43:55 +0900 Subject: [PATCH 27/69] fix to remove un-necessary begin Co-authored-by: Olivier Halligon --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index eaf976a2275..6ae08e3bf7a 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -204,11 +204,9 @@ def execute(command, hide_output) begin exit_status = FastlaneCore::FastlanePty.spawn(command) do |command_stdout, command_stdin, pid| - begin - command_stdout.each do |line| - @all_lines << line - parse_line(line, hide_output) # this is where the parsing happens - end + command_stdout.each do |line| + @all_lines << line + parse_line(line, hide_output) # this is where the parsing happens end end rescue => ex From ddb437aaad45b3cad3f15f9bf96c753ce659f51b Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Sun, 11 Sep 2022 07:44:58 +0900 Subject: [PATCH 28/69] fix to use unless Co-authored-by: Olivier Halligon --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 6ae08e3bf7a..c4a640e79b6 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -219,7 +219,7 @@ def execute(command, hide_output) UI.important(@warnings.join("\n")) unless @warnings.empty? - if @errors.count > 0 && @all_lines.count > 0 + unless @errors.empty? || @all_lines.empty? # Print out the last 18 lines, this is key for non-verbose mode @all_lines.last(18).each do |line| UI.important("[altool] #{line}") From b4f5324a4b27b2f611fbc1744c00e54aab5b147f Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Sun, 11 Sep 2022 07:49:57 +0900 Subject: [PATCH 29/69] improve showing error on UI Co-authored-by: Olivier Halligon --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index c4a640e79b6..72fd7a4a2ff 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -225,7 +225,7 @@ def execute(command, hide_output) UI.important("[altool] #{line}") end UI.message("Application Loader output above ^") - UI.error(@errors.join("\n")) + @errors.each { |error| UI.error(error) } end yield(@all_lines) if block_given? From 44bf7aaf775a90cf9e02101bc070167653fe2bc4 Mon Sep 17 00:00:00 2001 From: freddi Date: Sun, 11 Sep 2022 07:50:53 +0900 Subject: [PATCH 30/69] fix to remove warning in altool executer --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 72fd7a4a2ff..0ef442fd316 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -193,7 +193,6 @@ def execute(command, hide_output) end @errors = [] - @warnings = [] @all_lines = [] if hide_output @@ -217,8 +216,6 @@ def execute(command, hide_output) @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero? - UI.important(@warnings.join("\n")) unless @warnings.empty? - unless @errors.empty? || @all_lines.empty? # Print out the last 18 lines, this is key for non-verbose mode @all_lines.last(18).each do |line| From 01a58737a9a805b3d8034a63f8c94d7725a992e0 Mon Sep 17 00:00:00 2001 From: freddi Date: Sun, 11 Sep 2022 08:26:26 +0900 Subject: [PATCH 31/69] improve error log --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 0ef442fd316..24d68344120 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -182,7 +182,7 @@ def additional_upload_parameters # Generates commands and executes the altool. class AltoolTransporterExecutor < TransporterExecutor - ERROR_REGEX = /\sNSLocalizedFailureReason\s=\s"+(.+)"/ + ERROR_REGEX = /\*\*\* Error:\s+(.+)/ private_constant :ERROR_REGEX @@ -217,8 +217,11 @@ def execute(command, hide_output) @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero? unless @errors.empty? || @all_lines.empty? - # Print out the last 18 lines, this is key for non-verbose mode - @all_lines.last(18).each do |line| + # Print out the last lines until shows error + # If error text is not detected, it will be 20 lines + # This is key for non-verbose mode + error_line_index = @all_lines.each_index.select { |i| ERROR_REGEX.match?(@all_lines[i]) }.last + @all_lines.last(error_line_index.nil? ? 20 : (@all_lines.length - error_line_index + 1)).each do |line| UI.important("[altool] #{line}") end UI.message("Application Loader output above ^") @@ -284,7 +287,7 @@ def parse_line(line, hide_output) unless hide_output # General logging for debug purposes unless output_done - UI.verbose("[altool]: #{$1}") + UI.verbose("[altool]: #{line}") end end end From 7490c5c0742d7e3eba540b3a7b61c9a4f70bffda Mon Sep 17 00:00:00 2001 From: freddi Date: Sun, 11 Sep 2022 08:51:15 +0900 Subject: [PATCH 32/69] add some small fix --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 24d68344120..a094ba31806 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -217,10 +217,10 @@ def execute(command, hide_output) @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero? unless @errors.empty? || @all_lines.empty? - # Print out the last lines until shows error + # Print the last lines that appear after the last error from the logs # If error text is not detected, it will be 20 lines # This is key for non-verbose mode - error_line_index = @all_lines.each_index.select { |i| ERROR_REGEX.match?(@all_lines[i]) }.last + error_line_index = @all_lines.rindex { |line| ERROR_REGEX.match?(line) } @all_lines.last(error_line_index.nil? ? 20 : (@all_lines.length - error_line_index + 1)).each do |line| UI.important("[altool] #{line}") end From 388726bbfd5b32ba4c8546576ede1def28d00a4f Mon Sep 17 00:00:00 2001 From: freddi Date: Sun, 11 Sep 2022 09:12:14 +0900 Subject: [PATCH 33/69] fix code format --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index a094ba31806..e8b9552a50c 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -221,7 +221,7 @@ def execute(command, hide_output) # If error text is not detected, it will be 20 lines # This is key for non-verbose mode error_line_index = @all_lines.rindex { |line| ERROR_REGEX.match?(line) } - @all_lines.last(error_line_index.nil? ? 20 : (@all_lines.length - error_line_index + 1)).each do |line| + @all_lines[(error_line_index || -20)..-1].each do |line| UI.important("[altool] #{line}") end UI.message("Application Loader output above ^") From b070b587b865271a00bb1529e3eb8917d1c7fbe6 Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Sun, 11 Sep 2022 12:49:03 +0900 Subject: [PATCH 34/69] fix to remove unnecessary return Co-authored-by: Kohki Miki --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index e8b9552a50c..96b5fe504d2 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -255,7 +255,7 @@ def additional_upload_parameters return nil end - return env_deliver_additional_params.to_s.strip + env_deliver_additional_params.to_s.strip end def handle_error(password) From 1cdc8170f8fe70a9c777f44fc7984ddb5b5bf503 Mon Sep 17 00:00:00 2001 From: freddi Date: Sun, 11 Sep 2022 12:51:52 +0900 Subject: [PATCH 35/69] fix to use File.open() |p8| --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 96b5fe504d2..c7bf5d63bf9 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -698,10 +698,10 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform if use_api_key # Specified p8 needs to be generated to call altool tmp_p8_file_path = File.join(Dir.tmpdir, "AuthKey_#{@api_key[:key_id]}.p8") - p8 = File.open(tmp_p8_file_path, "w") - key_content = @api_key[:is_key_content_base64] ? Base64.decode64(@api_key[:key]) : @api_key[:key] - p8.write(key_content) - p8.close + File.open(tmp_p8_file_path, "w") do |p8| + key_content = @api_key[:is_key_content_base64] ? Base64.decode64(@api_key[:key]) : @api_key[:key] + p8.write(key_content) + end end command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key) From c82e99a896e5a07978c8d114948ca3ee6c88ef3b Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 03:32:09 +0900 Subject: [PATCH 36/69] fix to use mktmpdir for saving p8 temp --- .../lib/fastlane_core/itunes_transporter.rb | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index c7bf5d63bf9..703ba70f429 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -232,10 +232,10 @@ def execute(command, hide_output) exit_status.zero? end - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil, p8_dir = nil) use_api_key = !api_key.nil? [ - ("API_PRIVATE_KEYS_DIR=#{Dir.tmpdir}" if use_api_key), + ("API_PRIVATE_KEYS_DIR=#{p8_dir}" if use_api_key), "xcrun altool", "--upload-app", ("-u #{username.shellescape}" unless use_api_key), @@ -295,7 +295,7 @@ def parse_line(line, hide_output) # Generates commands and executes the iTMSTransporter through the shell script it provides by the same name class ShellScriptTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil, p8_dir = nil) use_jwt = !jwt.to_s.empty? [ '"' + Helper.transporter_path + '"', @@ -391,7 +391,7 @@ def shell_escaped_password(password) # Generates commands and executes the iTMSTransporter by invoking its Java app directly, to avoid the crazy parameter # escaping problems in its accompanying shell script. class JavaTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil, p8_dir = nil) use_jwt = !jwt.to_s.empty? if !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(11) [ @@ -692,20 +692,20 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform # Handle AppStore Connect API use_api_key = !@api_key.nil? - api_key_placeholder = nil unless use_api_key - api_key_placeholder = { key_id: "YourKeyID", issuer_id: "YourIssuerID" } if use_api_key + api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID" } : nil + tmp_p8_dir_path = nil if use_api_key + tmp_p8_dir_path = Dir.mktmpdir("deliver-") # Specified p8 needs to be generated to call altool - tmp_p8_file_path = File.join(Dir.tmpdir, "AuthKey_#{@api_key[:key_id]}.p8") - File.open(tmp_p8_file_path, "w") do |p8| + File.open(File.join(tmp_p8_dir_path, "AuthKey_#{@api_key[:key_id]}.p8"), "w") do |p8| key_content = @api_key[:is_key_content_base64] ? Base64.decode64(@api_key[:key]) : @api_key[:key] p8.write(key_content) end end - command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key) - UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder)) + command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key, tmp_p8_dir_path) + UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder, tmp_p8_dir_path)) begin result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?) @@ -714,8 +714,7 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform return upload(app_id, dir, package_path: package_path, asset_path: asset_path) ensure if use_api_key - tmp_p8_file_path = File.join(Dir.tmpdir, "AuthKey_#{@api_key[:key_id]}.p8") - FileUtils.rm_f(tmp_p8_file_path) + FileUtils.rm_rf(tmp_p8_dir_path) unless tmp_p8_dir_path.nil? end end From bdbacb54d7eb783e6b126226df0d1301c14d6e7d Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 03:43:08 +0900 Subject: [PATCH 37/69] fix linter issue --- .../lib/fastlane_core/itunes_transporter.rb | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 703ba70f429..a4162295e91 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -232,10 +232,10 @@ def execute(command, hide_output) exit_status.zero? end - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil, p8_dir = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_api_key = !api_key.nil? [ - ("API_PRIVATE_KEYS_DIR=#{p8_dir}" if use_api_key), + ("API_PRIVATE_KEYS_DIR=#{api_key[:key_dir]}" if use_api_key), "xcrun altool", "--upload-app", ("-u #{username.shellescape}" unless use_api_key), @@ -295,7 +295,7 @@ def parse_line(line, hide_output) # Generates commands and executes the iTMSTransporter through the shell script it provides by the same name class ShellScriptTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil, p8_dir = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_jwt = !jwt.to_s.empty? [ '"' + Helper.transporter_path + '"', @@ -391,7 +391,7 @@ def shell_escaped_password(password) # Generates commands and executes the iTMSTransporter by invoking its Java app directly, to avoid the crazy parameter # escaping problems in its accompanying shell script. class JavaTransporterExecutor < TransporterExecutor - def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil, p8_dir = nil) + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) use_jwt = !jwt.to_s.empty? if !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(11) [ @@ -692,20 +692,21 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform # Handle AppStore Connect API use_api_key = !@api_key.nil? - api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID" } : nil + api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_dir: "YourTmpP8KeyDir" } : nil - tmp_p8_dir_path = nil + api_key = nil if use_api_key - tmp_p8_dir_path = Dir.mktmpdir("deliver-") + api_key = @api_key.clone + api_key[:key_dir] = Dir.mktmpdir("deliver-") # Specified p8 needs to be generated to call altool - File.open(File.join(tmp_p8_dir_path, "AuthKey_#{@api_key[:key_id]}.p8"), "w") do |p8| - key_content = @api_key[:is_key_content_base64] ? Base64.decode64(@api_key[:key]) : @api_key[:key] + File.open(File.join(api_key[:key_dir], "AuthKey_#{api_key[:key_id]}.p8"), "w") do |p8| + key_content = api_key[:is_key_content_base64] ? Base64.decode64(api_key[:key]) : @api_key[:key] p8.write(key_content) end end - command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, @api_key, tmp_p8_dir_path) - UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder, tmp_p8_dir_path)) + command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, api_key) + UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder)) begin result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?) @@ -714,7 +715,7 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform return upload(app_id, dir, package_path: package_path, asset_path: asset_path) ensure if use_api_key - FileUtils.rm_rf(tmp_p8_dir_path) unless tmp_p8_dir_path.nil? + FileUtils.rm_rf(api_key[:key_dir]) unless api_key.nil? end end From 00c974cc7593f2fc204a95c9f056bbfc481753fa Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 03:44:58 +0900 Subject: [PATCH 38/69] fix to use wb option when making p8 file --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index a4162295e91..f4cb578e104 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -699,7 +699,7 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform api_key = @api_key.clone api_key[:key_dir] = Dir.mktmpdir("deliver-") # Specified p8 needs to be generated to call altool - File.open(File.join(api_key[:key_dir], "AuthKey_#{api_key[:key_id]}.p8"), "w") do |p8| + File.open(File.join(api_key[:key_dir], "AuthKey_#{api_key[:key_id]}.p8"), "wb") do |p8| key_content = api_key[:is_key_content_base64] ? Base64.decode64(api_key[:key]) : @api_key[:key] p8.write(key_content) end From 1994860af01ef446fe1154b8be050a64f63e687b Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 05:13:34 +0900 Subject: [PATCH 39/69] add unit test for altool case --- .../lib/fastlane_core/itunes_transporter.rb | 2 +- fastlane_core/spec/itunes_transporter_spec.rb | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index f4cb578e104..d91712ea0b8 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -189,7 +189,7 @@ class AltoolTransporterExecutor < TransporterExecutor def execute(command, hide_output) if Helper.test? yield(nil) if block_given? - command + return command end @errors = [] diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index dc85b9dc02e..71383e4d05b 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -93,6 +93,24 @@ def shell_provider_id_command(jwt: nil) ].compact.join(' ') end + def altool_upload_command(api_key: nil, platform: "macos") + use_api_key = !api_key.nil? + upload_part = "-f /tmp/my.app.id.itmsp" + escaped_password = password.shellescape + + [ + "xcrun altool", + "--upload-app", + ("-u #{email.shellescape}" unless use_api_key), + ("-p #{escaped_password}" unless use_api_key), + ("--apiKey #{api_key[:key_id]}" if use_api_key), + ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), + ("-t #{platform}"), + upload_part, + "-k 100000" + ].compact.join(' ') + end + def java_upload_command(provider_short_name: nil, transporter: nil, jwt: nil, classpath: true, use_asset_path: false) upload_part = use_asset_path ? "-assetFile /tmp/#{random_uuid}.ipa" : "-f /tmp/my.app.id.itmsp" @@ -1107,6 +1125,61 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) end end + describe "with Xcode 14.x installed" do + before(:each) do + allow(FastlaneCore::Helper).to receive(:xcode_version).and_return('14.0') + allow(FastlaneCore::Helper).to receive(:mac?).and_return(true) + allow(FastlaneCore::Helper).to receive(:windows?).and_return(false) + end + + describe "with username and password" do + describe "with default itms_path" do + before(:each) do + allow(FastlaneCore::Helper).to receive(:itms_path).and_return(nil) + stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => nil }) + end + describe "upload command generation" do + it 'generates a call to altool' do + transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true) + expect(transporter.upload('my.app.id', '/tmp', package_path: '/tmp/my.app.id.itmsp', platform: "osx")).to eq(altool_upload_command) + end + end + end + + describe "with user defined itms_path" do + before(:each) do + allow(FastlaneCore::Helper).to receive(:itms_path).and_return('/tmp') + stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => '/tmp' }) + end + describe "upload command generation" do + it 'generates a call to altool' do + transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true) + expect(transporter.upload('my.app.id', '/tmp', platform: "osx")).to eq(java_upload_command(provider_short_name: 'abcd123', classpath: false)) + end + end + end + + after(:each) { ENV.delete("FASTLANE_ITUNES_TRANSPORTER_PATH") } + end + + describe "with api_key" do + describe "with default itms_path" do + before(:each) do + allow(FastlaneCore::Helper).to receive(:itms_path).and_return(nil) + stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => nil }) + end + describe "upload command generation" do + api_key = { key_id: "TESTAPIK2HW", issuer_id: "11223344-1122-aabb-aabb-uuvvwwxxyyzz" } + it 'generates a call to altool' do + transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true, api_key: api_key) + expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_upload_command(api_key: api_key))}") + expect(transporter.upload('my.app.id', '/tmp', platform: "osx")).to match(expected) + end + end + end + end + end + describe "with `FASTLANE_ITUNES_TRANSPORTER_USE_SHELL_SCRIPT` set" do before(:each) do ENV["FASTLANE_ITUNES_TRANSPORTER_USE_SHELL_SCRIPT"] = "1" From 16249e7eed30f9764ff2982aa97d42bf99d81ac5 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 05:19:10 +0900 Subject: [PATCH 40/69] fix test format --- fastlane_core/spec/itunes_transporter_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index 71383e4d05b..155cd45baa6 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -5,6 +5,7 @@ let(:password) { "!> p@$s_-+=w'o%rd\"&#*<" } let(:email) { 'fabric.devtools@gmail.com' } let(:jwt) { '409jjl43j90ghjqoineio49024' } + let(:api_key) { { key_id: "TESTAPIK2HW", issuer_id: "11223344-1122-aabb-aabb-uuvvwwxxyyzz" } } describe FastlaneCore::ItunesTransporter do let(:random_uuid) { '2a912f38-5dbc-4fc3-a5b3-1bf184b2b021' } @@ -1152,7 +1153,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => '/tmp' }) end describe "upload command generation" do - it 'generates a call to altool' do + it 'generates a call to xcrun iTMSTransporter instead altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true) expect(transporter.upload('my.app.id', '/tmp', platform: "osx")).to eq(java_upload_command(provider_short_name: 'abcd123', classpath: false)) end @@ -1168,8 +1169,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) allow(FastlaneCore::Helper).to receive(:itms_path).and_return(nil) stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => nil }) end - describe "upload command generation" do - api_key = { key_id: "TESTAPIK2HW", issuer_id: "11223344-1122-aabb-aabb-uuvvwwxxyyzz" } + describe "upload command generation" do it 'generates a call to altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true, api_key: api_key) expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_upload_command(api_key: api_key))}") From 8ab40fad7dc6ec73c597dc7e54b83c8dd72337c0 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 05:20:34 +0900 Subject: [PATCH 41/69] remove space --- fastlane_core/spec/itunes_transporter_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index 155cd45baa6..82151c639c6 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -1172,7 +1172,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) describe "upload command generation" do it 'generates a call to altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true, api_key: api_key) - expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_upload_command(api_key: api_key))}") + expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_upload_command(api_key: api_key))}") expect(transporter.upload('my.app.id', '/tmp', platform: "osx")).to match(expected) end end From 22cfcec0f28ac400272b27ccc27de7cbf7ebcc99 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 11:12:26 +0900 Subject: [PATCH 42/69] support api json path --- deliver/lib/deliver/runner.rb | 10 +++++++--- pilot/lib/pilot/build_manager.rb | 10 +++++++--- spaceship/lib/spaceship/connect_api/token.rb | 7 +++++-- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index c91c2507337..a0d8e71ec28 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -273,14 +273,18 @@ def submit_for_review def transporter_for_selected_team(upload: false) # Use JWT auth api_token = Spaceship::ConnectAPI.token + api_key = nil + api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if options[:api_key].nil? && !options[:api_key_path].nil? + api_key = options[:api_key] unless options[:api_key].nil? + unless api_token.nil? api_token.refresh! if api_token.expired? - return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: upload, api_key: options[:api_key]) + return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: upload, api_key: api_key) end tunes_client = Spaceship::ConnectAPI.client.tunes_client - generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: upload, api_key: options[:api_key]) + generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: upload, api_key: api_key) return generic_transporter unless options[:itc_provider].nil? && tunes_client.teams.count > 1 begin @@ -288,7 +292,7 @@ def transporter_for_selected_team(upload: false) name = team['name'] provider_id = generic_transporter.provider_ids[name] UI.verbose("Inferred provider id #{provider_id} for team #{name}.") - return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: upload, api_key: options[:api_key]) + return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: upload, api_key: api_key) rescue => ex UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.") return generic_transporter diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index d3d38c169cb..6282a75ddae 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -389,15 +389,19 @@ def expire_previous_builds(build) def transporter_for_selected_team(options) # Use JWT auth api_token = Spaceship::ConnectAPI.token + api_key = nil + api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if options[:api_key].nil? && !options[:api_key_path].nil? + api_key = options[:api_key] unless options[:api_key].nil? + unless api_token.nil? api_token.refresh! if api_token.expired? - return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: true, api_key: options[:api_key]) + return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, upload: true, api_key: api_key) end # Otherwise use username and password tunes_client = Spaceship::ConnectAPI.client ? Spaceship::ConnectAPI.client.tunes_client : nil - generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: true, api_key: options[:api_key]) + generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider], upload: true, api_key: api_key) return generic_transporter if options[:itc_provider] || tunes_client.nil? return generic_transporter unless tunes_client.teams.count > 1 @@ -406,7 +410,7 @@ def transporter_for_selected_team(options) name = team['name'] provider_id = generic_transporter.provider_ids[name] UI.verbose("Inferred provider id #{provider_id} for team #{name}.") - return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: true, api_key: options[:api_key]) + return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id, upload: true, api_key: api_key) rescue => ex STDERR.puts(ex.to_s) UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.") diff --git a/spaceship/lib/spaceship/connect_api/token.rb b/spaceship/lib/spaceship/connect_api/token.rb index ce3e922697d..fd0e495a06a 100644 --- a/spaceship/lib/spaceship/connect_api/token.rb +++ b/spaceship/lib/spaceship/connect_api/token.rb @@ -22,6 +22,7 @@ class Token attr_reader :expiration attr_reader :key_raw + attr_reader :is_key_content_base64 # Temporary attribute not needed to create the JWT text # There is no way to determine if the team associated with this @@ -71,17 +72,19 @@ def self.create(key_id: nil, issuer_id: nil, filepath: nil, key: nil, is_key_con key: OpenSSL::PKey::EC.new(key), key_raw: key, duration: duration, - in_house: in_house + in_house: in_house, + is_key_content_base64: is_key_content_base64 ) end - def initialize(key_id: nil, issuer_id: nil, key: nil, key_raw: nil, duration: nil, in_house: nil) + def initialize(key_id: nil, issuer_id: nil, key: nil, key_raw: nil, duration: nil, in_house: nil, is_key_content_base64: nil) @key_id = key_id @key = key @key_raw = key_raw @issuer_id = issuer_id @duration = duration @in_house = in_house + @is_key_content_base64 = is_key_content_base64 @duration ||= DEFAULT_TOKEN_DURATION @duration = @duration.to_i if @duration From 3fc11fa612b208eddb8a850b8ba172522d7bf342 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 11:36:32 +0900 Subject: [PATCH 43/69] add some comment and fix code style --- deliver/lib/deliver/runner.rb | 6 +++--- pilot/lib/pilot/build_manager.rb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index a0d8e71ec28..39c00521329 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -273,9 +273,9 @@ def submit_for_review def transporter_for_selected_team(upload: false) # Use JWT auth api_token = Spaceship::ConnectAPI.token - api_key = nil - api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if options[:api_key].nil? && !options[:api_key_path].nil? - api_key = options[:api_key] unless options[:api_key].nil? + api_key = options[:api_key] + # Load api key info if user set api_key_path, not api_key + api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if api_key.nil? && !options[:api_key_path].nil? unless api_token.nil? api_token.refresh! if api_token.expired? diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index 6282a75ddae..cb655616343 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -389,9 +389,9 @@ def expire_previous_builds(build) def transporter_for_selected_team(options) # Use JWT auth api_token = Spaceship::ConnectAPI.token - api_key = nil - api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if options[:api_key].nil? && !options[:api_key_path].nil? - api_key = options[:api_key] unless options[:api_key].nil? + api_key = options[:api_key] + # Load api key info if user set api_key_path, not api_key + api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if api_key.nil? && !options[:api_key_path].nil? unless api_token.nil? api_token.refresh! if api_token.expired? From 980f189cd87f55e4026ac87d08a6b41e90ddd04a Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 11:50:02 +0900 Subject: [PATCH 44/69] add comment about error info --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index d91712ea0b8..f93f8bcf9d8 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -220,7 +220,17 @@ def execute(command, hide_output) # Print the last lines that appear after the last error from the logs # If error text is not detected, it will be 20 lines # This is key for non-verbose mode + + # The format of altool's result with error is like below + # > *** Error: Error uploading '...'. + # > *** Error: ... + # > { + # > NSLocalizedDescription = "...", + # > ... + # > } + # So this line tries to find the line which has "*** Error:" prefix from bottom of log error_line_index = @all_lines.rindex { |line| ERROR_REGEX.match?(line) } + @all_lines[(error_line_index || -20)..-1].each do |line| UI.important("[altool] #{line}") end From 669bebc6fbcf958d2dfe5ac0f793a673f7c857bd Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Tue, 13 Sep 2022 17:54:50 +0900 Subject: [PATCH 45/69] compose return expression in one line Co-authored-by: Kohki Miki --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index f93f8bcf9d8..690e4d96949 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -261,9 +261,7 @@ def build_upload_command(username, password, source = "/tmp", provider_short_nam def additional_upload_parameters env_deliver_additional_params = ENV["DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS"] - if env_deliver_additional_params.to_s.strip.empty? - return nil - end + return nil if env_deliver_additional_params.to_s.strip.empty? env_deliver_additional_params.to_s.strip end From 98e1a8890ceb7cf01f189292195cb525a17e76c7 Mon Sep 17 00:00:00 2001 From: "freddi(Yuki Aki)" Date: Tue, 13 Sep 2022 17:58:34 +0900 Subject: [PATCH 46/69] fix to use checking raise_error Co-authored-by: Kohki Miki --- fastlane_core/spec/helper_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/spec/helper_spec.rb b/fastlane_core/spec/helper_spec.rb index 31f80be8ef6..fdd185eec7d 100644 --- a/fastlane_core/spec/helper_spec.rb +++ b/fastlane_core/spec/helper_spec.rb @@ -183,7 +183,7 @@ if FastlaneCore::Helper.xcode_at_least?("14") expect(FastlaneCore::UI).to receive(:user_error!).with(/Could not find transporter/) - FastlaneCore::Helper.itms_path + expect { FastlaneCore::Helper.itms_path }.not_to raise_error else expect(FastlaneCore::Helper.itms_path).to match(/itms/) end From 355cc9d6dc630337f1a94c8a81b75ee2d01a88b8 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 17:59:12 +0900 Subject: [PATCH 47/69] use context for matching rpec --- fastlane_core/spec/itunes_transporter_spec.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index 82151c639c6..bbe36b1a940 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -1126,20 +1126,20 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) end end - describe "with Xcode 14.x installed" do + context "with Xcode 14.x installed" do before(:each) do allow(FastlaneCore::Helper).to receive(:xcode_version).and_return('14.0') allow(FastlaneCore::Helper).to receive(:mac?).and_return(true) allow(FastlaneCore::Helper).to receive(:windows?).and_return(false) end - describe "with username and password" do - describe "with default itms_path" do + context "with username and password" do + context "with default itms_path" do before(:each) do allow(FastlaneCore::Helper).to receive(:itms_path).and_return(nil) stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => nil }) end - describe "upload command generation" do + context "upload command generation" do it 'generates a call to altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true) expect(transporter.upload('my.app.id', '/tmp', package_path: '/tmp/my.app.id.itmsp', platform: "osx")).to eq(altool_upload_command) @@ -1147,12 +1147,12 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) end end - describe "with user defined itms_path" do + context "with user defined itms_path" do before(:each) do allow(FastlaneCore::Helper).to receive(:itms_path).and_return('/tmp') stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => '/tmp' }) end - describe "upload command generation" do + context "upload command generation" do it 'generates a call to xcrun iTMSTransporter instead altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true) expect(transporter.upload('my.app.id', '/tmp', platform: "osx")).to eq(java_upload_command(provider_short_name: 'abcd123', classpath: false)) @@ -1163,13 +1163,13 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) after(:each) { ENV.delete("FASTLANE_ITUNES_TRANSPORTER_PATH") } end - describe "with api_key" do - describe "with default itms_path" do + context "with api_key" do + context "with default itms_path" do before(:each) do allow(FastlaneCore::Helper).to receive(:itms_path).and_return(nil) stub_const('ENV', { 'FASTLANE_ITUNES_TRANSPORTER_PATH' => nil }) end - describe "upload command generation" do + context "upload command generation" do it 'generates a call to altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true, api_key: api_key) expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_upload_command(api_key: api_key))}") From 0f6bfcbc90e24df12be7c056153e7e5a1996c004 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 18:11:10 +0900 Subject: [PATCH 48/69] fix code's readability --- deliver/lib/deliver/runner.rb | 11 ++++++++--- pilot/lib/pilot/build_manager.rb | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 39c00521329..87b23cad39f 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -273,9 +273,14 @@ def submit_for_review def transporter_for_selected_team(upload: false) # Use JWT auth api_token = Spaceship::ConnectAPI.token - api_key = options[:api_key] - # Load api key info if user set api_key_path, not api_key - api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if api_key.nil? && !options[:api_key_path].nil? + api_key = if options[:api_key].nil? && !options[:api_key_path].nil? + # Load api key info if user set api_key_path, not api_key + { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } + elsif !options[:api_key].nil? + options[:api_key] + else + nil + end unless api_token.nil? api_token.refresh! if api_token.expired? diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index cb655616343..2e4f6f80125 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -389,9 +389,14 @@ def expire_previous_builds(build) def transporter_for_selected_team(options) # Use JWT auth api_token = Spaceship::ConnectAPI.token - api_key = options[:api_key] - # Load api key info if user set api_key_path, not api_key - api_key = { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } if api_key.nil? && !options[:api_key_path].nil? + api_key = if options[:api_key].nil? && !options[:api_key_path].nil? + # Load api key info if user set api_key_path, not api_key + { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } + elsif !options[:api_key].nil? + options[:api_key] + else + nil + end unless api_token.nil? api_token.refresh! if api_token.expired? From f4cd02047284bcd0cf124b8c7552fd917341eabb Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 18:16:34 +0900 Subject: [PATCH 49/69] fix lint --- deliver/lib/deliver/runner.rb | 14 +++++++------- pilot/lib/pilot/build_manager.rb | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 87b23cad39f..8ce0acb4d46 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -274,13 +274,13 @@ def transporter_for_selected_team(upload: false) # Use JWT auth api_token = Spaceship::ConnectAPI.token api_key = if options[:api_key].nil? && !options[:api_key_path].nil? - # Load api key info if user set api_key_path, not api_key - { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - elsif !options[:api_key].nil? - options[:api_key] - else - nil - end + # Load api key info if user set api_key_path, not api_key + { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } + elsif !options[:api_key].nil? + options[:api_key] + else + nil + end unless api_token.nil? api_token.refresh! if api_token.expired? diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index 2e4f6f80125..e214338287b 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -390,13 +390,13 @@ def transporter_for_selected_team(options) # Use JWT auth api_token = Spaceship::ConnectAPI.token api_key = if options[:api_key].nil? && !options[:api_key_path].nil? - # Load api key info if user set api_key_path, not api_key - { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - elsif !options[:api_key].nil? - options[:api_key] - else - nil - end + # Load api key info if user set api_key_path, not api_key + { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } + elsif !options[:api_key].nil? + options[:api_key] + else + nil + end unless api_token.nil? api_token.refresh! if api_token.expired? From 95e7cb89d2bc502da1c9d93f92f403150a298c01 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 18:35:43 +0900 Subject: [PATCH 50/69] fix lint --- deliver/lib/deliver/runner.rb | 14 +++++++------- pilot/lib/pilot/build_manager.rb | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 8ce0acb4d46..7b6bf8419b6 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -274,13 +274,13 @@ def transporter_for_selected_team(upload: false) # Use JWT auth api_token = Spaceship::ConnectAPI.token api_key = if options[:api_key].nil? && !options[:api_key_path].nil? - # Load api key info if user set api_key_path, not api_key - { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - elsif !options[:api_key].nil? - options[:api_key] - else - nil - end + # Load api key info if user set api_key_path, not api_key + { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } + elsif !options[:api_key].nil? + options[:api_key] + else + nil + end unless api_token.nil? api_token.refresh! if api_token.expired? diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index e214338287b..9bbf87f3b1a 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -390,13 +390,13 @@ def transporter_for_selected_team(options) # Use JWT auth api_token = Spaceship::ConnectAPI.token api_key = if options[:api_key].nil? && !options[:api_key_path].nil? - # Load api key info if user set api_key_path, not api_key - { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - elsif !options[:api_key].nil? - options[:api_key] - else - nil - end + # Load api key info if user set api_key_path, not api_key + { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } + elsif !options[:api_key].nil? + options[:api_key] + else + nil + end unless api_token.nil? api_token.refresh! if api_token.expired? From 38f23ee3775e0fdf62c5aee013c6bc9842223ba9 Mon Sep 17 00:00:00 2001 From: freddi Date: Tue, 13 Sep 2022 23:08:02 +0900 Subject: [PATCH 51/69] fix lint --- deliver/lib/deliver/runner.rb | 4 +--- pilot/lib/pilot/build_manager.rb | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 7b6bf8419b6..e78b9887b1a 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -276,10 +276,8 @@ def transporter_for_selected_team(upload: false) api_key = if options[:api_key].nil? && !options[:api_key_path].nil? # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - elsif !options[:api_key].nil? - options[:api_key] else - nil + options[:api_key] end unless api_token.nil? diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index 9bbf87f3b1a..51c85c188e4 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -392,10 +392,8 @@ def transporter_for_selected_team(options) api_key = if options[:api_key].nil? && !options[:api_key_path].nil? # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - elsif !options[:api_key].nil? - options[:api_key] else - nil + options[:api_key] end unless api_token.nil? From 30839b923e855b01d3c6d014f967d15652a78676 Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 21:02:04 +0900 Subject: [PATCH 52/69] fix ids provider problem --- .../lib/fastlane_core/itunes_transporter.rb | 90 +++++++++++++++---- fastlane_core/spec/itunes_transporter_spec.rb | 7 +- 2 files changed, 76 insertions(+), 21 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 690e4d96949..0fa7b3b896f 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -252,6 +252,7 @@ def build_upload_command(username, password, source = "/tmp", provider_short_nam ("-p #{password.shellescape}" unless use_api_key), ("--apiKey #{api_key[:key_id]}" if use_api_key), ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), + ("--asc-provider #{provider_short_name}" if !use_api_key && !provider_short_name.to_s.empty?), platform_option(platform), file_upload_option(source), additional_upload_parameters, @@ -259,6 +260,19 @@ def build_upload_command(username, password, source = "/tmp", provider_short_nam ].compact.join(' ') end + def build_provider_ids_command(username, password, jwt = nil, api_key = nil) + use_api_key = !api_key.nil? + [ + ("API_PRIVATE_KEYS_DIR=#{api_key[:key_dir]}" if use_api_key), + "xcrun altool", + "--list-providers", + ("-u #{username.shellescape}" unless use_api_key), + ("-p #{password.shellescape}" unless use_api_key), + ("--apiKey #{api_key[:key_id]}" if use_api_key), + ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key) + ].compact.join(' ') + end + def additional_upload_parameters env_deliver_additional_params = ENV["DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS"] return nil if env_deliver_additional_params.to_s.strip.empty? @@ -333,7 +347,7 @@ def build_download_command(username, password, apple_id, destination = "/tmp", p ].compact.join(' ') end - def build_provider_ids_command(username, password, jwt = nil) + def build_provider_ids_command(username, password, jwt = nil, api_key = nil) use_jwt = !jwt.to_s.empty? [ '"' + Helper.transporter_path + '"', @@ -513,7 +527,7 @@ def build_download_command(username, password, apple_id, destination = "/tmp", p end end - def build_provider_ids_command(username, password, jwt = nil) + def build_provider_ids_command(username, password, jwt = nil, api_key = nil) use_jwt = !jwt.to_s.empty? if !Helper.user_defined_itms_path? && Helper.mac? && Helper.xcode_at_least?(11) [ @@ -572,8 +586,12 @@ def execute(command, hide_output) end class ItunesTransporter - # Matches a line in the provider table: "12 Initech Systems Inc LG89CQY559" - PROVIDER_REGEX = /^\d+\s{2,}.+\s{2,}[^\s]+$/ + # Matches a line in the iTMSTransporter provider table: "12 Initech Systems Inc LG89CQY559" + ITMS_PROVIDER_REGEX = /^\d+\s{2,}.+\s{2,}[^\s]+$/ + # Matches a line in the altool provider talble's separator + # ------------------- ----------------- ------------------------------------ ---------- + # Initech Systems Inc LG89CQY559 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LG89CQY559 + ALTOOL_SEPARATOR_PROVIDER_REGEX = /^\-{1,}\s{1}\-{1,}\s{1}\-{1,}\s{1}\-{1,}\s+$/ TWO_STEP_HOST_PREFIX = "deliver.appspecific" # This will be called from the Deliverfile, and disables the logging of the transporter output @@ -611,10 +629,12 @@ def initialize(user = nil, password = nil, use_shell_script = false, provider_sh @jwt = jwt @api_key = api_key + @is_altool = false if should_use_altool?(upload, use_shell_script) UI.verbose("Using altool as transporter.") @transporter_executor = AltoolTransporterExecutor.new + @is_altool = true else UI.verbose("Using iTMSTransporter as transporter.") @transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new @@ -703,15 +723,7 @@ def upload(app_id = nil, dir = nil, package_path: nil, asset_path: nil, platform api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_dir: "YourTmpP8KeyDir" } : nil api_key = nil - if use_api_key - api_key = @api_key.clone - api_key[:key_dir] = Dir.mktmpdir("deliver-") - # Specified p8 needs to be generated to call altool - File.open(File.join(api_key[:key_dir], "AuthKey_#{api_key[:key_id]}.p8"), "wb") do |p8| - key_content = api_key[:is_key_content_base64] ? Base64.decode64(api_key[:key]) : @api_key[:key] - p8.write(key_content) - end - end + api_key = api_key_with_p8_file_path(@api_key) if use_api_key command = @transporter_executor.build_upload_command(@user, @password, actual_dir, @provider_short_name, @jwt, platform, api_key) UI.verbose(@transporter_executor.build_upload_command(@user, password_placeholder, actual_dir, @provider_short_name, jwt_placeholder, platform, api_key_placeholder)) @@ -786,8 +798,15 @@ def provider_ids password_placeholder = @jwt.nil? ? 'YourPassword' : nil jwt_placeholder = @jwt.nil? ? nil : 'YourJWT' - command = @transporter_executor.build_provider_ids_command(@user, @password, @jwt) - UI.verbose(@transporter_executor.build_provider_ids_command(@user, password_placeholder, jwt_placeholder)) + # Handle AppStore Connect API + use_api_key = !@api_key.nil? + api_key_placeholder = use_api_key ? { key_id: "YourKeyID", issuer_id: "YourIssuerID", key_dir: "YourTmpP8KeyDir" } : nil + + api_key = nil + api_key = api_key_with_p8_file_path(@api_key) if use_api_key + + command = @transporter_executor.build_provider_ids_command(@user, @password, @jwt, api_key) + UI.verbose(@transporter_executor.build_provider_ids_command(@user, password_placeholder, jwt_placeholder, api_key_placeholder)) lines = [] begin @@ -796,15 +815,30 @@ def provider_ids rescue TransporterRequiresApplicationSpecificPasswordError => ex handle_two_step_failure(ex) return provider_ids + ensure + if use_api_key + FileUtils.rm_rf(api_key[:key_dir]) unless api_key.nil? + end end - lines.map { |line| provider_pair(line) }.compact.to_h + @is_altool ? parse_altool_provider_info(lines) : parse_itsm_provider_info(lines) end private TWO_FACTOR_ENV_VARIABLE = "FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD" + def api_key_with_p8_file_path(original_api_key) + api_key = original_api_key.clone + api_key[:key_dir] = Dir.mktmpdir("deliver-") + # Specified p8 needs to be generated to call altool + File.open(File.join(api_key[:key_dir], "AuthKey_#{api_key[:key_id]}.p8"), "wb") do |p8| + key_content = api_key[:is_key_content_base64] ? Base64.decode64(api_key[:key]) : api_key[:key] + p8.write(key_content) + end + api_key + end + # Returns whether altool should be used or ItunesTransporter should be used def should_use_altool?(upload, use_shell_script) # Xcode 14 no longer supports iTMSTransporter. Use altool instead @@ -869,10 +903,30 @@ def handle_error(password) @transporter_executor.handle_error(password) end - def provider_pair(line) + def itms_provider_pair(line) line = line.strip - return nil unless line =~ PROVIDER_REGEX + return nil unless line =~ ITMS_PROVIDER_REGEX line.split(/\s{2,}/).drop(1) end + + def parse_itsm_provider_info(lines) + lines.map { |line| itms_provider_pair(line) }.compact.to_h + end + + def parse_altool_provider_info(lines) + provider_info = {} + separator_index = lines.index { |line| line =~ ALTOOL_SEPARATOR_PROVIDER_REGEX } + return provider_info unless separator_index + provider_name_index = lines[separator_index].index(/\s/, 0) + short_name_index = lines[separator_index].index(/\s/, provider_name_index + 1) + + lines[separator_index + 1..-1].each do |line| + provider_name = line[0, provider_name_index] + short_name = line[provider_name_index + 1, short_name_index - provider_name_index] + break if provider_name.nil? || short_name.nil? + provider_info[provider_name.strip] = short_name.strip + end + provider_info + end end end diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index bbe36b1a940..a12751acc7a 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -94,7 +94,7 @@ def shell_provider_id_command(jwt: nil) ].compact.join(' ') end - def altool_upload_command(api_key: nil, platform: "macos") + def altool_upload_command(api_key: nil, platform: "macos", provider_short_name: "") use_api_key = !api_key.nil? upload_part = "-f /tmp/my.app.id.itmsp" escaped_password = password.shellescape @@ -106,6 +106,7 @@ def altool_upload_command(api_key: nil, platform: "macos") ("-p #{escaped_password}" unless use_api_key), ("--apiKey #{api_key[:key_id]}" if use_api_key), ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), + ("--asc-provider #{provider_short_name}" if !use_api_key && !provider_short_name.to_s.empty?), ("-t #{platform}"), upload_part, "-k 100000" @@ -1142,7 +1143,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) context "upload command generation" do it 'generates a call to altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true) - expect(transporter.upload('my.app.id', '/tmp', package_path: '/tmp/my.app.id.itmsp', platform: "osx")).to eq(altool_upload_command) + expect(transporter.upload('my.app.id', '/tmp', package_path: '/tmp/my.app.id.itmsp', platform: "osx")).to eq(altool_upload_command(provider_short_name: 'abcd123')) end end end @@ -1172,7 +1173,7 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) context "upload command generation" do it 'generates a call to altool' do transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true, api_key: api_key) - expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_upload_command(api_key: api_key))}") + expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_upload_command(api_key: api_key, provider_short_name: 'abcd123'))}") expect(transporter.upload('my.app.id', '/tmp', platform: "osx")).to match(expected) end end From a2ea2fbd6fafce6b38af1dc35b68df63b50fdc1d Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 21:10:48 +0900 Subject: [PATCH 53/69] add comments --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 0fa7b3b896f..54ab571142c 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -828,6 +828,7 @@ def provider_ids TWO_FACTOR_ENV_VARIABLE = "FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD" + # Create .p8 file from api_key and provide api key info which contains .p8 file path def api_key_with_p8_file_path(original_api_key) api_key = original_api_key.clone api_key[:key_dir] = Dir.mktmpdir("deliver-") @@ -914,12 +915,17 @@ def parse_itsm_provider_info(lines) end def parse_altool_provider_info(lines) + # This tries parsing the provider id from altool output to detect provider list provider_info = {} separator_index = lines.index { |line| line =~ ALTOOL_SEPARATOR_PROVIDER_REGEX } return provider_info unless separator_index + # The actual length of provider and its short name can be detect by the separator's ('----') length + # First separator provider_name_index = lines[separator_index].index(/\s/, 0) + # Second separator short_name_index = lines[separator_index].index(/\s/, provider_name_index + 1) + # Check lines after separators lines[separator_index + 1..-1].each do |line| provider_name = line[0, provider_name_index] short_name = line[provider_name_index + 1, short_name_index - provider_name_index] From 874320cf5eeeb041312ffc5072508dbdfea3b64e Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 21:33:17 +0900 Subject: [PATCH 54/69] add test for provider ids --- fastlane_core/spec/itunes_transporter_spec.rb | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index a12751acc7a..fe0fba8d854 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -113,6 +113,20 @@ def altool_upload_command(api_key: nil, platform: "macos", provider_short_name: ].compact.join(' ') end + def altool_provider_id_command(api_key: nil) + use_api_key = !api_key.nil? + escaped_password = password.shellescape + + [ + "xcrun altool", + "--list-providers", + ("-u #{email.shellescape}" unless use_api_key), + ("-p #{escaped_password}" unless use_api_key), + ("--apiKey #{api_key[:key_id]}" if use_api_key), + ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key) + ].compact.join(' ') + end + def java_upload_command(provider_short_name: nil, transporter: nil, jwt: nil, classpath: true, use_asset_path: false) upload_part = use_asset_path ? "-assetFile /tmp/#{random_uuid}.ipa" : "-f /tmp/my.app.id.itmsp" @@ -1146,6 +1160,13 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) expect(transporter.upload('my.app.id', '/tmp', package_path: '/tmp/my.app.id.itmsp', platform: "osx")).to eq(altool_upload_command(provider_short_name: 'abcd123')) end end + + context "provider IDs command generation" do + it 'generates a call to altool' do + transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true) + expect(transporter.provider_ids).to eq(altool_provider_id_command) + end + end end context "with user defined itms_path" do @@ -1177,6 +1198,14 @@ def xcrun_download_command(provider_short_name = nil, jwt: nil) expect(transporter.upload('my.app.id', '/tmp', platform: "osx")).to match(expected) end end + + context "provider IDs command generation" do + it 'generates a call to altool' do + transporter = FastlaneCore::ItunesTransporter.new(email, password, false, 'abcd123', upload: true, api_key: api_key) + expected = Regexp.new("API_PRIVATE_KEYS_DIR=#{Regexp.escape(Dir.tmpdir)}.*\s#{Regexp.escape(altool_provider_id_command(api_key: api_key))}") + expect(transporter.provider_ids).to match(expected) + end + end end end end From ab02d6dacb2c2a2b9d8ca82a5dd991a4315fbcb2 Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 21:54:52 +0900 Subject: [PATCH 55/69] fix api key condition to make code more readable --- deliver/lib/deliver/runner.rb | 2 +- pilot/lib/pilot/build_manager.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index e78b9887b1a..0a0f26fbd9c 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -273,7 +273,7 @@ def submit_for_review def transporter_for_selected_team(upload: false) # Use JWT auth api_token = Spaceship::ConnectAPI.token - api_key = if options[:api_key].nil? && !options[:api_key_path].nil? + api_key = if options[:api_key].nil? && !api_token.nil? # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } else diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index 51c85c188e4..33b654e3bbb 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -389,7 +389,7 @@ def expire_previous_builds(build) def transporter_for_selected_team(options) # Use JWT auth api_token = Spaceship::ConnectAPI.token - api_key = if options[:api_key].nil? && !options[:api_key_path].nil? + api_key = if options[:api_key].nil? && !api_token.nil? # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } else From 71e57d60cad428d53766a4aac6a9dc4eb2567f39 Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 22:01:43 +0900 Subject: [PATCH 56/69] add more detailed comment --- .../lib/fastlane_core/itunes_transporter.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 54ab571142c..f5f6524cd6f 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -917,17 +917,30 @@ def parse_itsm_provider_info(lines) def parse_altool_provider_info(lines) # This tries parsing the provider id from altool output to detect provider list provider_info = {} + # The actual length of provider and its short name can be detect by the separator's ('----') length + + # Below is example, let's see with it + # ------------------- ----------------- ------------------------------------ ---------- + # Initech Systems Inc LG89CQY559 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LG89CQY559 + + # Detect line of "------------------- ----------------- ------------------------------------ ----------" from output separator_index = lines.index { |line| line =~ ALTOOL_SEPARATOR_PROVIDER_REGEX } return provider_info unless separator_index - # The actual length of provider and its short name can be detect by the separator's ('----') length + # First separator + # ------------------- + # Initech Systems Inc provider_name_index = lines[separator_index].index(/\s/, 0) - # Second separator + # Second separator (e.g. LG89CQY559) + # ----------------- + # LG89CQY559 short_name_index = lines[separator_index].index(/\s/, provider_name_index + 1) # Check lines after separators lines[separator_index + 1..-1].each do |line| + # Get provider name by Index of First separator provider_name = line[0, provider_name_index] + # Get short name by Index of Second separator short_name = line[provider_name_index + 1, short_name_index - provider_name_index] break if provider_name.nil? || short_name.nil? provider_info[provider_name.strip] = short_name.strip From b518207a7ae9e4e2c83701f79e9856e1bb03b559 Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 22:19:26 +0900 Subject: [PATCH 57/69] fix typo --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index f5f6524cd6f..ba18496198a 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -588,7 +588,7 @@ def execute(command, hide_output) class ItunesTransporter # Matches a line in the iTMSTransporter provider table: "12 Initech Systems Inc LG89CQY559" ITMS_PROVIDER_REGEX = /^\d+\s{2,}.+\s{2,}[^\s]+$/ - # Matches a line in the altool provider talble's separator + # Matches a line in the altool provider table's separator # ------------------- ----------------- ------------------------------------ ---------- # Initech Systems Inc LG89CQY559 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LG89CQY559 ALTOOL_SEPARATOR_PROVIDER_REGEX = /^\-{1,}\s{1}\-{1,}\s{1}\-{1,}\s{1}\-{1,}\s+$/ From 8d5bb624867b1c5c502c2ae2874cb1f2b5413f9f Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 22:27:23 +0900 Subject: [PATCH 58/69] improve specifying substring --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index ba18496198a..d404d11aa9f 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -939,9 +939,9 @@ def parse_altool_provider_info(lines) # Check lines after separators lines[separator_index + 1..-1].each do |line| # Get provider name by Index of First separator - provider_name = line[0, provider_name_index] + provider_name = line[0..provider_name_index] # Get short name by Index of Second separator - short_name = line[provider_name_index + 1, short_name_index - provider_name_index] + short_name = line[provider_name_index + 1..short_name_index - 1] break if provider_name.nil? || short_name.nil? provider_info[provider_name.strip] = short_name.strip end From 5beca1e2045818542a2fd34d7c6f486bebf8d847 Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 22:29:35 +0900 Subject: [PATCH 59/69] fix index --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index d404d11aa9f..5037699dc5c 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -939,7 +939,7 @@ def parse_altool_provider_info(lines) # Check lines after separators lines[separator_index + 1..-1].each do |line| # Get provider name by Index of First separator - provider_name = line[0..provider_name_index] + provider_name = line[0..provider_name_index - 1] # Get short name by Index of Second separator short_name = line[provider_name_index + 1..short_name_index - 1] break if provider_name.nil? || short_name.nil? From 4f4d3eefded04f86147bfa044a9b62fd542d7420 Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 23:24:05 +0900 Subject: [PATCH 60/69] fix altool providers output to parse json --- .../lib/fastlane_core/itunes_transporter.rb | 40 ++++--------------- fastlane_core/spec/itunes_transporter_spec.rb | 3 +- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 5037699dc5c..ae3120440f4 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -269,7 +269,8 @@ def build_provider_ids_command(username, password, jwt = nil, api_key = nil) ("-u #{username.shellescape}" unless use_api_key), ("-p #{password.shellescape}" unless use_api_key), ("--apiKey #{api_key[:key_id]}" if use_api_key), - ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key) + ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), + "--output-format json" ].compact.join(' ') end @@ -588,10 +589,6 @@ def execute(command, hide_output) class ItunesTransporter # Matches a line in the iTMSTransporter provider table: "12 Initech Systems Inc LG89CQY559" ITMS_PROVIDER_REGEX = /^\d+\s{2,}.+\s{2,}[^\s]+$/ - # Matches a line in the altool provider table's separator - # ------------------- ----------------- ------------------------------------ ---------- - # Initech Systems Inc LG89CQY559 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LG89CQY559 - ALTOOL_SEPARATOR_PROVIDER_REGEX = /^\-{1,}\s{1}\-{1,}\s{1}\-{1,}\s{1}\-{1,}\s+$/ TWO_STEP_HOST_PREFIX = "deliver.appspecific" # This will be called from the Deliverfile, and disables the logging of the transporter output @@ -917,33 +914,12 @@ def parse_itsm_provider_info(lines) def parse_altool_provider_info(lines) # This tries parsing the provider id from altool output to detect provider list provider_info = {} - # The actual length of provider and its short name can be detect by the separator's ('----') length - - # Below is example, let's see with it - # ------------------- ----------------- ------------------------------------ ---------- - # Initech Systems Inc LG89CQY559 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx LG89CQY559 - - # Detect line of "------------------- ----------------- ------------------------------------ ----------" from output - separator_index = lines.index { |line| line =~ ALTOOL_SEPARATOR_PROVIDER_REGEX } - return provider_info unless separator_index - - # First separator - # ------------------- - # Initech Systems Inc - provider_name_index = lines[separator_index].index(/\s/, 0) - # Second separator (e.g. LG89CQY559) - # ----------------- - # LG89CQY559 - short_name_index = lines[separator_index].index(/\s/, provider_name_index + 1) - - # Check lines after separators - lines[separator_index + 1..-1].each do |line| - # Get provider name by Index of First separator - provider_name = line[0..provider_name_index - 1] - # Get short name by Index of Second separator - short_name = line[provider_name_index + 1..short_name_index - 1] - break if provider_name.nil? || short_name.nil? - provider_info[provider_name.strip] = short_name.strip + json_body = lines[-2] # altool outputs result in second line from last + return provider_info if json_body.nil? + providers = JSON.parse(json_body)["providers"] + return provider_info if providers.nil? + providers.each do |provider| + provider_info[provider["ProviderName"]] = provider["ProviderShortname"] end provider_info end diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index fe0fba8d854..e4b07ab23d6 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -123,7 +123,8 @@ def altool_provider_id_command(api_key: nil) ("-u #{email.shellescape}" unless use_api_key), ("-p #{escaped_password}" unless use_api_key), ("--apiKey #{api_key[:key_id]}" if use_api_key), - ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key) + ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), + "--output-format json" ].compact.join(' ') end From cd2c504c7ba16769aadc2dd9ab465a177c263a9b Mon Sep 17 00:00:00 2001 From: freddi Date: Wed, 14 Sep 2022 23:25:35 +0900 Subject: [PATCH 61/69] fix code format --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 2 +- fastlane_core/spec/itunes_transporter_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index ae3120440f4..85078e0af15 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -252,7 +252,7 @@ def build_upload_command(username, password, source = "/tmp", provider_short_nam ("-p #{password.shellescape}" unless use_api_key), ("--apiKey #{api_key[:key_id]}" if use_api_key), ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), - ("--asc-provider #{provider_short_name}" if !use_api_key && !provider_short_name.to_s.empty?), + ("--asc-provider #{provider_short_name}" unless use_api_key || provider_short_name.to_s.empty?), platform_option(platform), file_upload_option(source), additional_upload_parameters, diff --git a/fastlane_core/spec/itunes_transporter_spec.rb b/fastlane_core/spec/itunes_transporter_spec.rb index e4b07ab23d6..133724461d5 100644 --- a/fastlane_core/spec/itunes_transporter_spec.rb +++ b/fastlane_core/spec/itunes_transporter_spec.rb @@ -106,7 +106,7 @@ def altool_upload_command(api_key: nil, platform: "macos", provider_short_name: ("-p #{escaped_password}" unless use_api_key), ("--apiKey #{api_key[:key_id]}" if use_api_key), ("--apiIssuer #{api_key[:issuer_id]}" if use_api_key), - ("--asc-provider #{provider_short_name}" if !use_api_key && !provider_short_name.to_s.empty?), + ("--asc-provider #{provider_short_name}" unless use_api_key || provider_short_name.to_s.empty?), ("-t #{platform}"), upload_part, "-k 100000" From 4b93a81e8b1f616bbddf349a3b59052730664128 Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 06:50:22 +0900 Subject: [PATCH 62/69] fix hash problem if user pass key via environment variable --- deliver/lib/deliver/runner.rb | 2 +- pilot/lib/pilot/build_manager.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index 0a0f26fbd9c..ce0cc564337 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -277,7 +277,7 @@ def transporter_for_selected_team(upload: false) # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } else - options[:api_key] + options[:api_key].transform_keys!(&:to_sym) end unless api_token.nil? diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index 33b654e3bbb..443610d6473 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -393,7 +393,7 @@ def transporter_for_selected_team(options) # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } else - options[:api_key] + options[:api_key].transform_keys!(&:to_sym) end unless api_token.nil? From 18f460f099fcaa97028a1d1a871b562d11ce0e39 Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 06:53:11 +0900 Subject: [PATCH 63/69] remove unnecessary ! --- deliver/lib/deliver/runner.rb | 2 +- pilot/lib/pilot/build_manager.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index ce0cc564337..d6289f3bb9c 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -277,7 +277,7 @@ def transporter_for_selected_team(upload: false) # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } else - options[:api_key].transform_keys!(&:to_sym) + options[:api_key].transform_keys(&:to_sym) end unless api_token.nil? diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index 443610d6473..bb9796da754 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -393,7 +393,7 @@ def transporter_for_selected_team(options) # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } else - options[:api_key].transform_keys!(&:to_sym) + options[:api_key].transform_keys(&:to_sym) end unless api_token.nil? From ac7358d14df4d058d089953adf62b068c3978349 Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 07:05:48 +0900 Subject: [PATCH 64/69] fix null handle --- deliver/lib/deliver/runner.rb | 2 +- pilot/lib/pilot/build_manager.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deliver/lib/deliver/runner.rb b/deliver/lib/deliver/runner.rb index d6289f3bb9c..d4c39bc67dd 100644 --- a/deliver/lib/deliver/runner.rb +++ b/deliver/lib/deliver/runner.rb @@ -276,7 +276,7 @@ def transporter_for_selected_team(upload: false) api_key = if options[:api_key].nil? && !api_token.nil? # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - else + elsif !options[:api_key].nil? options[:api_key].transform_keys(&:to_sym) end diff --git a/pilot/lib/pilot/build_manager.rb b/pilot/lib/pilot/build_manager.rb index bb9796da754..9ee9da0edbd 100644 --- a/pilot/lib/pilot/build_manager.rb +++ b/pilot/lib/pilot/build_manager.rb @@ -392,7 +392,7 @@ def transporter_for_selected_team(options) api_key = if options[:api_key].nil? && !api_token.nil? # Load api key info if user set api_key_path, not api_key { key_id: api_token.key_id, issuer_id: api_token.issuer_id, key: api_token.key_raw, is_key_content_base64: api_token.is_key_content_base64 } - else + elsif !options[:api_key].nil? options[:api_key].transform_keys(&:to_sym) end From 07181a7381727ba4e30347507dfd367b653f97dc Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 08:12:19 +0900 Subject: [PATCH 65/69] dummy commit for test --- match/lib/match/encryption/openssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/match/lib/match/encryption/openssl.rb b/match/lib/match/encryption/openssl.rb index 2c31a94a93b..c5a9d3a2a10 100644 --- a/match/lib/match/encryption/openssl.rb +++ b/match/lib/match/encryption/openssl.rb @@ -50,7 +50,7 @@ def decrypt_files rescue => ex UI.verbose(ex.to_s) UI.error("Couldn't decrypt the repo, please make sure you enter the right password!") - UI.user_error!("Invalid password passed via 'MATCH_PASSWORD'") if ENV["MATCH_PASSWORD"] + UI.user_error!("Invalid password passed via 'MATCH_PASSWORD'") if ENV["MATCH_PASSWORD"] clear_password self.decrypt_files # Call itself return From 599ab2bdf4f013df049f3ac0ef92e175a91ddfdb Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 08:12:26 +0900 Subject: [PATCH 66/69] dummy commit for test --- match/lib/match/encryption/openssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/match/lib/match/encryption/openssl.rb b/match/lib/match/encryption/openssl.rb index c5a9d3a2a10..2c31a94a93b 100644 --- a/match/lib/match/encryption/openssl.rb +++ b/match/lib/match/encryption/openssl.rb @@ -50,7 +50,7 @@ def decrypt_files rescue => ex UI.verbose(ex.to_s) UI.error("Couldn't decrypt the repo, please make sure you enter the right password!") - UI.user_error!("Invalid password passed via 'MATCH_PASSWORD'") if ENV["MATCH_PASSWORD"] + UI.user_error!("Invalid password passed via 'MATCH_PASSWORD'") if ENV["MATCH_PASSWORD"] clear_password self.decrypt_files # Call itself return From 8be9c7ec4703cc3eb28ae9172a07fd558b9577cf Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 14:05:37 +0900 Subject: [PATCH 67/69] change the implementation place of provider id parser --- .../lib/fastlane_core/itunes_transporter.rb | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 85078e0af15..22c07a76392 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -28,6 +28,9 @@ class TransporterExecutor OUTPUT_REGEX = />\s+(.+)/ RETURN_VALUE_REGEX = />\sDBG-X:\sReturning\s+(\d+)/ + # Matches a line in the iTMSTransporter provider table: "12 Initech Systems Inc LG89CQY559" + ITMS_PROVIDER_REGEX = /^\d+\s{2,}.+\s{2,}[^\s]+$/ + SKIP_ERRORS = ["ERROR: An exception has occurred: Scheduling automatic restart in 1 minute"] private_constant :ERROR_REGEX, :WARNING_REGEX, :OUTPUT_REGEX, :RETURN_VALUE_REGEX, :SKIP_ERRORS @@ -100,8 +103,18 @@ def displayable_errors @errors.map { |error| "[Transporter Error Output]: #{error}" }.join("\n").gsub!(/"/, "") end + def parse_provider_info(lines) + lines.map { |line| itms_provider_pair(line) }.compact.to_h + end + private + def itms_provider_pair(line) + line = line.strip + return nil unless line =~ ITMS_PROVIDER_REGEX + line.split(/\s{2,}/).drop(1) + end + def parse_line(line, hide_output) # Taken from https://github.com/sshaw/itunes_store_transporter/blob/master/lib/itunes/store/transporter/output_parser.rb @@ -289,6 +302,19 @@ def displayable_errors @errors.map { |error| "[Application Loader Error Output]: #{error}" }.join("\n") end + def parse_provider_info(lines) + # This tries parsing the provider id from altool output to detect provider list + provider_info = {} + json_body = lines[-2] # altool outputs result in second line from last + return provider_info if json_body.nil? + providers = JSON.parse(json_body)["providers"] + return provider_info if providers.nil? + providers.each do |provider| + provider_info[provider["ProviderName"]] = provider["ProviderShortname"] + end + provider_info + end + private def file_upload_option(source) @@ -587,8 +613,6 @@ def execute(command, hide_output) end class ItunesTransporter - # Matches a line in the iTMSTransporter provider table: "12 Initech Systems Inc LG89CQY559" - ITMS_PROVIDER_REGEX = /^\d+\s{2,}.+\s{2,}[^\s]+$/ TWO_STEP_HOST_PREFIX = "deliver.appspecific" # This will be called from the Deliverfile, and disables the logging of the transporter output @@ -626,12 +650,10 @@ def initialize(user = nil, password = nil, use_shell_script = false, provider_sh @jwt = jwt @api_key = api_key - @is_altool = false if should_use_altool?(upload, use_shell_script) UI.verbose("Using altool as transporter.") @transporter_executor = AltoolTransporterExecutor.new - @is_altool = true else UI.verbose("Using iTMSTransporter as transporter.") @transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new @@ -818,7 +840,7 @@ def provider_ids end end - @is_altool ? parse_altool_provider_info(lines) : parse_itsm_provider_info(lines) + @transporter_executor.parse_provider_info(lines) end private @@ -900,28 +922,5 @@ def handle_two_step_failure(ex) def handle_error(password) @transporter_executor.handle_error(password) end - - def itms_provider_pair(line) - line = line.strip - return nil unless line =~ ITMS_PROVIDER_REGEX - line.split(/\s{2,}/).drop(1) - end - - def parse_itsm_provider_info(lines) - lines.map { |line| itms_provider_pair(line) }.compact.to_h - end - - def parse_altool_provider_info(lines) - # This tries parsing the provider id from altool output to detect provider list - provider_info = {} - json_body = lines[-2] # altool outputs result in second line from last - return provider_info if json_body.nil? - providers = JSON.parse(json_body)["providers"] - return provider_info if providers.nil? - providers.each do |provider| - provider_info[provider["ProviderName"]] = provider["ProviderShortname"] - end - provider_info - end end end From 8e7d6f3349ad56c112444df7f84d86831d73b64a Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 14:20:59 +0900 Subject: [PATCH 68/69] make absract method --- .../lib/fastlane_core/itunes_transporter.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 22c07a76392..4445db18148 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -35,6 +35,22 @@ class TransporterExecutor private_constant :ERROR_REGEX, :WARNING_REGEX, :OUTPUT_REGEX, :RETURN_VALUE_REGEX, :SKIP_ERRORS + def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil) + not_implemented(__method__) + end + + def build_provider_ids_command(username, password, jwt = nil, api_key = nil) + not_implemented(__method__) + end + + def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) + not_implemented(__method__) + end + + def build_verify_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil) + not_implemented(__method__) + end + def execute(command, hide_output) if Helper.test? yield(nil) if block_given? From c005aae337e7db579ec640d739f2e4ffa1ae50ac Mon Sep 17 00:00:00 2001 From: freddi Date: Thu, 15 Sep 2022 15:08:20 +0900 Subject: [PATCH 69/69] add raise for not implemented functions --- fastlane_core/lib/fastlane_core/itunes_transporter.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fastlane_core/lib/fastlane_core/itunes_transporter.rb b/fastlane_core/lib/fastlane_core/itunes_transporter.rb index 4445db18148..db2299a66f2 100644 --- a/fastlane_core/lib/fastlane_core/itunes_transporter.rb +++ b/fastlane_core/lib/fastlane_core/itunes_transporter.rb @@ -303,6 +303,14 @@ def build_provider_ids_command(username, password, jwt = nil, api_key = nil) ].compact.join(' ') end + def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil) + raise "This feature has not been implemented yet with altool for Xcode 14" + end + + def build_verify_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil) + raise "This feature has not been implemented yet with altool for Xcode 14" + end + def additional_upload_parameters env_deliver_additional_params = ENV["DELIVER_ALTOOL_ADDITIONAL_UPLOAD_PARAMETERS"] return nil if env_deliver_additional_params.to_s.strip.empty?