Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[deliver][pilot] use altool instead of using iTMSTransporter for Xcode 14 #20631

Merged
merged 69 commits into from Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
83cdc08
Use altool instead of using iTMSTransporter for Xcode 14
freddi-kit Sep 7, 2022
ec4cfee
fix linter error
freddi-kit Sep 7, 2022
f1e0575
fix linter error
freddi-kit Sep 7, 2022
c3a66db
fix linter error
freddi-kit Sep 7, 2022
39c919e
use keyword function for transporter_for_selected_team
freddi-kit Sep 9, 2022
74f681d
fix typo and move platform string handling
freddi-kit Sep 9, 2022
6d10343
remove unecessary return
freddi-kit Sep 9, 2022
ce9b12d
create should_use_altool
freddi-kit Sep 9, 2022
40337e3
fix to use unless to make code one line
freddi-kit Sep 9, 2022
0f2a3d4
make code oneline by using unless
freddi-kit Sep 9, 2022
d675551
improve error message
freddi-kit Sep 9, 2022
fa388c7
fix to support apple connect api key
freddi-kit Sep 9, 2022
dcb97a8
fix jwt check
freddi-kit Sep 9, 2022
5bd7d3f
fix to set? for boolean function
freddi-kit Sep 9, 2022
2023aa8
fix rubocup issue
freddi-kit Sep 9, 2022
7a13c48
fix rubocup issue
freddi-kit Sep 9, 2022
8df9559
fix test
freddi-kit Sep 9, 2022
ed28c90
fix to call upload without replacement
freddi-kit Sep 9, 2022
375f951
fix typo
freddi-kit Sep 9, 2022
711eb3c
fix checking apikey available or not
freddi-kit Sep 9, 2022
747178f
fix to generate p8 file for every calling altool
freddi-kit Sep 10, 2022
13afc8c
PR review fixes (Remove unused file, autogenerated by uni-tests + imp…
crazymanish Sep 10, 2022
d36bf23
Fix itunes_transporter_spec.rb which was failing in Xcode14 https://g…
crazymanish Sep 10, 2022
e4e44ac
Fix helper_spec.rb which was failing in Xcode14 https://github.com/fa…
crazymanish Sep 10, 2022
4f677a6
support base64 key_content for using altool with appstore connect apikey
freddi-kit Sep 10, 2022
9988e33
fix typo
freddi-kit Sep 10, 2022
4ebf009
fix to remove un-necessary begin
freddi-kit Sep 10, 2022
ddb437a
fix to use unless
freddi-kit Sep 10, 2022
b4f5324
improve showing error on UI
freddi-kit Sep 10, 2022
44bf7aa
fix to remove warning in altool executer
freddi-kit Sep 10, 2022
01a5873
improve error log
freddi-kit Sep 10, 2022
7490c5c
add some small fix
freddi-kit Sep 10, 2022
388726b
fix code format
freddi-kit Sep 11, 2022
b070b58
fix to remove unnecessary return
freddi-kit Sep 11, 2022
1cdc817
fix to use File.open() |p8|
freddi-kit Sep 11, 2022
c82e99a
fix to use mktmpdir for saving p8 temp
freddi-kit Sep 12, 2022
bdbacb5
fix linter issue
freddi-kit Sep 12, 2022
00c974c
fix to use wb option when making p8 file
freddi-kit Sep 12, 2022
1994860
add unit test for altool case
freddi-kit Sep 12, 2022
16249e7
fix test format
freddi-kit Sep 12, 2022
8ab40fa
remove space
freddi-kit Sep 12, 2022
22cfcec
support api json path
freddi-kit Sep 13, 2022
3fc11fa
add some comment and fix code style
freddi-kit Sep 13, 2022
980f189
add comment about error info
freddi-kit Sep 13, 2022
669bebc
compose return expression in one line
freddi-kit Sep 13, 2022
98e1a88
fix to use checking raise_error
freddi-kit Sep 13, 2022
355cc9d
use context for matching rpec
freddi-kit Sep 13, 2022
0f6bfcb
fix code's readability
freddi-kit Sep 13, 2022
f4cd020
fix lint
freddi-kit Sep 13, 2022
95e7cb8
fix lint
freddi-kit Sep 13, 2022
38f23ee
fix lint
freddi-kit Sep 13, 2022
30839b9
fix ids provider problem
freddi-kit Sep 14, 2022
a2ea2fb
add comments
freddi-kit Sep 14, 2022
874320c
add test for provider ids
freddi-kit Sep 14, 2022
ab02d6d
fix api key condition to make code more readable
freddi-kit Sep 14, 2022
71e57d6
add more detailed comment
freddi-kit Sep 14, 2022
b518207
fix typo
freddi-kit Sep 14, 2022
8d5bb62
improve specifying substring
freddi-kit Sep 14, 2022
5beca1e
fix index
freddi-kit Sep 14, 2022
4f4d3ee
fix altool providers output to parse json
freddi-kit Sep 14, 2022
cd2c504
fix code format
freddi-kit Sep 14, 2022
4b93a81
fix hash problem if user pass key via environment variable
freddi-kit Sep 14, 2022
18f460f
remove unnecessary !
freddi-kit Sep 14, 2022
ac7358d
fix null handle
freddi-kit Sep 14, 2022
07181a7
dummy commit for test
freddi-kit Sep 14, 2022
599ab2b
dummy commit for test
freddi-kit Sep 14, 2022
8be9c7e
change the implementation place of provider id parser
freddi-kit Sep 15, 2022
8e7d6f3
make absract method
freddi-kit Sep 15, 2022
c005aae
add raise for not implemented functions
freddi-kit Sep 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 7 additions & 7 deletions deliver/lib/deliver/runner.rb
Expand Up @@ -206,7 +206,7 @@ def upload_binary
pkg_path = options[:pkg]

platform = options[:platform]
transporter = transporter_for_selected_team
transporter = transporter_for_selected_team(upload: true)

case platform
when "ios", "appletvos"
Expand All @@ -216,15 +216,15 @@ 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,
pkg_path: pkg_path,
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_path, platform: platform)
else
UI.user_error!("No suitable file found for upload for platform: #{options[:platform]}")
end
Expand Down Expand Up @@ -270,25 +270,25 @@ 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, 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])
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
team = tunes_client.teams.find { |t| t['providerId'].to_s == tunes_client.team_id }
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, 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
Expand Down
6 changes: 3 additions & 3 deletions deliver/spec/runner_spec.rb
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
160 changes: 153 additions & 7 deletions fastlane_core/lib/fastlane_core/itunes_transporter.rb
Expand Up @@ -180,9 +180,122 @@ def additional_upload_parameters
end
end

