class FastlaneCore::AltoolTransporterExecutor

Generates commands and executes the altool.

Constants

ERROR_REGEX

Attributes

errors[R]

Public Instance Methods

additional_upload_parameters() click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 331
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?

  env_deliver_additional_params.to_s.strip
end
build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 309
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
build_provider_ids_command(username, password, jwt = nil, api_key = nil) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 295
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),
    "--output-format json"
  ].compact.join(' ')
end
build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 277
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_dir]}" if use_api_key),
    "xcrun altool",
    "--upload-app",
    ("-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),
    ("--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,
    "-k 100000"
  ].compact.join(' ')
end
build_verify_command(username, password, source = "/tmp", provider_short_name = "", **kwargs) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 313
def build_verify_command(username, password, source = "/tmp", provider_short_name = "", **kwargs)
  api_key = kwargs[:api_key]
  platform = kwargs[:platform]
  use_api_key = !api_key.nil?
  [
    ("API_PRIVATE_KEYS_DIR=#{api_key[:key_dir]}" if use_api_key),
    "xcrun altool",
    "--validate-app",
    ("-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),
    ("--asc-provider #{provider_short_name}" unless use_api_key || provider_short_name.to_s.empty?),
    platform_option(platform),
    file_upload_option(source)
  ].compact.join(' ')
end
displayable_errors() click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 342
def displayable_errors
  @errors.map { |error| "[Application Loader Error Output]: #{error}" }.join("\n")
end
execute(command, hide_output) { |nil| ... } click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 220
def execute(command, hide_output)
  if Helper.test?
    yield(nil) if block_given?
    return command
  end

  @errors = []
  @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|
      command_stdout.each do |line|
        @all_lines << line
        parse_line(line, hide_output) # this is where the parsing happens
      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

  @errors << "The call to the altool completed with a non-zero exit status: #{exit_status}. This indicates a failure." unless exit_status.zero?
  @errors << "-1 indicates altool exited abnormally; try retrying (see https://github.com/fastlane/fastlane/issues/21535)" if exit_status == -1

  unless @errors.empty? || @all_lines.empty?
    # 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
    UI.message("Application Loader output above ^")
    @errors.each { |error| UI.error(error) }
  end

  yield(@all_lines) if block_given?
  exit_status.zero?
end
handle_error(password) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 338
def handle_error(password)
  UI.error("Could not download/upload from App Store Connect!")
end
parse_provider_info(lines) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 346
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 Instance Methods

file_upload_option(source) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 361
def file_upload_option(source)
  "-f #{source.shellescape}"
end
parse_line(line, hide_output) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 369
def parse_line(line, hide_output)
  output_done = false

  if line =~ ERROR_REGEX
    @errors << $1
    output_done = true
  end

  unless hide_output
    # General logging for debug purposes
    unless output_done
      UI.verbose("[altool]: #{line}")
    end
  end
end
platform_option(platform) click to toggle source
# File fastlane_core/lib/fastlane_core/itunes_transporter.rb, line 365
def platform_option(platform)
  "-t #{platform == 'osx' ? 'macos' : platform}"
end