spaceship 0.6.1 → 0.7.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: 046dcf3de83d63e9e9d4feaeda5b09d8b409db1d
4
- data.tar.gz: fb112b2b56de7ac46c9f8e866a99df53f4bafe24
3
+ metadata.gz: cb67ea61ddcb8fc09c87de04eb400be6a4c0c9e2
4
+ data.tar.gz: c62c7bc6307daf12b7dd9a890c30241e633ec02c
5
5
  SHA512:
6
- metadata.gz: a3eefd3ccd0cdbce93caaa729e1286ad10c7975ec08925b7c99e419ccd7d1d3dfe8c3f77bcd75d492f66b2a568891518ecc96277a91217e06bdc865824e45ee8
7
- data.tar.gz: eefe43691c442b18bb53c990de69ebe28f876803bcbb010a492edf4e9d7893895fa6666039d368415a861c9359ac12d6f57f2b15a7ca678e5d0b3581e3d6708a
6
+ metadata.gz: 86c17cf18e9949250db8d312822188f2896ba4beff339fd949d876fc0e9bd4c2b017d58dc18bcade5a831682ab8f84cddcdd3d640cbf1fe4b2d22b33d7e7cb38
7
+ data.tar.gz: bd449519839313194d8128f72b6f1fa74f4a89b03293f35b33b692cf5e638d1014f03ccc01db8fb1dd73db8270dc4a77c5559f52f6f8182725f60ffa442766a7
data/lib/spaceship.rb CHANGED
@@ -10,7 +10,6 @@ require 'spaceship/portal/spaceship'
10
10
  # iTunes Connect
11
11
  require 'spaceship/tunes/tunes'
12
12
  require 'spaceship/tunes/spaceship'
13
- require 'spaceship/tunes/tester'
14
13
 
15
14
  # To support legacy code
16
15
  module Spaceship
@@ -45,7 +45,9 @@ module Spaceship
45
45
  end
46
46
 
47
47
  def to_json
48
- @hash.to_json
48
+ h = @hash.dup
49
+ h.delete(:application)
50
+ h.to_json
49
51
  end
50
52
  end
51
53
 
@@ -0,0 +1,107 @@
1
+ module Spaceship
2
+ module Tunes
3
+ class AppDetails < TunesBase
4
+ attr_accessor :application
5
+
6
+ ####
7
+ # Localized values
8
+ ####
9
+
10
+ # @return (Array) Raw access the all available languages. You shouldn't use it probbaly
11
+ attr_accessor :languages
12
+
13
+ # @return (Hash) A hash representing the app name in all languages
14
+ attr_reader :name
15
+
16
+ # @return (Hash) A hash representing the keywords in all languages
17
+ attr_reader :privacy_url
18
+
19
+ # Categories (e.g. MZGenre.Business)
20
+ attr_accessor :primary_category
21
+
22
+ attr_accessor :primary_first_sub_category
23
+
24
+ attr_accessor :primary_second_sub_category
25
+
26
+ attr_accessor :secondary_category
27
+
28
+ attr_accessor :secondary_first_sub_category
29
+
30
+ attr_accessor :secondary_second_sub_category
31
+
32
+ attr_mapping(
33
+ 'localizedMetadata.value' => :languages,
34
+ 'primaryCategory.value' => :primary_category,
35
+ 'primaryFirstSubCategory.value' => :primary_first_sub_category,
36
+ 'primarySecondSubCategory.value' => :primary_second_sub_category,
37
+ 'secondaryCategory.value' => :secondary_category,
38
+ 'secondaryFirstSubCategory.value' => :secondary_first_sub_category,
39
+ 'secondarySecondSubCategory.value' => :secondary_second_sub_category
40
+ )
41
+
42
+ class << self
43
+ # Create a new object based on a hash.
44
+ # This is used to create a new object based on the server response.
45
+ def factory(attrs)
46
+ obj = self.new(attrs)
47
+ obj.unfold_languages
48
+
49
+ return obj
50
+ end
51
+ end
52
+
53
+ # Prefill name, privacy url
54
+ def unfold_languages
55
+ {
56
+ name: :name,
57
+ privacyPolicyUrl: :privacy_url
58
+ }.each do |json, attribute|
59
+ instance_variable_set("@#{attribute}".to_sym, LanguageItem.new(json, languages))
60
+ end
61
+ end
62
+
63
+ # Push all changes that were made back to iTunes Connect
64
+ def save!
65
+ client.update_app_details!(application.apple_id, raw_data)
66
+ end
67
+
68
+ # Custom Setters
69
+ #
70
+ def primary_category=(value)
71
+ value = "MZGenre.#{value}" unless value.include? "MZGenre"
72
+ super(value)
73
+ end
74
+
75
+ def primary_first_sub_category=(value)
76
+ value = "MZGenre.#{value}" unless value.include? "MZGenre"
77
+ super(value)
78
+ end
79
+
80
+ def primary_second_sub_category=(value)
81
+ value = "MZGenre.#{value}" unless value.include? "MZGenre"
82
+ super(value)
83
+ end
84
+
85
+ def secondary_category=(value)
86
+ value = "MZGenre.#{value}" unless value.include? "MZGenre"
87
+ super(value)
88
+ end
89
+
90
+ def secondary_first_sub_category=(value)
91
+ value = "MZGenre.#{value}" unless value.include? "MZGenre"
92
+ super(value)
93
+ end
94
+
95
+ def secondary_second_sub_category=(value)
96
+ value = "MZGenre.#{value}" unless value.include? "MZGenre"
97
+ super(value)
98
+ end
99
+
100
+ #####################################################
101
+ # @!group General
102
+ #####################################################
103
+ def setup
104
+ end
105
+ end
106
+ end
107
+ end
@@ -20,19 +20,6 @@ module Spaceship
20
20
  # @return (Bool) Is that the version that's currently available in the App Store?
