Class: FastlaneCore::TransporterExecutor

Inherits:
Object
  • Object
show all
Defined in:
fastlane_core/lib/fastlane_core/itunes_transporter.rb

Overview

Base class for executing the iTMSTransporter

Constant Summary collapse

ITMS_PROVIDER_REGEX =

Matches a line in the iTMSTransporter provider table: “12 Initech Systems Inc LG89CQY559”

/^\d+\s{2,}.+\s{2,}[^\s]+$/

Instance Method Summary collapse

Instance Method Details

#build_credential_params(username = nil, password = nil, jwt = nil, api_key = nil) ⇒ String

Builds a string array of credentials parameters based on the provided authentication details.

Parameters:

  • username (String, nil) (defaults to: nil)

    The username for authentication (optional).

  • password (String, nil) (defaults to: nil)

    The password for authentication (optional).

  • jwt (String, nil) (defaults to: nil)

    A JSON Web Token for token-based authentication (optional).

  • api_key (Hash, nil) (defaults to: nil)

    An API key for authentication (optional).

Returns:

  • (String)

    A string containing the appropriate credentials for authentication.



62
63
64
# 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

#build_download_command(username, password, apple_id, destination = "/tmp", provider_short_name = "", jwt = nil) ⇒ Object



38
39
40
# 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

#build_provider_ids_command(username, password, jwt = nil, api_key = nil) ⇒ Object



42
43
44
# 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

#build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil) ⇒ Object



46
47
48
# 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

#build_verify_command(username, password, source = "/tmp", provider_short_name = "", **kwargs) ⇒ Object



50
51
52
# 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

#displayable_errorsObject



157
158
159
# 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

#execute(command, hide_output) {|@all_lines| ... } ⇒ Object

Yields:

  • (@all_lines)


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# 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

#parse_provider_info(lines) ⇒ Object



161
162
163
# 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

#prepare(original_api_key:) ⇒ Hash

Runs preparations before executing any command from the executor.

Parameters:

  • original_api_key (Hash)

    api key containing the issuer id and private key

Returns:

  • (Hash)

    copy of ‘api_key` which includes an extra `key_dir` with the location of the .p8 file on disk



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 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