# Generates commands and executes the altool.
class AltoolTransporterExecutor < TransporterExecutor
ERROR_REGEX = /\*\*\* Error:\s+(.+)/

private_constant :ERROR_REGEX

def execute(command, hide_output)
if Helper.test?
yield(nil) if block_given?
command
end

@errors = []
@all_lines = []

if hide_output
giginet marked this conversation as resolved.
Show resolved Hide resolved
# 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?

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
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

def build_upload_command(username, password, source = "/tmp", provider_short_name = "", jwt = nil, platform = nil, api_key = nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💄 I'd love for this method to use named parameters at some point (build_upload_command(username:, password:, source: "/tmp", provider_short_name: "", jwt: nil, platform: nil, api_key: nil) for easier-to-read call sites; but that's just a code-style nitpick and not a blocker at all, and can be ironed out in a separate PR, so no worries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, since build_upload_command's style is same with other executer class so it would be kind of refactoring. I think I can do it later PR 🙇

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally 👍 no need to fix this in this PR given the refactoring it will involve indeed. And not that critical if we don't do it anyway to be honest 🙃

giginet marked this conversation as resolved.
Show resolved Hide resolved
use_api_key = !api_key.nil?
[
("API_PRIVATE_KEYS_DIR=#{Dir.tmpdir}" if use_api_key),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course if you decide to go with my suggestion of using TempFile to generate the temporary p8 file, you'll have to adjust this here too.

Easiest way to do this imho is to pass the tmp_p8_file_path that you'd generate via TempFile (or Dir.mktmpdir) as the api_key parameter of the build_upload_command function at this call site, instead of passing the actual API key value (since that value would already be written to the temp p8 file and we don't use it directly in this method's implementation anyway). And then use "API_PRIVATE_KEYS_DIR=#{File.dirname(api_key)}" if use_api_key here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of passing the actual API key value

Other API key value is necessary like key_id and issuer_id, so I wanna you this api_key argument as current actual API key value

"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),
platform_option(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
giginet marked this conversation as resolved.
Show resolved Hide resolved
freddi-kit marked this conversation as resolved.
Show resolved Hide resolved

env_deliver_additional_params.to_s.strip
end

def handle_error(password)
UI.error("Could not download/upload from App Store Connect!")
giginet marked this conversation as resolved.
Show resolved Hide resolved
end

def displayable_errors
@errors.map { |error| "[Application Loader Error Output]: #{error}" }.join("\n")
end

private

def file_upload_option(source)
"-f #{source.shellescape}"
end

def platform_option(platform)
"-t #{platform == 'osx' ? 'macos' : platform}"
end

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
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, api_key = nil)
use_jwt = !jwt.to_s.empty?
[
'"' + Helper.transporter_path + '"',
Expand Down Expand Up @@ -278,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)
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)
[
Expand Down Expand Up @@ -476,7 +589,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, 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.')
Expand All @@ -489,8 +602,16 @@ 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("Using altool as transporter.")
@transporter_executor = AltoolTransporterExecutor.new
else
UI.verbose("Using iTMSTransporter as transporter.")
@transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new
end
giginet marked this conversation as resolved.
Show resolved Hide resolved

@transporter_executor = use_shell_script ? ShellScriptTransporterExecutor.new : JavaTransporterExecutor.new
@provider_short_name = provider_short_name
end

Expand Down Expand Up @@ -539,7 +660,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
Expand Down Expand Up @@ -569,14 +690,33 @@ 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))
# 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-style nitpick: merging those two lines into a single one using a ternary condition will make this easier to read/reason about imho:

