fastlane 2.34.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a703ca979d3b3cd10a0396a0cc9a826bfa43d67
|
4
|
+
data.tar.gz: 5909052758266430d88fc2a1970b8399848039da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17c241d3e80cf683d5ff1a5426cea3870cd1f58bb4574d8d3a823499e0a472ea079fbd80d37d0bb604b56f0ca150aeb47afc48b96f1e67f6bb047dcf7c2683e8
|
7
|
+
data.tar.gz: 1f8ee5eccdccfd78b1270c1a604037faac1b474d94b84bc6e3d0c24b0a3402ec3e322c9586119f8d3a6cb2ddea5a6e0fed395e02a325709d5e871cb8226c7461
|
@@ -28,6 +28,7 @@ module Fastlane
|
|
28
28
|
|
29
29
|
input_format: '--input-format',
|
30
30
|
scheme: '--scheme',
|
31
|
+
configuration: '--configuration',
|
31
32
|
workspace: '--workspace',
|
32
33
|
binary_file: '--binary-file',
|
33
34
|
binary_basename: '--binary-basename',
|
@@ -52,7 +53,20 @@ module Fastlane
|
|
52
53
|
File.file?('.slather.yml')
|
53
54
|
end
|
54
55
|
|
56
|
+
def self.slather_version
|
57
|
+
require 'slather'
|
58
|
+
Slather::VERSION
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.configuration_available?
|
62
|
+
Gem::Version.new('2.4.1') <= Gem::Version.new(slather_version)
|
63
|
+
end
|
64
|
+
|
55
65
|
def self.validate_params!(params)
|
66
|
+
if params[:configuration]
|
67
|
+
UI.user_error!('configuration option is available since version 2.4.1') unless configuration_available?
|
68
|
+
end
|
69
|
+
|
56
70
|
if params[:proj] || has_config_file
|
57
71
|
true
|
58
72
|
else
|
@@ -121,6 +135,10 @@ Slather is available at https://github.com/SlatherOrg/slather
|
|
121
135
|
env_name: "FL_SLATHER_SCHEME", # The name of the environment variable
|
122
136
|
description: "Scheme to use when calling slather",
|
123
137
|
optional: true),
|
138
|
+
FastlaneCore::ConfigItem.new(key: :configuration,
|
139
|
+
env_name: "FL_SLATHER_CONFIGURATION", # The name of the environment variable
|
140
|
+
description: "Configuration to use when calling slather (since slather-2.4.1)",
|
141
|
+
optional: true),
|
124
142
|
FastlaneCore::ConfigItem.new(key: :input_format,
|
125
143
|
env_name: "FL_SLATHER_INPUT_FORMAT", # The name of the environment variable
|
126
144
|
description: "The input format that slather should look for",
|
@@ -137,6 +137,50 @@ module Spaceship
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
+
# Fetch the general information of the user, is used by various methods across spaceship
|
141
|
+
# Sample return value
|
142
|
+
# => {"associatedAccounts"=>
|
143
|
+
# [{"contentProvider"=>{"contentProviderId"=>11142800, "name"=>"Felix Krause", "contentProviderTypes"=>["Purple Software"]}, "roles"=>["Developer"], "lastLogin"=>1468784113000}],
|
144
|
+
# "sessionToken"=>{"dsId"=>"8501011116", "contentProviderId"=>18111111, "expirationDate"=>nil, "ipAddress"=>nil},
|
145
|
+
# "permittedActivities"=>
|
146
|
+
# {"EDIT"=>
|
147
|
+
# ["UserManagementSelf",
|
148
|
+
# "GameCenterTestData",
|
149
|
+
# "AppAddonCreation"],
|
150
|
+
# "REPORT"=>
|
151
|
+
# ["UserManagementSelf",
|
152
|
+
# "AppAddonCreation"],
|
153
|
+
# "VIEW"=>
|
154
|
+
# ["TestFlightAppExternalTesterManagement",
|
155
|
+
# ...
|
156
|
+
# "HelpGeneral",
|
157
|
+
# "HelpApplicationLoader"]},
|
158
|
+
# "preferredCurrencyCode"=>"EUR",
|
159
|
+
# "preferredCountryCode"=>nil,
|
160
|
+
# "countryOfOrigin"=>"AT",
|
161
|
+
# "isLocaleNameReversed"=>false,
|
162
|
+
# "feldsparToken"=>nil,
|
163
|
+
# "feldsparChannelName"=>nil,
|
164
|
+
# "hasPendingFeldsparBindingRequest"=>false,
|
165
|
+
# "isLegalUser"=>false,
|
166
|
+
# "userId"=>"1771111155",
|
167
|
+
# "firstname"=>"Detlef",
|
168
|
+
# "lastname"=>"Mueller",
|
169
|
+
# "isEmailInvalid"=>false,
|
170
|
+
# "hasContractInfo"=>false,
|
171
|
+
# "canEditITCUsersAndRoles"=>false,
|
172
|
+
# "canViewITCUsersAndRoles"=>true,
|
173
|
+
# "canEditIAPUsersAndRoles"=>false,
|
174
|
+
# "transporterEnabled"=>false,
|
175
|
+
# "contentProviderFeatures"=>["APP_SILOING", "PROMO_CODE_REDESIGN", ...],
|
176
|
+
# "contentProviderType"=>"Purple Software",
|
177
|
+
# "displayName"=>"Detlef",
|
178
|
+
# "contentProviderId"=>"18742800",
|
179
|
+
# "userFeatures"=>[],
|
180
|
+
# "visibility"=>true,
|
181
|
+
# "DYCVisibility"=>false,
|
182
|
+
# "contentProvider"=>"Felix Krause",
|
183
|
+
# "userName"=>"detlef@krausefx.com"}
|
140
184
|
def user_details_data
|
141
185
|
return @_cached_user_details if @_cached_user_details
|
142
186
|
r = request(:get, '/WebObjects/iTunesConnect.woa/ra/user/detail')
|
@@ -186,6 +230,13 @@ module Spaceship
|
|
186
230
|
@current_team_id = team_id
|
187
231
|
end
|
188
232
|
|
233
|
+
# @return (Hash) Fetches all information of the currently used team
|
234
|
+
def team_information
|
235
|
+
teams.find do |t|
|
236
|
+
t['teamId'] == team_id
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
189
240
|
# Instantiates a client but with a cookie derived from another client.
|
190
241
|
#
|
191
242
|
# HACK: since the `@cookie` is not exposed, we use this hacky way of sharing the instance.
|
@@ -350,7 +401,7 @@ module Spaceship
|
|
350
401
|
if keychain_entry.invalid_credentials
|
351
402
|
login(user)
|
352
403
|
else
|
353
|
-
|
404
|
+
raise ex
|
354
405
|
end
|
355
406
|
end
|
356
407
|
end
|
@@ -392,10 +443,11 @@ module Spaceship
|
|
392
443
|
end
|
393
444
|
|
394
445
|
response = request(:post) do |req|
|
395
|
-
req.url "https://idmsa.apple.com/appleauth/auth/signin
|
446
|
+
req.url "https://idmsa.apple.com/appleauth/auth/signin"
|
396
447
|
req.body = data.to_json
|
397
448
|
req.headers['Content-Type'] = 'application/json'
|
398
449
|
req.headers['X-Requested-With'] = 'XMLHttpRequest'
|
450
|
+
req.headers['X-Apple-Widget-Key'] = self.itc_service_key
|
399
451
|
req.headers['Accept'] = 'application/json, text/javascript'
|
400
452
|
req.headers["Cookie"] = modified_cookie if modified_cookie
|
401
453
|
end
|
@@ -403,23 +455,22 @@ module Spaceship
|
|
403
455
|
raise InvalidUserCredentialsError.new, "Invalid username and password combination. Used '#{user}' as the username."
|
404
456
|
end
|
405
457
|
|
406
|
-
#
|
407
|
-
request(:get, "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/wa")
|
408
|
-
|
409
|
-
# Get the `itctx` from the new (22nd May 2017) API endpoint "olympus"
|
410
|
-
request(:get, "https://olympus.itunes.apple.com/v1/session")
|
458
|
+
# Now we know if the login is successful or if we need to do 2 factor
|
411
459
|
|
412
460
|
case response.status
|
413
461
|
when 403
|
414
462
|
raise InvalidUserCredentialsError.new, "Invalid username and password combination. Used '#{user}' as the username."
|
415
463
|
when 200
|
464
|
+
fetch_olympus_session
|
416
465
|
return response
|
466
|
+
when 409
|
467
|
+
# 2 factor is enabled for this account, first handle that
|
468
|
+
# and then get the olympus session
|
469
|
+
handle_two_step(response)
|
470
|
+
fetch_olympus_session
|
471
|
+
return true
|
417
472
|
else
|
418
|
-
|
419
|
-
if location && URI.parse(location).path == "/auth" # redirect to 2 step auth page
|
420
|
-
handle_two_step(response)
|
421
|
-
return true
|
422
|
-
elsif (response.body || "").include?('invalid="true"')
|
473
|
+
if (response.body || "").include?('invalid="true"')
|
423
474
|
# User Credentials are wrong
|
424
475
|
raise InvalidUserCredentialsError.new, "Invalid username and password combination. Used '#{user}' as the username."
|
425
476
|
elsif (response['Set-Cookie'] || "").include?("itctx")
|
@@ -431,6 +482,11 @@ module Spaceship
|
|
431
482
|
end
|
432
483
|
end
|
433
484
|
|
485
|
+
# Get the `itctx` from the new (22nd May 2017) API endpoint "olympus"
|
486
|
+
def fetch_olympus_session
|
487
|
+
request(:get, "https://olympus.itunes.apple.com/v1/session")
|
488
|
+
end
|
489
|
+
|
434
490
|
def itc_service_key
|
435
491
|
return @service_key if @service_key
|
436
492
|
|
@@ -438,16 +494,10 @@ module Spaceship
|
|
438
494
|
itc_service_key_path = "/tmp/spaceship_itc_service_key.txt"
|
439
495
|
return File.read(itc_service_key_path) if File.exist?(itc_service_key_path)
|
440
496
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
#
|
446
|
-
# https://github.com/fastlane/fastlane/issues/4610
|
447
|
-
headers = { 'Accept-Encoding' => 'identity' }
|
448
|
-
# We need a service key from a JS file to properly auth
|
449
|
-
js = request(:get, "https://itunesconnect.apple.com/itc/static-resources/controllers/login_cntrl.js", nil, headers)
|
450
|
-
@service_key = js.body.match(/itcServiceKey = '(.*)'/)[1]
|
497
|
+
response = request(:get, "https://olympus.itunes.apple.com/v1/app/config?hostname=itunesconnect.apple.com")
|
498
|
+
@service_key = response.body["authServiceKey"].to_s
|
499
|
+
|
500
|
+
raise "Service key is empty" if @service_key.length == 0
|
451
501
|
|
452
502
|
# Cache the key locally
|
453
503
|
File.write(itc_service_key_path, @service_key)
|
@@ -43,59 +43,6 @@ module Spaceship
|
|
43
43
|
"https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/"
|
44
44
|
end
|
45
45
|
|
46
|
-
# @return (Array) A list of all available teams
|
47
|
-
def teams
|
48
|
-
user_details_data['associatedAccounts'].sort_by do |team|
|
49
|
-
[
|
50
|
-
team['contentProvider']['name'],
|
51
|
-
team['contentProvider']['contentProviderId']
|
52
|
-
]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# @return (String) The currently selected Team ID
|
57
|
-
def team_id
|
58
|
-
return @current_team_id if @current_team_id
|
59
|
-
|
60
|
-
if teams.count > 1
|
61
|
-
puts "The current user is in #{teams.count} teams. Pass a team ID or call `select_team` to choose a team. Using the first one for now."
|
62
|
-
end
|
63
|
-
@current_team_id ||= teams[0]['contentProvider']['contentProviderId']
|
64
|
-
end
|
65
|
-
|
66
|
-
# Set a new team ID which will be used from now on
|
67
|
-
def team_id=(team_id)
|
68
|
-
# First, we verify the team actually exists, because otherwise iTC would return the
|
69
|
-
# following confusing error message
|
70
|
-
#
|
71
|
-
# invalid content provider id
|
72
|
-
#
|
73
|
-
available_teams = teams.collect do |team|
|
74
|
-
(team["contentProvider"] || {})["contentProviderId"]
|
75
|
-
end
|
76
|
-
|
77
|
-
result = available_teams.find do |available_team_id|
|
78
|
-
team_id.to_s == available_team_id.to_s
|
79
|
-
end
|
80
|
-
|
81
|
-
unless result
|
82
|
-
raise ITunesConnectError.new, "Could not set team ID to '#{team_id}', only found the following available teams: #{available_teams.join(', ')}"
|
83
|
-
end
|
84
|
-
|
85
|
-
response = request(:post) do |req|
|
86
|
-
req.url "ra/v1/session/webSession"
|
87
|
-
req.body = {
|
88
|
-
contentProviderId: team_id,
|
89
|
-
dsId: user_detail_data.ds_id # https://github.com/fastlane/fastlane/issues/6711
|
90
|
-
}.to_json
|
91
|
-
req.headers['Content-Type'] = 'application/json'
|
92
|
-
end
|
93
|
-
|
94
|
-
handle_itc_response(response.body)
|
95
|
-
|
96
|
-
@current_team_id = team_id
|
97
|
-
end
|
98
|
-
|
99
46
|
# Shows a team selection for the user in the terminal. This should not be
|
100
47
|
# called on CI systems
|
101
48
|
def select_team
|
@@ -149,13 +96,6 @@ module Spaceship
|
|
149
96
|
end
|
150
97
|
end
|
151
98
|
|
152
|
-
# @return (Hash) Fetches all information of the currently used team
|
153
|
-
def team_information
|
154
|
-
teams.find do |t|
|
155
|
-
t['teamId'] == team_id
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
99
|
def send_login_request(user, password)
|
160
100
|
clear_user_cached_data
|
161
101
|
send_shared_login_request(user, password)
|
@@ -679,56 +619,6 @@ module Spaceship
|
|
679
619
|
Spaceship::Tunes::AppVersionRef.factory(data)
|
680
620
|
end
|
681
621
|
|
682
|
-
# Fetch the general information of the user, is used by various methods across spaceship
|
683
|
-
# Sample return value
|
684
|
-
# => {"associatedAccounts"=>
|
685
|
-
# [{"contentProvider"=>{"contentProviderId"=>11142800, "name"=>"Felix Krause", "contentProviderTypes"=>["Purple Software"]}, "roles"=>["Developer"], "lastLogin"=>1468784113000}],
|
686
|
-
# "sessionToken"=>{"dsId"=>"8501011116", "contentProviderId"=>18111111, "expirationDate"=>nil, "ipAddress"=>nil},
|
687
|
-
# "permittedActivities"=>
|
688
|
-
# {"EDIT"=>
|
689
|
-
# ["UserManagementSelf",
|
690
|
-
# "GameCenterTestData",
|
691
|
-
# "AppAddonCreation"],
|
692
|
-
# "REPORT"=>
|
693
|
-
# ["UserManagementSelf",
|
694
|
-
# "AppAddonCreation"],
|
695
|
-
# "VIEW"=>
|
696
|
-
# ["TestFlightAppExternalTesterManagement",
|
697
|
-
# ...
|
698
|
-
# "HelpGeneral",
|
699
|
-
# "HelpApplicationLoader"]},
|
700
|
-
# "preferredCurrencyCode"=>"EUR",
|
701
|
-
# "preferredCountryCode"=>nil,
|
702
|
-
# "countryOfOrigin"=>"AT",
|
703
|
-
# "isLocaleNameReversed"=>false,
|
704
|
-
# "feldsparToken"=>nil,
|
705
|
-
# "feldsparChannelName"=>nil,
|
706
|
-
# "hasPendingFeldsparBindingRequest"=>false,
|
707
|
-
# "isLegalUser"=>false,
|
708
|
-
# "userId"=>"1771111155",
|
709
|
-
# "firstname"=>"Detlef",
|
710
|
-
# "lastname"=>"Mueller",
|
711
|
-
# "isEmailInvalid"=>false,
|
712
|
-
# "hasContractInfo"=>false,
|
713
|
-
# "canEditITCUsersAndRoles"=>false,
|
714
|
-
# "canViewITCUsersAndRoles"=>true,
|
715
|
-
# "canEditIAPUsersAndRoles"=>false,
|
716
|
-
# "transporterEnabled"=>false,
|
717
|
-
# "contentProviderFeatures"=>["APP_SILOING", "PROMO_CODE_REDESIGN", ...],
|
718
|
-
# "contentProviderType"=>"Purple Software",
|
719
|
-
# "displayName"=>"Detlef",
|
720
|
-
# "contentProviderId"=>"18742800",
|
721
|
-
# "userFeatures"=>[],
|
722
|
-
# "visibility"=>true,
|
723
|
-
# "DYCVisibility"=>false,
|
724
|
-
# "contentProvider"=>"Felix Krause",
|
725
|
-
# "userName"=>"detlef@krausefx.com"}
|
726
|
-
def user_details_data
|
727
|
-
return @_cached_user_details if @_cached_user_details
|
728
|
-
r = request(:get, '/WebObjects/iTunesConnect.woa/ra/user/detail')
|
729
|
-
@_cached_user_details = parse_response(r, 'data')
|
730
|
-
end
|
731
|
-
|
732
622
|
# Fetches the User Detail information from ITC. This gets called often and almost never changes
|
733
623
|
# so we cache it
|
734
624
|
# @return [UserDetail] the response
|
@@ -6,9 +6,7 @@ module Spaceship
|
|
6
6
|
|
7
7
|
r = request(:get) do |req|
|
8
8
|
req.url "https://idmsa.apple.com/appleauth/auth"
|
9
|
-
req
|
10
|
-
req.headers["X-Apple-Id-Session-Id"] = @x_apple_id_session_id
|
11
|
-
req.headers["Accept"] = "application/json"
|
9
|
+
update_request_headers(req)
|
12
10
|
end
|
13
11
|
|
14
12
|
if r.body.kind_of?(Hash) && r.body["trustedDevices"].kind_of?(Array)
|
@@ -66,11 +64,10 @@ module Spaceship
|
|
66
64
|
# Send securityCode back to server to get a valid session
|
67
65
|
r = request(:post) do |req|
|
68
66
|
req.url "https://idmsa.apple.com/appleauth/auth/verify/trusteddevice/securitycode"
|
69
|
-
req.headers["Accept"] = "application/json"
|
70
67
|
req.headers['Content-Type'] = 'application/json'
|
71
|
-
req.headers["scnt"] = @scnt
|
72
|
-
req.headers["X-Apple-Id-Session-Id"] = @x_apple_id_session_id
|
73
68
|
req.body = { "securityCode" => { "code" => code.to_s } }.to_json
|
69
|
+
|
70
|
+
update_request_headers(req)
|
74
71
|
end
|
75
72
|
|
76
73
|
# we use `Spaceship::TunesClient.new.handle_itc_response`
|
@@ -121,9 +118,7 @@ module Spaceship
|
|
121
118
|
# Request Token
|
122
119
|
r = request(:put) do |req|
|
123
120
|
req.url "https://idmsa.apple.com/appleauth/auth/verify/device/#{device_id}/securitycode"
|
124
|
-
req
|
125
|
-
req.headers["scnt"] = @scnt
|
126
|
-
req.headers["X-Apple-Id-Session-Id"] = @x_apple_id_session_id
|
121
|
+
update_request_headers(req)
|
127
122
|
end
|
128
123
|
|
129
124
|
# we use `Spaceship::TunesClient.new.handle_itc_response`
|
@@ -137,11 +132,10 @@ module Spaceship
|
|
137
132
|
# Send token back to server to get a valid session
|
138
133
|
r = request(:post) do |req|
|
139
134
|
req.url "https://idmsa.apple.com/appleauth/auth/verify/device/#{device_id}/securitycode"
|
140
|
-
req.headers["Accept"] = "application/json"
|
141
|
-
req.headers["scnt"] = @scnt
|
142
|
-
req.headers["X-Apple-Id-Session-Id"] = @x_apple_id_session_id
|
143
135
|
req.body = { "code" => code.to_s }.to_json
|
144
136
|
req.headers['Content-Type'] = 'application/json'
|
137
|
+
|
138
|
+
update_request_headers(req)
|
145
139
|
end
|
146
140
|
|
147
141
|
begin
|
@@ -193,8 +187,8 @@ module Spaceship
|
|
193
187
|
|
194
188
|
request(:get) do |req|
|
195
189
|
req.url "https://idmsa.apple.com/appleauth/auth/2sv/trust"
|
196
|
-
|
197
|
-
req
|
190
|
+
|
191
|
+
update_request_headers(req)
|
198
192
|
end
|
199
193
|
# This request will fail if the user isn't added to a team on iTC
|
200
194
|
# However we don't really care, this request will still return the
|
@@ -202,5 +196,14 @@ module Spaceship
|
|
202
196
|
|
203
197
|
self.store_cookie
|
204
198
|
end
|
199
|
+
|
200
|
+
# Responsible for setting all required header attributes for the requests
|
201
|
+
# to succeed
|
202
|
+
def update_request_headers(req)
|
203
|
+
req.headers["X-Apple-Id-Session-Id"] = @x_apple_id_session_id
|
204
|
+
req.headers["X-Apple-Widget-Key"] = self.itc_service_key
|
205
|
+
req.headers["Accept"] = "application/json"
|
206
|
+
req.headers["scnt"] = @scnt
|
207
|
+
end
|
205
208
|
end
|
206
209
|
end
|