21
21
  attr_accessor :is_live
22
22
 
23
- # Categories (e.g. MZGenre.Business)
24
- attr_accessor :primary_category
25
-
26
- attr_accessor :primary_first_sub_category
27
-
28
- attr_accessor :primary_second_sub_category
29
-
30
- attr_accessor :secondary_category
31
-
32
- attr_accessor :secondary_first_sub_category
33
-
34
- attr_accessor :secondary_second_sub_category
35
-
36
23
  # @return (String) App Status (e.g. 'readyForSale'). You should use `app_status` instead
37
24
  attr_accessor :raw_status
38
25
 
@@ -100,9 +87,6 @@ module Spaceship
100
87
  # @return (Array) Raw access the all available languages. You shouldn't use it probbaly
101
88
  attr_accessor :languages
102
89
 
103
- # @return (Hash) A hash representing the app name in all languages
104
- attr_reader :name
105
-
106
90
  # @return (Hash) A hash representing the keywords in all languages
107
91
  attr_reader :keywords
108
92
 
@@ -112,9 +96,6 @@ module Spaceship
112
96
  # @return (Hash) The changelog
113
97
  attr_reader :release_notes
114
98
 
115
- # @return (Hash) A hash representing the keywords in all languages
116
- attr_reader :privacy_url
117
-
118
99
  # @return (Hash) A hash representing the keywords in all languages
119
100
  attr_reader :support_url
120
101
 
@@ -133,13 +114,7 @@ module Spaceship
133
114
  'details.value' => :languages,
134
115
  'largeAppIcon.value.originalFileName' => :app_icon_original_name,
135
116
  'largeAppIcon.value.url' => :app_icon_url,
136
- 'primaryCategory.value' => :primary_category,
137
- 'primaryFirstSubCategory.value' => :primary_first_sub_category,
138
- 'primarySecondSubCategory.value' => :primary_second_sub_category,
139
117
  'releaseOnApproval.value' => :release_on_approval,
140
- 'secondaryCategory.value' => :secondary_category,
141
- 'secondaryFirstSubCategory.value' => :secondary_first_sub_category,
142
- 'secondarySecondSubCategory.value' => :secondary_second_sub_category,
143
118
  'status' => :raw_status,
144
119
  'supportsAppleWatch' => :supports_apple_watch,
145
120
  'versionId' => :version_id,
