Skip to content

Commit 5cbc8bd

Browse files
janpioJosh Holtz
andauthored
[pilot] Do not use spaceship if both skip_waiting_for_build_processing and apple_id are set (fastlane#14456)
* make pilot not use spaceship if both skip_waiting_for_build_processing and apple_id are set * make rubocop happy * use options instead of config (assumption: they are actually identical) * still have to fill @config somehow when start is not called (UGLY!) * prepare test a bit * 2 tests that make sure that the spaceship login method is only called when the 2 options are _not_ set * make rubocop happy * add missing options param * add missing options param * add some docs * A few small improvements * rename and clarify specs * add explicit expect and !expect clean and resort allows * rubocop * correct order * Removed the login_if_needed method and replaced with better code and comments Co-authored-by: Josh Holtz <josh@rokkincat.com>
1 parent 457c5d6 commit 5cbc8bd

File tree

4 files changed

+90
-15
lines changed

4 files changed

+90
-15
lines changed

fastlane/lib/fastlane/actions/docs/upload_to_testflight.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,7 @@ _pilot_ uses the [CredentialsManager](https://github.com/fastlane/fastlane/tree/
225225

226226
## Provider Short Name
227227
If you are on multiple App Store Connect teams, iTunes Transporter may need a provider short name to know where to upload your binary. _pilot_ will try to use the long name of the selected team to detect the provider short name. To override the detected value with an explicit one, use the `itc_provider` option.
228+
229+
## Use an Application Specific Password to upload
230+
231+
_pilot_/`upload_to_testflight` can use an [Application Specific Password via the `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` envirionment variable](https://docs.fastlane.tools/best-practices/continuous-integration/#application-specific-passwords) to upload a binary if both the `skip_waiting_for_build_processing` and `apple_id` options are set. (If any of those are not set, it will use the normal Apple login process that might require 2FA authentication.)

pilot/lib/pilot/build_manager.rb

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
module Pilot
1111
class BuildManager < Manager
1212
def upload(options)
13-
start(options)
13+
# Only need to login before upload if no apple_id was given
14+
# 'login' will be deferred until before waiting for build processing
15+
should_login_in_start = options[:apple_id].nil?
16+
start(options, should_login: should_login_in_start)
1417

1518
options[:changelog] = self.class.sanitize_changelog(options[:changelog]) if options[:changelog]
1619

@@ -24,18 +27,18 @@ def upload(options)
2427
end
2528
end
2629

27-
UI.success("Ready to upload new build to TestFlight (App: #{app.apple_id})...")
30+
UI.success("Ready to upload new build to TestFlight (App: #{fetch_apple_id})...")
2831

2932
dir = Dir.mktmpdir
3033

3134
platform = fetch_app_platform
32-
package_path = FastlaneCore::IpaUploadPackageBuilder.new.generate(app_id: app.apple_id,
33-
ipa_path: config[:ipa],
35+
package_path = FastlaneCore::IpaUploadPackageBuilder.new.generate(app_id: fetch_apple_id,
36+
ipa_path: options[:ipa],
3437
package_path: dir,
3538
platform: platform)
3639

3740
transporter = transporter_for_selected_team(options)
38-
result = transporter.upload(app.apple_id, package_path)
41+
result = transporter.upload(fetch_apple_id, package_path)
3942

4043
unless result
4144
UI.user_error!("Error uploading ipa file, for more information see above")
@@ -49,6 +52,9 @@ def upload(options)
4952
return
5053
end
5154

55+
# Calling login again here is needed if login was not called during 'start'
56+
login unless should_login_in_start
57+
5258
UI.message("If you want to skip waiting for the processing to be finished, use the `skip_waiting_for_build_processing` option")
5359
latest_build = wait_for_build_processing_to_be_complete
5460
distribute(options, build: latest_build)
@@ -58,7 +64,7 @@ def wait_for_build_processing_to_be_complete
5864
platform = fetch_app_platform
5965
app_version = FastlaneCore::IpaFileAnalyser.fetch_app_version(config[:ipa])
6066
app_build = FastlaneCore::IpaFileAnalyser.fetch_app_build(config[:ipa])
61-
latest_build = FastlaneCore::BuildWatcher.wait_for_build_processing_to_be_complete(app_id: app.apple_id, platform: platform, train_version: app_version, build_version: app_build, poll_interval: config[:wait_processing_interval])
67+
latest_build = FastlaneCore::BuildWatcher.wait_for_build_processing_to_be_complete(app_id: app.apple_id, platform: platform, train_version: app_version, build_version: app_build, poll_interval: config[:wait_processing_interval], strict_build_watch: config[:wait_for_uploaded_build])
6268

6369
unless latest_build.train_version == app_version && latest_build.build_version == app_build
6470
UI.important("Uploaded app #{app_version} - #{app_build}, but received build #{latest_build.train_version} - #{latest_build.build_version}.")
@@ -220,7 +226,8 @@ def should_update_localized_build_information?(options)
220226
# If there are fewer than two teams, don't infer the provider.
221227
def transporter_for_selected_team(options)
222228
generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider])
223-
return generic_transporter unless options[:itc_provider].nil? && Spaceship::Tunes.client.teams.count > 1
229+
return generic_transporter if options[:itc_provider] || Spaceship::Tunes.client.nil?
230+
return generic_transporter unless Spaceship::Tunes.client.teams.count > 1
224231

225232
begin
226233
team = Spaceship::Tunes.client.teams.find { |t| t['contentProvider']['contentProviderId'].to_s == Spaceship::Tunes.client.team_id }

pilot/lib/pilot/manager.rb

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010

1111
module Pilot
1212
class Manager
13-
def start(options)
13+
def start(options, should_login: true)
1414
return if @config # to not login multiple times
1515
@config = options
16-
login
16+
login if should_login
1717
end
1818

1919
def login
@@ -27,7 +27,7 @@ def login
2727

2828
# The app object we're currently using
2929
def app
30-
@apple_id ||= fetch_app_id
30+
@apple_id ||= fetch_apple_id
3131

3232
@app ||= Spaceship::Tunes::Application.find(@apple_id)
3333
unless @app
@@ -42,19 +42,20 @@ def app
4242
# Config Related
4343
################
4444

45-
def fetch_app_id
45+
def fetch_apple_id
46+
@apple_id ||= config[:apple_id]
4647
return @apple_id if @apple_id
4748
config[:app_identifier] = fetch_app_identifier
4849

4950
if config[:app_identifier]
5051
@app ||= Spaceship::Tunes::Application.find(config[:app_identifier])
5152
UI.user_error!("Couldn't find app '#{config[:app_identifier]}' on the account of '#{config[:username]}' on App Store Connect") unless @app
52-
app_id ||= @app.apple_id
53+
apple_id ||= @app.apple_id
5354
end
5455

55-
app_id ||= UI.input("Could not automatically find the app ID, please enter it here (e.g. 956814360): ")
56+
apple_id ||= UI.input("Could not automatically find the app ID, please enter it here (e.g. 956814360): ")
5657

57-
return app_id
58+
return apple_id
5859
end
5960

6061
def fetch_app_identifier

pilot/spec/build_manager_spec.rb

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
expect(changelog).to eq("1234")
1212
end
1313
end
14+
1415
describe ".sanitize_changelog" do
1516
it "removes emoji" do
1617
changelog = "I'm 🦇B🏧an!"
@@ -24,7 +25,8 @@
2425
expect(changelog).to eq(File.read("./pilot/spec/fixtures/build_manager/changelog_long_truncated"))
2526
end
2627
end
27-
describe "distribute submits the build for review" do
28+
29+
describe "#distribute submits the build for review" do
2830
let(:mock_base_client) { "fake testflight base client" }
2931
let(:mock_base_api_client) { "fake api base client" }
3032
let(:fake_build_manager) { Pilot::BuildManager.new }
@@ -240,4 +242,65 @@
240242
end
241243
end
242244
end
245+
246+
describe "#upload" do
247+
describe "uses Manager.login (which does spaceship login)" do
248+
let(:fake_build_manager) { Pilot::BuildManager.new }
249+
let(:upload_options) do
250+
{
251+
apple_id: 'mock_apple_id',
252+
skip_waiting_for_build_processing: true,
253+
ipa: 'foo'
254+
}
255+
end
256+
257+
before(:each) do
258+
allow(fake_build_manager).to receive(:fetch_app_platform).and_return('ios')
259+
260+
fake_ipauploadpackagebuilder = double
261+
allow(fake_ipauploadpackagebuilder).to receive(:generate).and_return(true)
262+
allow(FastlaneCore::IpaUploadPackageBuilder).to receive(:new).and_return(fake_ipauploadpackagebuilder)
263+
264+
fake_itunestransporter = double
265+
allow(fake_itunestransporter).to receive(:upload).and_return(true)
266+
allow(FastlaneCore::ItunesTransporter).to receive(:new).and_return(fake_itunestransporter)
267+
end
268+
269+
it "NOT when skip_waiting_for_build_processing and apple_id are set" do
270+
# should not execute Manager.login (which does spaceship login)
271+
expect(fake_build_manager).not_to(receive(:login))
272+
273+
fake_build_manager.upload(upload_options)
274+
end
275+
276+
it "when skip_waiting_for_build_processing and apple_id are not set" do
277+
# remove options that make login unnecessary
278+
upload_options.delete(:apple_id)
279+
upload_options.delete(:skip_waiting_for_build_processing)
280+
281+
# allow Manager.login method this time
282+
expect(fake_build_manager).to receive(:login).at_least(:once)
283+
284+
# other stuff required to let `upload` work:
285+
286+
allow(FastlaneCore::IpaFileAnalyser).to receive(:fetch_app_identifier).and_return("com.fastlane")
287+
allow(fake_build_manager).to receive(:fetch_apple_id).and_return(123)
288+
allow(FastlaneCore::IpaFileAnalyser).to receive(:fetch_app_version)
289+
allow(FastlaneCore::IpaFileAnalyser).to receive(:fetch_app_build)
290+
291+
fake_app = double
292+
allow(fake_app).to receive(:apple_id).and_return(123)
293+
allow(fake_build_manager).to receive(:app).and_return(fake_app)
294+
295+
fake_build = double
296+
allow(fake_build).to receive(:train_version)
297+
allow(fake_build).to receive(:build_version)
298+
allow(FastlaneCore::BuildWatcher).to receive(:wait_for_build_processing_to_be_complete).and_return(fake_build)
299+
300+
allow(fake_build_manager).to receive(:distribute)
301+
302+
fake_build_manager.upload(upload_options)
303+
end
304+
end
305+
end
243306
end

0 commit comments

Comments
 (0)