spaceship 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5874fb36abe1aa100b7c5b793a291699ca11568d
4
- data.tar.gz: 43449a997428f3e6bddc8eda4e67f94e50781354
3
+ metadata.gz: 904794a304cacd104b57a5dfdc757a9daaa73154
4
+ data.tar.gz: c73073f31e7b3d3b7385fc1e864cf9944ef55583
5
5
  SHA512:
6
- metadata.gz: 7aec5cec146a3ee90077d67a2c0efba4c3ae03a6d9000f0aa36bbf7a763cc02f33f821257d782d83751ec1150050690b21aa98d2d235ee002e177ec1873b97b8
7
- data.tar.gz: 7f54d76361cc18e52b826fdd40f1542c5623823b83dddb7321d140b5d63d59caf3c5aa119ddc90b81e12f413ef09036dfa901b97882d217376fd0a8a401b6688
6
+ metadata.gz: da46f269738c9ed37cf56fa1c4c5ae8ba491eb9c3eedef6c59415d492b0defb7819df981091666cadd328d84aea67bccb8c6a21d7104e17a1c2395aa000ad6fb
7
+ data.tar.gz: a8e15b850a1fca1cdbb565a988b51bf9fbb503ed9d6fc911bd4f09032f234971d1cc4513b82b3ee2d845bd5d68f1e3e3a310dad05d6e8b0f8f3dd8169b9f7661
@@ -162,6 +162,8 @@ module Spaceship
162
162
  Tunes::BuildTrain.all(self, self.apple_id)
163
163
  end
164
164
 
165
+ # @return [Array] A list of all pre-processing builds
166
+ # These are all build that have no information except the upload date
165
167
  def pre_processing_builds
166
168
  data = client.build_trains(apple_id) # we need to fetch all trains here to get the builds
167
169
 
@@ -171,6 +173,33 @@ module Spaceship
171
173
  end
172
174
  end
173
175
 
176
+ # @return [Array] This will return an array of *all* processing builds
177
+ # this include pre-processing or standard processing
178
+ def all_processing_builds
179
+ builds = self.pre_processing_builds
180
+
181
+ self.build_trains.each do |version_number, train|
182
+ train.processing_builds.each do |build|
183
+ builds << build
184
+ end
185
+ end
186
+
187
+ return builds
188
+ end
189
+
190
+ # Get all builds that are already processed for all build trains
191
+ # You can either use the return value (array) or pass a block
192
+ def builds
193
+ all_builds = []
194
+ self.build_trains.each do |version_number, train|
195
+ train.builds.each do |build|
196
+ yield(build) if block_given?
197
+ all_builds << build unless block_given?
198
+ end
199
+ end
200
+ all_builds
201
+ end
202
+
174
203
  #####################################################
175
204
  # @!group Submit for Review
176
205
  #####################################################
@@ -184,6 +213,18 @@ module Spaceship
184
213
  Spaceship::AppSubmission.create(self, self.apple_id, version)
185
214
  end
186
215
 
216
+ # Cancels all ongoing TestFlight beta submission for this application
217
+ def cancel_all_testflight_submissions!
218
+ self.builds do |build|
219
+ begin
220
+ build.cancel_beta_review!
221
+ rescue => ex
222
+ # We really don't care about any errors here
223
+ end
224
+ end
225
+ true
226
+ end
227
+
187
228
  #####################################################
188
229
  # @!group General
189
230
  #####################################################
@@ -7,7 +7,7 @@ module Spaceship
7
7
  # @!group General metadata
8
8
  #####################################################
9
9
 
10
- # @return (Spaceship::Tunes::Application) A reference to the build train this build is contained in
10
+ # @return (Spaceship::Tunes::BuildTrain) A reference to the build train this build is contained in
11
11
  attr_accessor :build_train
12
12
 
13
13
  # @return (Integer) The ID generated by iTunes Connect
@@ -16,7 +16,7 @@ module Spaceship
16
16
  # @return (Boolean)
17
17
  attr_accessor :valid
18
18
 
19
- # @return (String) The build version (not the version number)
19
+ # @return (String) The build version (not the version number), but also is named `build number`
20
20
  attr_accessor :build_version
21
21
 
22
22
  # @return (String) The version number (e.g. 1.3)
@@ -28,7 +28,7 @@ module Spaceship
28
28
  # @return (String) URL to the app icon of this build (150x150px)
29
29
  attr_accessor :icon_url
30
30
 
31
- # @return (String)
31
+ # @return (String) The name of the app this build is for
32
32
  attr_accessor :app_name
33
33
 
34
34
  # @return (String) The platform of this build (e.g. 'ios')
@@ -104,6 +104,65 @@ module Spaceship
104
104
 
105
105
  @external_testing_enabled = (self.external_expiry_date || 0) > 0
106
106
  end