@@ -169,9 +144,10 @@ module Spaceship
169
144
 
170
145
  # @param application (Spaceship::Tunes::Application) The app this version is for
171
146
  # @param app_id (String) The unique Apple ID of this app
172
- # @param is_live (Boolean) Is that the version that's live in the App Store?
173
- def find(application, app_id, is_live = false)
147
+ # @param is_live (Boolean)
148
+ def find(application, app_id, is_live)
174
149
  attrs = client.app_version(app_id, is_live)
150
+ return nil unless attrs
175
151
  attrs.merge!(application: application)
176
152
  attrs.merge!(is_live: is_live)
177
153
 
@@ -226,7 +202,9 @@ module Spaceship
226
202
 
227
203
  # @return (String) An URL to this specific resource. You can enter this URL into your browser
228
204
  def url
229
- "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/#{self.application.apple_id}/" + (self.is_live? ? "cur" : "")
205
+ url = "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/904332168/ios/versioninfo/"
206
+ url += "deliverable" if self.is_live?
207
+ return url
230
208
  end
231
209
 
232
210
  # Private methods
@@ -246,10 +224,8 @@ module Spaceship
246
224
  # Prefill name, keywords, etc...
247
225
  def unfold_languages
248
226
  {
249
- name: :name,
250
227
  keywords: :keywords,
251
228
  description: :description,
252
- privacyURL: :privacy_url,
253
229
  supportURL: :support_url,
254
230
  marketingURL: :marketing_url,
255
231
  releaseNotes: :release_notes
@@ -268,36 +244,6 @@ module Spaceship
268
244
  !super.nil?
269
245
  end
270
246
 
271
- def primary_category=(value)
272
- value = "MZGenre.#{value}" unless value.include? "MZGenre"
273
- super(value)
274
- end
275
-
276
- def primary_first_sub_category=(value)
277
- value = "MZGenre.#{value}" unless value.include? "MZGenre"
278
- super(value)
279
- end
280
-
281
- def primary_second_sub_category=(value)
282
- value = "MZGenre.#{value}" unless value.include? "MZGenre"
283
- super(value)
284
- end
285
-
286
- def secondary_category=(value)
287
- value = "MZGenre.#{value}" unless value.include? "MZGenre"
288
- super(value)
289
- end
290
-
291
- def secondary_first_sub_category=(value)
292
- value = "MZGenre.#{value}" unless value.include? "MZGenre"
293
- super(value)
294
- end
295
-
296
- def secondary_second_sub_category=(value)
297
- value = "MZGenre.#{value}" unless value.include? "MZGenre"
298
- super(value)
299
- end
300
-
301
247
  private
302
248
 
303
249
  # generates the nested data structure to represent screenshots
@@ -55,7 +55,7 @@ module Spaceship
55
55
  # Create a new object based on a hash.
56
56
  # This is used to create a new object based on the server response.
57
57
  def factory(attrs)
58
- self.new(attrs)
58
+ return self.new(attrs)
59
59
  end
60
60
 
61
61
  # @return (Array) Returns all apps available for this account
@@ -101,16 +101,24 @@ module Spaceship
101
101
  # @return (Spaceship::AppVersion) Receive the version that is currently live on the
102
102
  # App Store. You can't modify all values there, so be careful.
103
103
  def live_version
104
+ if raw_data['versions'].count == 1
105
+ v = raw_data['versions'].last
106
+ if ['Prepare for Upload', 'prepareForUpload'].include?(v['state']) # this only applies for the initial version
107
+ return nil
108
+ end
109
+ end
110
+
104
111
  Spaceship::AppVersion.find(self, self.apple_id, true)
105
112
  end
106
113
 
107
114
  # @return (Spaceship::AppVersion) Receive the version that can fully be edited
108
115
  def edit_version
109
- # Apple's server will respond with the same version if there is only one, for both v=live and v=
110
- # That's why we have to check in the app_summary.json request if there are 2 versions or just one
111
- # if there is only one version, we'll return nil
112
116
  if raw_data['versions'].count == 1
113
- return nil # only live version, user should create a new version
117
+ v = raw_data['versions'].last
118
+
119
+ unless ['Prepare for Upload', 'prepareForUpload'].include?(v['state']) # this only applies for the initial version
120
+ return nil # only live version, user should create a new version
121
+ end
114
122
  end
115
123
 
116
124
  Spaceship::AppVersion.find(self, self.apple_id, false)
@@ -134,6 +142,12 @@ module Spaceship
134
142
  client.get_resolution_center(apple_id)
135
143
  end
136
144
 
145
+ def details
146
+ attrs = client.app_details(apple_id)
147
+ attrs.merge!(application: self)
148
+ Tunes::AppDetails.factory(attrs)
149
+ end
150
+
137
151
  #####################################################
138
152
  # @!group Modifying
139
153
  #####################################################
@@ -165,7 +179,7 @@ module Spaceship
165
179
  # These are all build that have no information except the upload date
166
180
  # Those builds can also be the builds that are stuck on iTC.
167
181
  def pre_processing_builds
168
- data = client.build_trains(apple_id) # we need to fetch all trains here to get the builds
182
+ data = client.build_trains(apple_id, 'internal') # we need to fetch all trains here to get the builds
169
183
 
170
184
  builds = data.fetch('processingBuilds', []).collect do |attrs|
171
185
  attrs.merge!(build_train: self)
@@ -40,9 +40,11 @@ module Spaceship
40
40
  # @return (Integer): When is the external build going to expire?
41
41
  attr_accessor :external_expiry_date
42
42
 
43
- # @return (Boolean): Is this build available for external beta testing
44
- # this is only true after the build was approved by Apple
45
- attr_accessor :external_testing_enabled
43
+ # @return (Bool) Is external beta testing enabled for this train? Only one train can have enabled testing.
44
+ attr_reader :external_testing_enabled
45
+
46
+ # @return (Bool) Is internal beta testing enabled for this train? Only one train can have enabled testing.
47
+ attr_reader :internal_testing_enabled
46
48
 
47
49
  # @return (Bool) Does this build support WatchKit?
48
50
  attr_accessor :watch_kit_enabled
@@ -87,7 +89,9 @@ module Spaceship
87
89
  'internalExpiry' => :internal_expiry_date,
88
90
  'externalExpiry' => :external_expiry_date,
89
91
  'watchKitEnabled' => :watch_kit_enabled,
90
- 'readyToInstall' => :ready_to_install
92
+ 'readyToInstall' => :ready_to_install,
93
+ 'internalTesting.value' => :internal_testing_enabled,
94
+ 'externalTesting.value' => :external_testing_enabled
91
95
  )