Suggested change
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


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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to instead use Dir.mktmpdir to create an intermediate and guaranteed-unique temporary folder and generate the key file inside it. Or use TempFile to create the file.

(PS: In either case you can provide a prefix (like deliver-) to use for the autogenerate unique filename which could help identify it on disk… even though it'll get deleted soon after so it doesn't really matter)

If you go that route you'll have to declare tmp_p8_file_path = nil before the begin, then set it to a value on this line, so that you'll be able to use the same tmp_p8_file_path value in your ensure block to delete it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! c82e99a

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)
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?)
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you go with my suggestion above to use TempFile to create the file, this would become just:

Suggested change
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
FileUtils.rm_f(tmp_p8_file_path) unless tmp_p8_file_path.nil?

end

if result
Expand Down Expand Up @@ -657,6 +797,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
Expand Down
12 changes: 10 additions & 2 deletions fastlane_core/spec/helper_spec.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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
freddi-kit marked this conversation as resolved.
Show resolved Hide resolved
else
expect(FastlaneCore::Helper.itms_path).to match(/itms/)
end
end

it "uses FASTLANE_ITUNES_TRANSPORTER_PATH", requires_xcode: true do
Expand Down
3 changes: 3 additions & 0 deletions fastlane_core/spec/itunes_transporter_spec.rb
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions pilot/lib/pilot/build_manager.rb
Expand Up @@ -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)

unless result
transporter_errors = transporter.displayable_errors
Expand Down Expand Up @@ -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, 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])
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

Expand All @@ -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, 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.")
Expand Down