107
+
108
+ # This will submit this build for TestFlight beta review
109
+ # @param metadata [Hash] A hash containing the following information (keys must be symbols):
110
+ # {
111
+ # # Required Metadata:
112
+ # changelog: "Changelog",
113
+ # description: "Your Description",
114
+ # feedback_email: "Email Address for Feedback",
115
+ # marketing_url: "https://marketing.com",
116
+ # first_name: "Felix",
117
+ # last_name: "Krause",
118
+ # review_email: "Contact email address for Apple",
119
+ # phone_number: "0128383383",
120
+ #
121
+ # # Optional Metadata:
122
+ # privacy_policy_url: nil,
123
+ # review_notes: nil,
124
+ # review_user_name: nil,
125
+ # review_password: nil,
126
+ # encryption: false
127
+ # }
128
+ def submit_for_beta_review!(metadata)
129
+ # First, enable beta testing for this train (per iTC requirement)
130
+ self.build_train.update_testing_status!(true)
131
+
132
+ parameters = {
133
+ app_id: self.build_train.application.apple_id,
134
+ train: self.build_train.version_string,
135
+ build_number: self.build_version,
136
+
137
+ # Required Metadata:
138
+ changelog: "No changelog provided",
139
+ description: "No app description provided",
140
+ feedback_email: "contact@company.com",
141
+ marketing_url: "http://marketing.com",
142
+ first_name: "Felix",
143
+ last_name: "Krause",
144
+ review_email: "contact@company.com",
145
+ phone_number: "0123456789",
146
+
147
+ # Optional Metadata:
148
+ privacy_policy_url: nil,
149
+ review_notes: nil,
150
+ review_user_name: nil,
151
+ review_password: nil,
152
+ encryption: false
153
+ }.merge(metadata)
154
+
155
+ client.submit_testflight_build_for_review!(parameters)
156
+
157
+ return parameters
158
+ end
159
+
160
+ # This will cancel the review process for this TestFlight build
161
+ def cancel_beta_review!
162
+ client.remove_testflight_build_from_review!(app_id: self.build_train.application.apple_id,
163
+ train: self.build_train.version_string,
164
+ build_number: self.build_version)
165
+ end
107
166
  end
108
167
  end
109
168
  end
@@ -32,12 +32,31 @@ module Spaceship
32
32
  # }]
33
33
  attr_accessor :devices
34
34
 
35
+
36
+ # Information about the most recent beta install
37
+ # @return [Integer] The ID of the most recently installed app
38
+ attr_accessor :latest_install_app_id
39
+
40
+ # @return [Integer] Date of the last install of this tester
41
+ # Number of seconds since 1970
42
+ attr_accessor :latest_install_date
43
+
44
+ # @return [Integer] The build number of the last installed build
45
+ attr_accessor :latest_installed_build_number
46
+
47
+ # @return [Integer] The version number of the last installed build
48
+ attr_accessor :latest_installed_version_number
49
+
35
50
  attr_mapping(
36
51
  'testerId' => :tester_id,
37
52
  'emailAddress.value' => :email,
38
53
  'firstName.value' => :first_name,
39
54
  'lastName.value' => :last_name,
40
- 'devices' => :devices
55
+ 'devices' => :devices,
56
+ 'latestInstalledAppAdamId' => :latest_install_app_id,
57
+ 'latestInstalledDate' => :latest_install_date,
58
+ 'latestInstalledVersion' => :latest_installed_version_number,
59
+ 'latestInstalledShortVersion' => :latest_installed_build_number,
41
60
  )
42
61
 
43
62
  class << self
@@ -1,6 +1,10 @@
1
1
  module Spaceship
2
2
  class TunesClient < Spaceship::Client
3
3
 
4
+ # ITunesConnectError is only thrown when iTunes Connect raises an exception
5
+ class ITunesConnectError < StandardError
6
+ end
7
+
4
8
  #####################################################
5
9
  # @!group Init and Login
6
10
  #####################################################
@@ -65,9 +69,11 @@ module Spaceship
65
69
  end
66
70
  end
67
71
 
68
- def handle_itc_response(data)
69
- return unless data
70
- return unless data.kind_of?Hash
72
+ def handle_itc_response(raw)
73
+ return unless raw
74
+ return unless raw.kind_of?Hash
75
+
76
+ data = raw['data'] || raw # sometimes it's with data, sometimes it isn't
71
77
 
72
78
  if data.fetch('sectionErrorKeys', []).count == 0 and
73
79
  data.fetch('sectionInfoKeys', []).count == 0 and
@@ -100,10 +106,13 @@ module Spaceship
100
106
  errors = errors + data.fetch('sectionErrorKeys') if data['sectionErrorKeys']
101
107
 
102
108
  # Sometimes there is a different kind of error in the JSON response
103
- different_error = data.fetch('messages', {}).fetch('error', nil)
109
+ # e.g. {"warn"=>nil, "error"=>["operation_failed"], "info"=>nil}
110
+ different_error = raw.fetch('messages', {}).fetch('error', nil)
104
111
  errors << different_error if different_error
105
112
 
106
- raise errors.join(' ') if errors.count > 0 # they are separated by `.` by default
113
+ if errors.count > 0 # they are separated by `.` by default
114
+ raise ITunesConnectError.new(errors.join(' '))
115
+ end
107
116
 