92
96
 
93
97
  class << self
@@ -102,7 +106,7 @@ module Spaceship
102
106
  super
103
107
 
104
108
  self.external_expiry_date ||= 0
105
- @external_testing_enabled = self.external_expiry_date > 0
109
+ self.internal_expiry_date ||= 0
106
110
  end
107
111
 
108
112
  # This will submit this build for TestFlight beta review
@@ -127,7 +131,7 @@ module Spaceship
127
131
  # }
128
132
  def submit_for_beta_review!(metadata)
129
133
  # First, enable beta testing for this train (per iTC requirement)
130
- self.build_train.update_testing_status!(true)
134
+ self.build_train.update_testing_status!(true, 'external')
131
135
 
132
136
  parameters = {
133
137
  app_id: self.build_train.application.apple_id,
@@ -160,14 +164,8 @@ module Spaceship
160
164
  # @examples:
161
165
  # External, Internal, Inactive, Expired
162
166
  def testing_status
163
- testing ||= "External" if self.external_expiry_date > 0
164
-
165
- if self.build_train.testing_enabled
166
- # only the latest build is actually valid
167
- if self.build_train.builds.find_all { |b| b.upload_date > self.upload_date }.count == 0
168
- testing ||= "Internal"
169
- end
170
- end
167
+ testing ||= "External" if self.external_testing_enabled
168
+ testing ||= "Internal" if self.internal_testing_enabled
171
169
 
172
170
  if Time.at(self.internal_expiry_date / 1000) > Time.now
173
171
  testing ||= "Inactive"
@@ -188,36 +186,49 @@ module Spaceship
188
186
  end
189
187
  end
190
188
 
191
- # Example response
192
- # "buildVersion": "0.9.10",
193
- # "trainVersion": "0.9.10",
194
- # "uploadDate": 1413966436000,
195
- # "iconUrl": "https://is5-ssl.mzstatic.com/image/thumb/Newsstand5/v4/e8/ab/f8/e8abf8ca-6c22-a519-aa1b-c73901c4917e/Icon-60@2x.png.png/150x150bb-80.png",
196
- # "appName": "Yeahaa",
197
- # "platform": "ios",
198
- # "betaEntitled": false,
199
- # "id": 523299,
200
- # "valid": true,
201
- # "missingExportCompliance": false,
202
- # "waitingForExportComplianceApproval": false,
203
- # "addedInternalUsersCount": 0,
204
- # "addedExternalUsersCount": 0,
205
- # "invitedExternalUsersCount": 0,
206
- # "invitedInternalUsersCount": 0,
207
- # "acceptedInternalUsersCount": 0,
208
- # "acceptedExternalUsersCount": 0,
209
- # "installCount": 0,
210
- # "internalInstallCount": 0,
211
- # "externalInstallCount": 0,
212
- # "sessionCount": null,
213
- # "crashCount": null,
214
- # "promotedVersion": null,
215
- # "internalState": "noBetaEntitlement",
216
- # "betaState": "noBetaEntitlement",
217
- # "internalExpiry": 1416562036000,
218
- # "externalExpiry": 0,
219
- # "watchKitEnabled": false,
220
- # "readyToInstall": false,
221
- # "sdkBuildWhitelisted": true,
222
- # "internalTesting": null,
223
- # "externalTesting": null
189
+ # Example Response
190
+ # {"sectionErrorKeys"=>[],
191
+ # "sectionInfoKeys"=>[],
192
+ # "sectionWarningKeys"=>[],
193
+ # "buildVersion"=>"1",
194
+ # "trainVersion"=>"1.0",
195
+ # "uploadDate"=>1441975590000,
196
+ # "iconUrl"=>
197
+ # "https://is2-ssl.mzstatic.com/image/thumb/Newsstand3/v4/a9/f9/8b/a9f98b23-592d-af2e-6e10-a04873bed5df/Icon-76@2x.png.png/150x150bb-80.png",
198
+ # "iconAssetToken"=>
199
+ # "Newsstand3/v4/a9/f9/8b/a9f98b23-592d-af2e-6e10-a04873bed5df/Icon-76@2x.png.png",
200
+ # "appName"=>"Updated by fastlane",
201
+ # "platform"=>"ios",
202
+ # "betaEntitled"=>true,
203
+ # "exceededFileSizeLimit"=>false,
204
+ # "wentLiveWithVersion"=>false,
205
+ # "processing"=>false,
206
+ # "id"=>5298023,
207
+ # "valid"=>true,
208
+ # "missingExportCompliance"=>false,
209
+ # "waitingForExportComplianceApproval"=>false,
210
+ # "addedInternalUsersCount"=>0,
211
+ # "addedExternalUsersCount"=>0,
212
+ # "invitedExternalUsersCount"=>0,
213
+ # "invitedInternalUsersCount"=>0,
214
+ # "acceptedInternalUsersCount"=>1,
215
+ # "acceptedExternalUsersCount"=>0,
216
+ # "installCount"=>0,
217
+ # "internalInstallCount"=>0,
218
+ # "externalInstallCount"=>0,
219
+ # "sessionCount"=>0,
220
+ # "internalSessionCount"=>0,
221
+ # "externalSessionCount"=>0,
222
+ # "crashCount"=>0,
223
+ # "internalCrashCount"=>0,
224
+ # "externalCrashCount"=>0,
225
+ # "promotedVersion"=>nil,
226
+ # "internalState"=>"inactive",
227
+ # "betaState"=>"submitForReview",
228
+ # "internalExpiry"=>1444567590000,
229
+ # "externalExpiry"=>0,
230
+ # "watchKitEnabled"=>false,
231
+ # "readyToInstall"=>true,
232
+ # "sdkBuildWhitelisted"=>true,
233
+ # "internalTesting"=>{"value"=>false, "isEditable"=>true, "isRequired"=>false, "errorKeys"=>nil},
234
+ # "externalTesting"=>{"value"=>false, "isEditable"=>true, "isRequired"=>false, "errorKeys"=>nil}
@@ -17,8 +17,11 @@ module Spaceship
17
17
  # @return (String) Platform (e.g. "ios")
18
18
  attr_reader :platform
19
19
 
20
- # @return (Bool) Is beta testing enabled for this train? Only one train can have enabled testing.
21
- attr_reader :testing_enabled
20
+ # @return (Bool) Is external beta testing enabled for this train? Only one train can have enabled testing.
21
+ attr_reader :external_testing_enabled
22
+
23
+ # @return (Bool) Is internal beta testing enabled for this train? Only one train can have enabled testing.
24
+ attr_reader :internal_testing_enabled
22
25
 
23
26
  # @return (Array) An array of all builds that are inside this train (Spaceship::Tunes::Build)
24
27
  # I never got this to work to properly try and debug this
@@ -27,7 +30,8 @@ module Spaceship
27
30
  attr_mapping(
28
31
  'versionString' => :version_string,
29
32
  'platform' => :platform,
30
- 'testing.value' => :testing_enabled
33
+ 'externalTesting.value' => :external_testing_enabled,
34
+ 'internalTesting.value' => :internal_testing_enabled
31
35
  )
32
36
 
33
37
  class << self
@@ -40,9 +44,12 @@ module Spaceship
40
44
  # @param application (Spaceship::Tunes::Application) The app this train is for
41
45
  # @param app_id (String) The unique Apple ID of this app
42
46
  def all(application, app_id)
43
- data = client.build_trains(app_id)
47
+ trains = []
48
+ trains += client.build_trains(app_id, 'internal')['trains']
49
+ trains += client.build_trains(app_id, 'external')['trains']
50
+
44
51
  result = {}
45
- data['trains'].each do |attrs|
52
+ trains.each do |attrs|
46
53
  attrs.merge!(application: application)
47
54
  current = self.factory(attrs)
48
55
  result[current.version_string] = current
@@ -66,14 +73,19 @@ module Spaceship
66
73
  end
67
74
  end
68
75
 
69
- def update_testing_status!(new_value)
70
- data = client.build_trains(self.application.apple_id)
76
+ # @param (testing_type) internal or external
77
+ def update_testing_status!(new_value, testing_type)
78
+ data = client.build_trains(self.application.apple_id, testing_type)
79
+
71
80
  data['trains'].each do |train|
72
- train['testing']['value'] = false
73
- train['testing']['value'] = new_value if train['versionString'] == version_string
81
+ train["#{testing_type}Testing"]['value'] = false
82
+ train["#{testing_type}Testing"]['value'] = new_value if train['versionString'] == version_string
74
83
  end
75
- result = client.update_build_trains!(application.apple_id, data)
76
- self.testing_enabled = new_value
84
+
85
+ result = client.update_build_trains!(application.apple_id, testing_type, data)
86
+ self.internal_testing_enabled = new_value if testing_type == 'internal'
87
+ self.external_testing_enabled = new_value if testing_type == 'external'
88
+
77
89
  result
78
90
  end
79
91
  end
@@ -6,6 +6,8 @@ module Spaceship
6
6
  attr_accessor :original_array # reference to original array
7
7
 
8
8
  def initialize(identifier, ref)
9
+ raise "ref is nil" if ref.nil?
10
+
9
11
  self.identifier = identifier.to_s
10
12
  self.original_array = ref
11
13
  end
@@ -20,7 +22,7 @@ module Spaceship
20
22
 
21
23
  def get_lang(lang)
22
24
  result = self.original_array.find do |current|
23
- current['language'] == lang
25
+ current['language'] == lang or current['localeCode'] == lang # Apple being consistent
24
26
  end
25
27
  return result if result
26
28
 
@@ -10,3 +10,5 @@ require 'spaceship/tunes/language_converter'
10
10
  require 'spaceship/tunes/build'
11
11
  require 'spaceship/tunes/processing_build'
12
12
  require 'spaceship/tunes/build_train'
13
+ require 'spaceship/tunes/tester'
14
+ require 'spaceship/tunes/app_details'
@@ -6,6 +6,12 @@ module Spaceship
6
6
  class ITunesConnectError < StandardError
7
7
  end
8
8
 
9
+ # ITunesConnectNoChangesError is thrown when the only error is that there were no changes
10
+ # usually those errors are irrelevant
11
+ class ITunesConnectNoChangesError < ITunesConnectError
12
+
13
+ end
14
+
9
15
  #####################################################
10
16
  # @!group Init and Login
11
17
  #####################################################
@@ -75,6 +81,8 @@ module Spaceship
75
81
  end
76
82
  end
77
83
 
84
+ # rubocop:disable Metrics/CyclomaticComplexity
85
+ # rubocop:disable Metrics/PerceivedComplexity
78
86
  def handle_itc_response(raw)
79
87
  return unless raw
80
88
  return unless raw.kind_of? Hash
@@ -116,7 +124,12 @@ module Spaceship
116
124
  errors << different_error if different_error
117
125
 
118
126
  if errors.count > 0 # they are separated by `.` by default
119
- raise ITunesConnectError.new, errors.join(' ')
127
+ if errors.count == 1 and errors.first == "You haven't made any changes."
128
+ # This is a special error for which we throw a separate exception
129
+ raise ITunesConnectNoChangesError.new, errors.first
130
+ else
131
+ raise ITunesConnectError.new, errors.join(' ')
132
+ end
120
133
  end
121
134
 
122
135
  puts data['sectionInfoKeys'] if data['sectionInfoKeys']
@@ -124,16 +137,33 @@ module Spaceship
124
137
 
125
138
  return data
126
139
  end
140
+ # rubocop:enable Metrics/CyclomaticComplexity
141
+ # rubocop:enable Metrics/PerceivedComplexity
127
142
 
128
143
  #####################################################
129
144
  # @!group Applications
130
145
  #####################################################
131
146
 
132
147
  def applications
133
- r = request(:get, 'ra/apps/manageyourapps/summary')
148
+ r = request(:get, 'ra/apps/manageyourapps/summary/v2')
134
149
  parse_response(r, 'data')['summaries']
135
150
  end
136
151
 
152
+ def app_details(app_id)
153
+ r = request(:get, "ra/apps/#{app_id}/details")
154
+ parse_response(r, 'data')
155
+ end
156
+
157
+ def update_app_details!(app_id, data)
158
+ r = request(:post) do |req|
159
+ req.url "ra/apps/#{app_id}/details"
160
+ req.body = data.to_json
161
+ req.headers['Content-Type'] = 'application/json'
162
+ end
163
+
164
+ handle_itc_response(r.body)
165
+ end
166
+
137
167
  # Creates a new application on iTunes Connect
138
168
  # @param name (String): The name of your app as it will appear on the App Store.
139
169
  # This can't be longer than 255 characters.
@@ -146,21 +176,27 @@ module Spaceship
146
176
  # can't be changed after you submit your first build.
147
177
  def create_application!(name: nil, primary_language: nil, version: nil, sku: nil, bundle_id: nil, bundle_id_suffix: nil, company_name: nil)
148
178
  # First, we need to fetch the data from Apple, which we then modify with the user's values
149
- r = request(:get, 'ra/apps/create/?appType=ios')
179
+ app_type = 'ios'
180
+ r = request(:get, "ra/apps/create/v2/?platformString=#{app_type}")
150
181
  data = parse_response(r, 'data')
151
182
 
152
183
  # Now fill in the values we have
153
- data['versionString']['value'] = version
154
- data['newApp']['name']['value'] = name
184
+ # some values are nil, that's why there is a hash
185
+ data['versionString'] = { value: version }
186
+ data['newApp']['name'] = { value: name }
155
187
  data['newApp']['bundleId']['value'] = bundle_id
156
188
  data['newApp']['primaryLanguage']['value'] = primary_language || 'English'
157
- data['newApp']['vendorId']['value'] = sku
189
+ data['newApp']['vendorId'] = {value: sku }
158
190
  data['newApp']['bundleIdSuffix']['value'] = bundle_id_suffix
159
191
  data['companyName']['value'] = company_name if company_name
192
+ data['newApp']['appType'] = app_type
193
+
194
+ data['initialPlatform'] = app_type
195
+ data['enabledPlatformsForCreation']['value'] = [app_type]
160
196
 
161
197
  # Now send back the modified hash
162
198
  r = request(:post) do |req|
163
- req.url 'ra/apps/create/?appType=ios'
199
+ req.url 'ra/apps/create/v2'
164
200
  req.body = data.to_json
165
201
  req.headers['Content-Type'] = 'application/json'
166
202
  end
@@ -191,9 +227,17 @@ module Spaceship
191
227
  def app_version(app_id, is_live)
192
228
  raise "app_id is required" unless app_id
193
229
 
194
- v_text = (is_live ? 'live' : nil)
230
+ # First we need to fetch the IDs for the edit / live version
231
+ r = request(:get, "ra/apps/#{app_id}/overview")
232
+ platforms = parse_response(r, 'data')['platforms']
233
+
234
+ platforms = platforms.first # That won't work for mac apps
195
235
 
196
- r = request(:get, "ra/apps/version/#{app_id}", {v: v_text})
236
+ version = platforms[(is_live ? 'deliverableVersion' : 'inFlightVersion')]
237
+ return nil unless version
238
+ version_id = version['id']
239
+
240
+ r = request(:get, "ra/apps/#{app_id}/platforms/ios/versions/#{version_id}")
197
241
  parse_response(r, 'data')
198
242
  end
199
243
 
@@ -215,18 +259,18 @@ module Spaceship
215
259
  # @!group Build Trains
216
260
  #####################################################
217
261
 
218
- def build_trains(app_id)
262
+ # @param (testing_type) internal or external
263
+ def build_trains(app_id, testing_type)
219
264
  raise "app_id is required" unless app_id
220
-
221
- r = request(:get, "ra/apps/#{app_id}/trains/")
265
+ r = request(:get, "ra/apps/#{app_id}/trains/?testingType=#{testing_type}")
222
266
  parse_response(r, 'data')
223
267
  end
224
268
 
225
- def update_build_trains!(app_id, data)
269
+ def update_build_trains!(app_id, testing_type, data)
226
270
  raise "app_id is required" unless app_id
227
271
 
228
272
  r = request(:post) do |req|
229
- req.url "ra/apps/#{app_id}/trains/"
273
+ req.url "ra/apps/#{app_id}/testingTypes/#{testing_type}/trains/"
230
274
  req.body = data.to_json
231
275
  req.headers['Content-Type'] = 'application/json'
232
276
  end
@@ -1,3 +1,3 @@
1
1
  module Spaceship
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.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.6.1
4
+ version: 0.7.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: 2015-09-08 00:00:00.000000000 Z
12
+ date: 2015-09-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: credentials_manager
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: 0.8.0
20
+ version: 0.8.1
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: 0.8.0
27
+ version: 0.8.1
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: multi_xml
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -251,6 +251,7 @@ files:
251
251
  - lib/spaceship/portal/provisioning_profile.rb
252
252
  - lib/spaceship/portal/spaceship.rb
253
253
  - lib/spaceship/portal/ui/select_team.rb
254
+ - lib/spaceship/tunes/app_details.rb
254
255
  - lib/spaceship/tunes/app_screenshot.rb
255
256
  - lib/spaceship/tunes/app_status.rb
256
257
  - lib/spaceship/tunes/app_submission.rb
@@ -288,7 +289,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
288
289
  version: '0'
289
290
  requirements: []
290
291
  rubyforge_project:
291
- rubygems_version: 2.4.5
292
+ rubygems_version: 2.4.6
292
293
  signing_key:
293
294
  specification_version: 4
294
295
  summary: Because you would rather spend your time building stuff than fighting provisioning