spaceship 0.6.1 → 0.7.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 +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
|