class FastlaneCore::TransporterExecutor
Base class for executing the iTMSTransporter
Constants
- ERROR_REGEX
- ITMS_PROVIDER_REGEX
-
Matches a line in the iTMSTransporter provider table: “12 Initech Systems Inc LG89CQY559”
- OUTPUT_REGEX
- RETURN_VALUE_REGEX
- SKIP_ERRORS
- WARNING_REGEX
Public Instance Methods
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 62 def build_credential_params(username = nil, password = nil, jwt = nil, api_key = nil) not_implemented(__method__) end
Builds a string array of credentials parameters based on the provided authentication details.
@param username [String, nil] The username for authentication (optional). @param password [String, nil] The password for authentication (optional). @param jwt [String, nil] A JSON Web Token for token-based authentication (optional). @param api_key [Hash, nil] An API key for authentication (optional).
@return [String] A string containing the appropriate credentials for authentication.
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 38 def build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil) not_implemented(__method__) end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 42 def build_provider_ids_command(username, password, jwt = nil, api_key = nil) not_implemented(__method__) end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 46 def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) not_implemented(__method__) end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 50 def build_verify_command(username, password, source = "/tmp", provider_short_name = "", **kwargs) not_implemented(__method__) end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 157 def displayable_errors @errors.map { |error| "[Transporter Error Output]: #{error}" }.join("\n").gsub!(/"/, "") end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 93 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("iTunes Transporter 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 iTMSTransporter 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.join("").include?("app-specific") raise TransporterRequiresApplicationSpecificPasswordError end if @errors.count > 0 && @all_lines.count > 0 # Print out the last 15 lines, this is key for non-verbose mode @all_lines.last(15).each do |line| UI.important("[iTMSTransporter] #{line}") end UI.message("iTunes Transporter output above ^") UI.error(@errors.join("\n")) end # this is to handle GitHub issue #1896, which occurs when an # iTMSTransporter file transfer fails; iTMSTransporter will log an error # but will then retry; if that retry is successful, we will see the error # logged, but since the status code is zero, we want to return success if @errors.count > 0 && exit_status.zero? UI.important("Although errors occurred during execution of iTMSTransporter, it returned success status.") end yield(@all_lines) if block_given? return exit_status.zero? end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 161 def parse_provider_info(lines) lines.map { |line| itms_provider_pair(line) }.compact.to_h end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 70 def prepare(original_api_key:) return if original_api_key.nil? # Create .p8 file from api_key and provide api key info which contains .p8 file path api_key = original_api_key.dup if self.kind_of?(ShellScriptTransporterExecutor) # as of Transporter v3.3.0, the app is unable to detect the private keys under the 'private_keys' folder in current directory # so we must rely on the other search paths in the Home dir: # https://help.apple.com/itc/transporteruserguide/en.lproj/static.html#itc803b7be80 private_keys_dir = File.join(Dir.home, ".appstoreconnect/private_keys") unless Dir.exist?(private_keys_dir) FileUtils.mkdir_p(private_keys_dir) end api_key[:key_dir] = private_keys_dir else api_key[:key_dir] = Dir.mktmpdir("deliver-") end # Specified p8 needs to be generated to call altool or iTMSTransporter File.open(File.join(api_key[:key_dir], "AuthKey_#{api_key[:key_id]}.p8"), "wb") do |p8| p8.write(api_key[:key]) end api_key end
Runs preparations before executing any command from the executor.
@param original_api_key [Hash] api key containing the issuer id and private key @return [Hash] copy of ‘api_key` which includes an extra `key_dir` with the location of the .p8 file on disk
Private Instance Methods
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 232 def additional_upload_parameters # As Apple recommends in Transporter User Guide we shouldn't specify the -t transport parameter # and instead allow Transporter to use automatic transport discovery # to determine the best transport mode for packages. # It became crucial after WWDC 2020 as it leaded to "Broken pipe (Write failed)" exception # More information https://github.com/fastlane/fastlane/issues/16749 env_deliver_additional_params = ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"] if env_deliver_additional_params.to_s.strip.empty? return nil end deliver_additional_params = env_deliver_additional_params.to_s.strip if deliver_additional_params.include?("-t ") UI.important("Apple recommends you don’t specify the -t transport and instead allow Transporter to use automatic transport discovery to determine the best transport mode for your packages. For more information, please read Apple's Transporter User Guide 2.1: https://help.apple.com/itc/transporteruserguide/#/apdATD1E1288-D1E1A1303-D1E1288A1126") end return deliver_additional_params end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 221 def file_upload_option(source) ext = File.extname(source).downcase is_asset_file_type = !File.directory?(source) && [".ipa", ".pkg", ".dmg", ".zip"].include?(ext) if is_asset_file_type return "-assetFile #{source.shellescape}" else return "-f #{source.shellescape}" end end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 167 def itms_provider_pair(line) line = line.strip return nil unless line =~ ITMS_PROVIDER_REGEX line.split(/\s{2,}/).drop(1) end
Source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 173 def parse_line(line, hide_output) # Taken from https://github.com/sshaw/itunes_store_transporter/blob/master/lib/itunes/store/transporter/output_parser.rb 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 @errors << $1 # Check if it's a login error if $1.include?("Your Apple ID or password was entered incorrectly") || $1.include?("This Apple ID has been locked for security reasons") 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 elsif line =~ WARNING_REGEX @warnings << $1 UI.important("[Transporter Warning Output]: #{$1}") output_done = true end if line =~ RETURN_VALUE_REGEX if $1.to_i != 0 UI.error("Transporter transfer failed.") UI.important(@warnings.join("\n")) UI.error(@errors.join("\n")) UI.crash!("Return status of iTunes Transporter was #{$1}: #{@errors.join('\n')}") else 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