spaceship 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/spaceship/client.rb +42 -10
- data/lib/spaceship/tunes/tunes_client.rb +49 -16
- data/lib/spaceship/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6a3472e6fb40f5531aa8ae2c860f26fe8594c37
|
4
|
+
data.tar.gz: af5a9f4a0b7c9115123b32c07ef642d3ad80cfe6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b221fef762f3099d9893703b3959ba5302c595b23110af77a392febe04ae894b01d51065a877ebd8e0441c9e1210b09514ec87c3f9fb22264ac56c7fda2e2c9
|
7
|
+
data.tar.gz: 91d022c2ebacf26a18bdb8d1667ae886d0a91d709d1bacf214d9ed96e65c36d43e05ef75a0240540b40d138d51707fd0d55167f28725ec62940ae36d7fb961fd
|
data/lib/spaceship/client.rb
CHANGED
@@ -39,6 +39,9 @@ module Spaceship
|
|
39
39
|
# Raised when 302 is received from portal request
|
40
40
|
class AppleTimeoutError < StandardError; end
|
41
41
|
|
42
|
+
# Raised when 401 is received from portal request
|
43
|
+
class UnauthorizedAccessError < StandardError; end
|
44
|
+
|
42
45
|
# Authenticates with Apple's web services. This method has to be called once
|
43
46
|
# to generate a valid session. The session will automatically be used from then
|
44
47
|
# on.
|
@@ -66,8 +69,14 @@ module Spaceship
|
|
66
69
|
end
|
67
70
|
|
68
71
|
def initialize
|
72
|
+
options = {
|
73
|
+
request: {
|
74
|
+
timeout: 300,
|
75
|
+
open_timeout: 300
|
76
|
+
}
|
77
|
+
}
|
69
78
|
@cookie = HTTP::CookieJar.new
|
70
|
-
@client = Faraday.new(self.class.hostname) do |c|
|
79
|
+
@client = Faraday.new(self.class.hostname, options) do |c|
|
71
80
|
c.response :json, content_type: /\bjson$/
|
72
81
|
c.response :xml, content_type: /\bxml$/
|
73
82
|
c.response :plist, content_type: /\bplist$/
|
@@ -168,9 +177,9 @@ module Spaceship
|
|
168
177
|
end
|
169
178
|
|
170
179
|
self.user = user
|
171
|
-
|
180
|
+
@password = password
|
172
181
|
begin
|
173
|
-
|
182
|
+
do_login(user, password)
|
174
183
|
rescue InvalidUserCredentialsError => ex
|
175
184
|
raise ex unless keychain_entry
|
176
185
|
|
@@ -182,20 +191,36 @@ module Spaceship
|
|
182
191
|
end
|
183
192
|
end
|
184
193
|
|
185
|
-
def with_retry(tries = 5, &
|
186
|
-
return
|
187
|
-
rescue Faraday::Error::TimeoutError, AppleTimeoutError => ex # New Faraday version: Faraday::TimeoutError => ex
|
194
|
+
def with_retry(tries = 5, &_block)
|
195
|
+
return yield
|
196
|
+
rescue Faraday::Error::ConnectionFailed, Faraday::Error::TimeoutError, AppleTimeoutError => ex # New Faraday version: Faraday::TimeoutError => ex
|
188
197
|
unless (tries -= 1).zero?
|
189
198
|
logger.warn("Timeout received: '#{ex.message}'. Retrying after 3 seconds (remaining: #{tries})...")
|
190
|
-
sleep 3
|
199
|
+
sleep 3 unless defined? SpecHelper
|
200
|
+
retry
|
201
|
+
end
|
202
|
+
raise ex # re-raise the exception
|
203
|
+
rescue UnauthorizedAccessError => ex
|
204
|
+
if @loggedin
|
205
|
+
msg = "Auth error received: '#{ex.message}'. Login in again then retrying after 3 seconds (remaining: #{tries})..."
|
206
|
+
puts msg if $verbose
|
207
|
+
logger.warn msg
|
208
|
+
do_login(self.user, @password)
|
209
|
+
sleep 3 unless defined? SpecHelper
|
191
210
|
retry
|
192
211
|
end
|
193
|
-
|
194
212
|
raise ex # re-raise the exception
|
195
213
|
end
|
196
214
|
|
197
215
|
private
|
198
216
|
|
217
|
+
def do_login(user, password)
|
218
|
+
@loggedin = false
|
219
|
+
ret = send_login_request(user, password) # different in subclasses
|
220
|
+
@loggedin = true
|
221
|
+
ret
|
222
|
+
end
|
223
|
+
|
199
224
|
# Is called from `parse_response` to store the latest csrf_token (if available)
|
200
225
|
def store_csrf_tokens(response)
|
201
226
|
if response and response.headers
|
@@ -238,11 +263,11 @@ module Spaceship
|
|
238
263
|
params_to_log = params_to_log.collect do |key, value|
|
239
264
|
"{#{key}: #{value}}"
|
240
265
|
end
|
241
|
-
logger.info("#{method.upcase}: #{url} #{params_to_log.join(', ')}")
|
266
|
+
logger.info(">> #{method.upcase}: #{url} #{params_to_log.join(', ')}")
|
242
267
|
end
|
243
268
|
|
244
269
|
def log_response(method, url, response)
|
245
|
-
logger.debug("#{method.upcase}: #{url}: #{response.body}")
|
270
|
+
logger.debug("<< #{method.upcase}: #{url}: #{response.body}")
|
246
271
|
end
|
247
272
|
|
248
273
|
# Actually sends the request to the remote server
|
@@ -250,6 +275,13 @@ module Spaceship
|
|
250
275
|
def send_request(method, url_or_path, params, headers, &block)
|
251
276
|
with_retry do
|
252
277
|
response = @client.send(method, url_or_path, params, headers, &block)
|
278
|
+
resp_hash = response.to_hash
|
279
|
+
if resp_hash[:status] == 401
|
280
|
+
msg = "Auth lost"
|
281
|
+
logger.warn msg
|
282
|
+
raise UnauthorizedAccessError.new, "Unauthorized Access"
|
283
|
+
end
|
284
|
+
|
253
285
|
if response.body.to_s.include?("<title>302 Found</title>")
|
254
286
|
raise AppleTimeoutError.new, "Apple 302 detected"
|
255
287
|
end
|
@@ -5,6 +5,10 @@ module Spaceship
|
|
5
5
|
class ITunesConnectError < StandardError
|
6
6
|
end
|
7
7
|
|
8
|
+
# raised if the server failed to save temporarily
|
9
|
+
class ITunesConnectTemporaryError < ITunesConnectError
|
10
|
+
end
|
11
|
+
|
8
12
|
attr_reader :du_client
|
9
13
|
|
10
14
|
def initialize
|
@@ -120,18 +124,24 @@ module Spaceship
|
|
120
124
|
end
|
121
125
|
|
122
126
|
def send_login_request(user, password)
|
127
|
+
clear_user_cached_data
|
128
|
+
|
123
129
|
data = {
|
124
130
|
accountName: user,
|
125
131
|
password: password,
|
126
132
|
rememberMe: true
|
127
133
|
}
|
128
134
|
|
129
|
-
|
130
|
-
req
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
+
begin
|
136
|
+
response = request(:post) do |req|
|
137
|
+
req.url "https://idmsa.apple.com/appleauth/auth/signin?widgetKey=#{service_key}"
|
138
|
+
req.body = data.to_json
|
139
|
+
req.headers['Content-Type'] = 'application/json'
|
140
|
+
req.headers['X-Requested-With'] = 'XMLHttpRequest'
|
141
|
+
req.headers['Accept'] = 'application/json, text/javascript'
|
142
|
+
end
|
143
|
+
rescue UnauthorizedAccessError
|
144
|
+
raise InvalidUserCredentialsError.new, "Invalid username and password combination. Used '#{user}' as the username."
|
135
145
|
end
|
136
146
|
|
137
147
|
# get woinst, wois, and itctx cookie values
|
@@ -139,7 +149,7 @@ module Spaceship
|
|
139
149
|
request(:get, "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa")
|
140
150
|
|
141
151
|
case response.status
|
142
|
-
when 403
|
152
|
+
when 403
|
143
153
|
raise InvalidUserCredentialsError.new, "Invalid username and password combination. Used '#{user}' as the username."
|
144
154
|
when 200
|
145
155
|
return response
|
@@ -203,6 +213,8 @@ module Spaceship
|
|
203
213
|
if errors.count > 0 # they are separated by `.` by default
|
204
214
|
if errors.count == 1 and errors.first == "You haven't made any changes."
|
205
215
|
# This is a special error which we really don't care about
|
216
|
+
elsif errors.count == 1 and errors.first.include?("try again later")
|
217
|
+
raise ITunesConnectTemporaryError.new, errors.first
|
206
218
|
else
|
207
219
|
raise ITunesConnectError.new, errors.join(' ')
|
208
220
|
end
|
@@ -338,13 +350,15 @@ module Spaceship
|
|
338
350
|
raise "app_id is required" unless app_id
|
339
351
|
raise "version_id is required" unless version_id.to_i > 0
|
340
352
|
|
341
|
-
|
342
|
-
req
|
343
|
-
|
344
|
-
|
345
|
-
|
353
|
+
with_tunes_retry do
|
354
|
+
r = request(:post) do |req|
|
355
|
+
req.url "ra/apps/#{app_id}/platforms/ios/versions/#{version_id}"
|
356
|
+
req.body = data.to_json
|
357
|
+
req.headers['Content-Type'] = 'application/json'
|
358
|
+
end
|
346
359
|
|
347
|
-
|
360
|
+
handle_itc_response(r.body)
|
361
|
+
end
|
348
362
|
end
|
349
363
|
|
350
364
|
#####################################################
|
@@ -780,19 +794,38 @@ module Spaceship
|
|
780
794
|
|
781
795
|
private
|
782
796
|
|
797
|
+
def with_tunes_retry(tries = 5, &_block)
|
798
|
+
return yield
|
799
|
+
rescue Spaceship::TunesClient::ITunesConnectTemporaryError => ex
|
800
|
+
unless (tries -= 1).zero?
|
801
|
+
msg = "ITC temporary save error received: '#{ex.message}'. Retrying after 60 seconds (remaining: #{tries})..."
|
802
|
+
puts msg
|
803
|
+
logger.warn msg
|
804
|
+
sleep 60 unless defined? SpecHelper # unless FastlaneCore::Helper.is_test?
|
805
|
+
retry
|
806
|
+
end
|
807
|
+
raise ex # re-raise the exception
|
808
|
+
end
|
809
|
+
|
810
|
+
def clear_user_cached_data
|
811
|
+
@content_provider_id = nil
|
812
|
+
@sso_token_for_image = nil
|
813
|
+
@sso_token_for_video = nil
|
814
|
+
end
|
815
|
+
|
783
816
|
# the contentProviderIr found in the UserDetail instance
|
784
817
|
def content_provider_id
|
785
|
-
user_detail_data.content_provider_id
|
818
|
+
@content_provider_id ||= user_detail_data.content_provider_id
|
786
819
|
end
|
787
820
|
|
788
821
|
# the ssoTokenForImage found in the AppVersionRef instance
|
789
822
|
def sso_token_for_image
|
790
|
-
ref_data.sso_token_for_image
|
823
|
+
@sso_token_for_image ||= ref_data.sso_token_for_image
|
791
824
|
end
|
792
825
|
|
793
826
|
# the ssoTokenForVideo found in the AppVersionRef instance
|
794
827
|
def sso_token_for_video
|
795
|
-
ref_data.sso_token_for_video
|
828
|
+
@sso_token_for_video ||= ref_data.sso_token_for_video
|
796
829
|
end
|
797
830
|
|
798
831
|
def update_tester_from_app!(tester, app_id, testing)
|
data/lib/spaceship/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spaceship
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.21.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felix Krause
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-02-
|
12
|
+
date: 2016-02-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: credentials_manager
|