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 +4 -4
- data/lib/spaceship.rb +0 -1
- data/lib/spaceship/base.rb +3 -1
- data/lib/spaceship/tunes/app_details.rb +107 -0
- data/lib/spaceship/tunes/app_version.rb +6 -60
- data/lib/spaceship/tunes/application.rb +20 -6
- data/lib/spaceship/tunes/build.rb +58 -47
- data/lib/spaceship/tunes/build_train.rb +23 -11
- data/lib/spaceship/tunes/language_item.rb +3 -1
- data/lib/spaceship/tunes/tunes.rb +2 -0
- data/lib/spaceship/tunes/tunes_client.rb +58 -14
- data/lib/spaceship/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb67ea61ddcb8fc09c87de04eb400be6a4c0c9e2
|
4
|
+
data.tar.gz: c62c7bc6307daf12b7dd9a890c30241e633ec02c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86c17cf18e9949250db8d312822188f2896ba4beff339fd949d876fc0e9bd4c2b017d58dc18bcade5a831682ab8f84cddcdd3d640cbf1fe4b2d22b33d7e7cb38
|
7
|
+
data.tar.gz: bd449519839313194d8128f72b6f1fa74f4a89b03293f35b33b692cf5e638d1014f03ccc01db8fb1dd73db8270dc4a77c5559f52f6f8182725f60ffa442766a7
|
data/lib/spaceship.rb
CHANGED
data/lib/spaceship/base.rb
CHANGED
@@ -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)
|
173
|
-
def find(application, app_id, is_live
|
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
|
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
|
-
|
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 (
|
44
|
-
|
45
|
-
|
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
|
-
|
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.
|
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
|
192
|
-
#
|
193
|
-
#
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
# "
|
200
|
-
#
|
201
|
-
# "
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
#
|
217
|
-
#
|
218
|
-
#
|
219
|
-
#
|
220
|
-
#
|
221
|
-
#
|
222
|
-
#
|
223
|
-
#
|
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 :
|
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
|
-
'
|
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
|
-
|
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
|
-
|
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
|
-
|
70
|
-
|
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[
|
73
|
-
train[
|
81
|
+
train["#{testing_type}Testing"]['value'] = false
|
82
|
+
train["#{testing_type}Testing"]['value'] = new_value if train['versionString'] == version_string
|
74
83
|
end
|
75
|
-
|
76
|
-
|
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
|
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
154
|
-
data['
|
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']
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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.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-
|
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.
|
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.
|
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.
|
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
|