108
117
  puts data['sectionInfoKeys'] if data['sectionInfoKeys']
109
118
  puts data['sectionWarningKeys'] if data['sectionWarningKeys']
@@ -194,7 +203,7 @@ module Spaceship
194
203
  req.headers['Content-Type'] = 'application/json'
195
204
  end
196
205
 
197
- handle_itc_response(r.body['data'])
206
+ handle_itc_response(r.body)
198
207
  end
199
208
 
200
209
  #####################################################
@@ -217,7 +226,88 @@ module Spaceship
217
226
  req.headers['Content-Type'] = 'application/json'
218
227
  end
219
228
 
220
- handle_itc_response(r.body['data'])
229
+ handle_itc_response(r.body)
230
+ end
231
+
232
+ def remove_testflight_build_from_review!(app_id: nil, train: nil, build_number: nil)
233
+ r = request(:post) do |req|
234
+ req.url "ra/apps/#{app_id}/trains/#{train}/builds/#{build_number}/reject"
235
+ req.body = {}.to_json
236
+ req.headers['Content-Type'] = 'application/json'
237
+ end
238
+ handle_itc_response(r.body)
239
+ end
240
+
241
+ def submit_testflight_build_for_review!(# Required:
242
+ app_id: nil,
243
+ train: nil,
244
+ build_number: nil,
245
+ cancel_other_submissions: false,
246
+
247
+ # Required Metadata:
248
+ changelog: nil,
249
+ description: nil,
250
+ feedback_email: nil,
251
+ marketing_url: nil,
252
+ first_name: nil,
253
+ last_name: nil,
254
+ review_email: nil,
255
+ phone_number: nil,
256
+
257
+ # Optional Metadata:
258
+ privacy_policy_url: nil,
259
+ review_notes: nil,
260
+ review_user_name: nil,
261
+ review_password: nil,
262
+ encryption: false)
263
+
264
+ start_url = "ra/apps/#{app_id}/trains/#{train}/builds/#{build_number}/submit/start"
265
+ r = request(:get) do |req|
266
+ req.url start_url
267
+ req.headers['Content-Type'] = 'application/json'
268
+ end
269
+ handle_itc_response(r.body)
270
+
271
+ build_info = r.body['data']
272
+ # Now fill in the values provided by the user
273
+
274
+ # First the localised values:
275
+ build_info['testInfo']['details'].each do |current|
276
+ current['whatsNew']['value'] = changelog
277
+ current['description']['value'] = description
278
+ current['feedbackEmail']['value'] = feedback_email
279
+ current['marketingUrl']['value'] = marketing_url
280
+ current['privacyPolicyUrl']['value'] = privacy_policy_url
281
+ current["pageLanguageValue"] = current['language'] # could iTunes Connect be any more buggy? This is required for some reason
282
+ end
283
+ build_info['testInfo']['reviewFirstName']['value'] = first_name
284
+ build_info['testInfo']['reviewLastName']['value'] = last_name
285
+ build_info['testInfo']['reviewPhone']['value'] = phone_number
286
+ build_info['testInfo']['reviewEmail']['value'] = review_email
287
+ build_info['testInfo']['reviewUserName']['value'] = review_user_name
288
+ build_info['testInfo']['reviewPassword']['value'] = review_password
289
+
290
+ r = request(:post) do |req| # same URL, but a POST request
291
+ req.url start_url
292
+ req.body = build_info.to_json
293
+ req.headers['Content-Type'] = 'application/json'
294
+ end
295
+ handle_itc_response(r.body)
296
+
297
+ encryption_info = r.body['data']
298
+ if encryption_info['exportComplianceRequired']
299
+ # only sometimes this is required
300
+
301
+ encryption_info['usesEncryption']['value'] = encryption
302
+
303
+ r = request(:post) do |req|
304
+ req.url "ra/apps/#{app_id}/trains/#{train}/builds/#{build_number}/submit/complete"
305
+ req.body = encryption_info.to_json
306
+ req.headers['Content-Type'] = 'application/json'
307
+ end
308
+
309
+ handle_itc_response(r.body)
310
+ end
221
311
  end
222
312
 
223
313
  #####################################################
@@ -233,7 +323,7 @@ module Spaceship
233
323
  req.headers['Content-Type'] = 'application/json'
234
324
  end
235
325
 
236
- handle_itc_response(r.body['data'])
326
+ handle_itc_response(r.body)
237
327
  parse_response(r, 'data')
238
328
  end
239
329
 
@@ -310,7 +400,8 @@ module Spaceship
310
400
  },
311
401
  testing: {
312
402
  value: false
313
- },
403
+ },
404
+ userName: tester.email,
314
405
  testerId: tester.tester_id
315
406
  }
316
407
  ]
@@ -1,3 +1,3 @@
1
1
  module Spaceship
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
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.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Natchev
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-18 00:00:00.000000000 Z
12
+ date: 2015-07-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: credentials_manager