spaceship 0.0.15 → 0.1.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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/assets/languageMapping.json +224 -0
  3. data/lib/spaceship.rb +20 -63
  4. data/lib/spaceship/base.rb +71 -14
  5. data/lib/spaceship/client.rb +9 -274
  6. data/lib/spaceship/launcher.rb +1 -1
  7. data/lib/spaceship/portal/app.rb +125 -0
  8. data/lib/spaceship/portal/certificate.rb +273 -0
  9. data/lib/spaceship/portal/device.rb +102 -0
  10. data/lib/spaceship/portal/portal.rb +6 -0
  11. data/lib/spaceship/portal/portal_base.rb +13 -0
  12. data/lib/spaceship/portal/portal_client.rb +289 -0
  13. data/lib/spaceship/portal/provisioning_profile.rb +369 -0
  14. data/lib/spaceship/portal/spaceship.rb +94 -0
  15. data/lib/spaceship/{ui → portal/ui}/select_team.rb +0 -0
  16. data/lib/spaceship/tunes/app_screenshot.rb +28 -0
  17. data/lib/spaceship/tunes/app_status.rb +63 -0
  18. data/lib/spaceship/tunes/app_submission.rb +149 -0
  19. data/lib/spaceship/tunes/app_version.rb +337 -0
  20. data/lib/spaceship/tunes/application.rb +253 -0
  21. data/lib/spaceship/tunes/build.rb +128 -0
  22. data/lib/spaceship/tunes/build_train.rb +79 -0
  23. data/lib/spaceship/tunes/language_converter.rb +44 -0
  24. data/lib/spaceship/tunes/language_item.rb +54 -0
  25. data/lib/spaceship/tunes/processing_build.rb +30 -0
  26. data/lib/spaceship/tunes/spaceship.rb +26 -0
  27. data/lib/spaceship/tunes/tester.rb +177 -0
  28. data/lib/spaceship/tunes/tunes.rb +12 -0
  29. data/lib/spaceship/tunes/tunes_base.rb +15 -0
  30. data/lib/spaceship/tunes/tunes_client.rb +360 -0
  31. data/lib/spaceship/version.rb +1 -1
  32. metadata +27 -7
  33. data/lib/spaceship/app.rb +0 -125
  34. data/lib/spaceship/certificate.rb +0 -271
  35. data/lib/spaceship/device.rb +0 -100
  36. data/lib/spaceship/provisioning_profile.rb +0 -367
@@ -0,0 +1,253 @@
1
+ module Spaceship
2
+ module Tunes
3
+ class Application < TunesBase
4
+
5
+ # @return (String) The App identifier of this app, provided by iTunes Connect
6
+ # @example
7
+ # "1013943394"
8
+ attr_accessor :apple_id
9
+
10
+ # @return (String) The name you provided for this app (in the default language)
11
+ # @example
12
+ # "Spaceship App"
13
+ attr_accessor :name
14
+
15
+ # @return (String) the supported platform of this app
16
+ # @example
17
+ # "ios"
18
+ attr_accessor :platform
19
+
20
+ # @return (String) The Vendor ID provided by iTunes Connect
21
+ # @example
22
+ # "1435592086"
23
+ attr_accessor :vendor_id
24
+
25
+ # @return (String) The bundle_id (app identifier) of your app
26
+ # @example
27
+ # "com.krausefx.app"
28
+ attr_accessor :bundle_id
29
+
30
+ # @return (String) Last modified
31
+ attr_accessor :last_modified
32
+
33
+ # @return (Integer) The number of issues provided by iTunes Connect
34
+ attr_accessor :issues_count
35
+
36
+ # @return (String) The URL to a low resolution app icon of this app (340x340px). Might be nil
37
+ # @example
38
+ # "https://is1-ssl.mzstatic.com/image/thumb/Purple7/v4/cd/a3/e2/cda3e2ac-4034-c6af-ee0c-3e4d9a0bafaa/pr_source.png/340x340bb-80.png"
39
+ # @example
40
+ # nil
41
+ attr_accessor :app_icon_preview_url
42
+
43
+ # @return [Array] A list of binaries which are not even yet processing based on the version
44
+ # Those builds are usually the ones that are just stuck on iTunes Connect...
45
+ attr_accessor :pre_processing_builds
46
+
47
+ attr_mapping(
48
+ 'adamId' => :apple_id,
49
+ 'name' => :name,
50
+ 'appType' => :platform,
51
+ 'vendorId' => :vendor_id,
52
+ 'bundleId' => :bundle_id,
53
+ 'lastModifiedDate' => :last_modified,
54
+ 'issuesCount' => :issues_count,
55
+ 'iconUrl' => :app_icon_preview_url
56
+ )
57
+
58
+ class << self
59
+ # Create a new object based on a hash.
60
+ # This is used to create a new object based on the server response.
61
+ def factory(attrs)
62
+ self.new(attrs)
63
+ end
64
+
65
+ # @return (Array) Returns all apps available for this account
66
+ def all
67
+ client.applications.map { |application| self.factory(application) }
68
+ end
69
+
70
+ # @return (Spaceship::Tunes::Application) Returns the application matching the parameter
71
+ # as either the App ID or the bundle identifier
72
+ def find(identifier)
73
+ all.find do |app|
74
+ (app.apple_id == identifier.to_s or app.bundle_id == identifier)
75
+ end
76
+ end
77
+
78
+ # Creates a new application on iTunes Connect
79
+ # @param name (String): The name of your app as it will appear on the App Store.
80
+ # This can't be longer than 255 characters.
81
+ # @param primary_language (String): If localized app information isn't available in an
82
+ # App Store territory, the information from your primary language will be used instead.
83
+ # @param version (String): The version number is shown on the App Store and should
84
+ # match the one you used in Xcode.
85
+ # @param sku (String): A unique ID for your app that is not visible on the App Store.
86
+ # @param bundle_id (String): The bundle ID must match the one you used in Xcode. It
87
+ # can't be changed after you submit your first build.
88
+ def create!(name: nil, primary_language: nil, version: nil, sku: nil, bundle_id: nil, bundle_id_suffix: nil)
89
+ client.create_application!(name: name,
90
+ primary_language: primary_language,
91
+ version: version,
92
+ sku: sku,
93
+ bundle_id: bundle_id,
94
+ bundle_id_suffix: bundle_id_suffix)
95
+ end
96
+ end
97
+
98
+ #####################################################
99
+ # @!group Getting information
100
+ #####################################################
101
+
102
+ # @return (Spaceship::AppVersion) Receive the version that is currently live on the
103
+ # App Store. You can't modify all values there, so be careful.
104
+ def live_version
105
+ v = Spaceship::AppVersion.find(self, self.apple_id, true)
106
+ end
107
+
108
+ # @return (Spaceship::AppVersion) Receive the version that can fully be edited
109
+ def edit_version
110
+ # Apple's server will respond with the same version if there is only one, for both v=live and v=
111
+ # That's why we have to check in the app_summary.json request if there are 2 versions or just one
112
+ # if there is only one version, we'll return nil
113
+ if raw_data['versions'].count == 1
114
+ return nil # only live version, user should create a new version
115
+ end
116
+
117
+ Spaceship::AppVersion.find(self, self.apple_id, false)
118
+ end
119
+
120
+ # @return (Spaceship::AppVersion) This will return the `edit_version` if available
121
+ # and fallback to the `edit_version`. Use this to just access the latest data
122
+ def latest_version
123
+ edit_version || live_version
124
+ end
125
+
126
+ # @return (String) An URL to this specific resource. You can enter this URL into your browser
127
+ def url
128
+ "https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app/#{self.apple_id}"
129
+ end
130
+
131
+ # @return (Hash) Contains the reason for rejection.
132
+ # if everything is alright, the result will be
133
+ # `{"sectionErrorKeys"=>[], "sectionInfoKeys"=>[], "sectionWarningKeys"=>[], "replyConstraints"=>{"minLength"=>1, "maxLength"=>4000}, "appNotes"=>{"threads"=>[]}, "betaNotes"=>{"threads"=>[]}, "appMessages"=>{"threads"=>[]}}`
134
+ def resolution_center
135
+ client.get_resolution_center(apple_id)
136
+ end
137
+
138
+ #####################################################
139
+ # @!group Modifying
140
+ #####################################################
141
+
142
+ # Create a new version of your app
143
+ def create_version!(version_number)
144
+ if edit_version
145
+ raise "Cannot create a new version for this app as there already is an `edit_version` available"
146
+ end
147
+
148
+ client.create_version!(apple_id, version_number)
149
+
150
+ # Since we have stored the outdated raw_data, we need to refresh this object
151
+ # otherwise `edit_version` will return nil
152
+ # TODO: implemented -reload method
153
+ end
154
+
155
+ #####################################################
156
+ # @!group Builds
157
+ #####################################################
158
+
159
+ # A reference to all the build trains
160
+ # @return [Hash] a hash, the version number being the key
161
+ def build_trains
162
+ Tunes::BuildTrain.all(self, self.apple_id)
163
+ end
164
+
165
+ def pre_processing_builds
166
+ data = client.build_trains(apple_id) # we need to fetch all trains here to get the builds
167
+
168
+ data.fetch('processingBuilds', []).collect do |attrs|
169
+ attrs.merge!(build_train: self)
170
+ Tunes::ProcessingBuild.factory(attrs)
171
+ end
172
+ end
173
+
174
+ #####################################################
175
+ # @!group Submit for Review
176
+ #####################################################
177
+
178
+ def create_submission
179
+ version = self.latest_version
180
+ if version.nil?
181
+ raise "Could not find a valid version to submit for review"
182
+ end
183
+
184
+ Spaceship::AppSubmission.create(self, self.apple_id, version)
185
+ end
186
+
187
+ #####################################################
188
+ # @!group General
189
+ #####################################################
190
+ def setup
191
+
192
+ end
193
+
194
+ #####################################################
195
+ # @!group Testers
196
+ #####################################################
197
+
198
+ # Add all testers (internal and external) to the current app list
199
+ def add_all_testers!
200
+ Tunes::Tester.external.add_all_to_app!(self.apple_id)
201
+ Tunes::Tester.internal.add_all_to_app!(self.apple_id)
202
+ end
203
+
204
+ # @return (Array) Returns all external testers available for this app
205
+ def external_testers
206
+ Tunes::Tester.external.all_by_app(self.apple_id)
207
+ end
208
+
209
+ # @return (Array) Returns all internal testers available for this app
210
+ def internal_testers
211
+ Tunes::Tester.internal.all_by_app(self.apple_id)
212
+ end
213
+
214
+ # @return (Spaceship::Tunes::Tester.external) Returns the external tester matching the parameter
215
+ # as either the Tester id or email
216
+ # @param identifier (String) (required): Value used to filter the tester
217
+ def find_external_tester(identifier)
218
+ Tunes::Tester.external.find_by_app(self.apple_id, identifier)
219
+ end
220
+
221
+ # @return (Spaceship::Tunes::Tester.internal) Returns the internal tester matching the parameter
222
+ # as either the Tester id or email
223
+ # @param identifier (String) (required): Value used to filter the tester
224
+ def find_internal_tester(identifier)
225
+ Tunes::Tester.internal.find_by_app(self.apple_id, identifier)
226
+ end
227
+
228
+ # Add external tester to the current app list, if it doesn't exist will be created
229
+ # @param email (String) (required): The email of the tester
230
+ # @param first_name (String) (optional): The first name of the tester (Ignored if user already exist)
231
+ # @param last_name (String) (optional): The last name of the tester (Ignored if user already exist)
232
+ def add_external_tester!(email: nil, first_name: nil, last_name: nil)
233
+ raise "Tester is already on #{self.name} betatesters" if find_external_tester(email)
234
+
235
+ tester = Tunes::Tester.external.find(email) || Tunes::Tester.external.create!(email: email,
236
+ first_name: first_name,
237
+ last_name: last_name)
238
+ tester.add_to_app!(self.apple_id)
239
+ end
240
+
241
+ # Remove external tester from the current app list that matching the parameter
242
+ # as either the Tester id or email
243
+ # @param identifier (String) (required): Value used to filter the tester
244
+ def remove_external_tester!(identifier)
245
+ tester = find_external_tester(identifier)
246
+
247
+ raise "Tester is not on #{self.name} betatesters" unless tester
248
+
249
+ tester.remove_from_app!(self.apple_id)
250
+ end
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,128 @@
1
+ module Spaceship
2
+ module Tunes
3
+ # Represents a build which is inside the build train
4
+ class Build < TunesBase
5
+
6
+ #####################################################
7
+ # @!group General metadata
8
+ #####################################################
9
+
10
+ # @return (Spaceship::Tunes::Application) A reference to the build train this build is contained in
11
+ attr_accessor :build_train
12
+
13
+ # @return (Integer) The ID generated by iTunes Connect
14
+ attr_accessor :id
15
+
16
+ # @return (Boolean)
17
+ attr_accessor :valid
18
+
19
+ # @return (String) The build version (not the version number)
20
+ attr_accessor :build_version
21
+
22
+ # @return (String) The version number (e.g. 1.3)
23
+ attr_accessor :train_version
24
+
25
+ # @return (Integer) The number of ticks since 1970 (e.g. 1413966436000)
26
+ attr_accessor :upload_date
27
+
28
+ # @return (String) URL to the app icon of this build (150x150px)
29
+ attr_accessor :icon_url
30
+
31
+ # @return (String)
32
+ attr_accessor :app_name
33
+
34
+ # @return (String) The platform of this build (e.g. 'ios')
35
+ attr_accessor :platform
36
+
37
+ # @return (Integer) When is this build going to be invalid
38
+ attr_accessor :internal_expiry_date
39
+
40
+ # @return (Bool) Does this build support WatchKit?
41
+ attr_accessor :watch_kit_enabled
42
+
43
+ # @return (Bool):
44
+ attr_accessor :ready_to_install
45
+
46
+ #####################################################
47
+ # @!group Analytics
48
+ #####################################################
49
+
50
+ # @return (Integer) Number of installs of this build
51
+ attr_accessor :install_count
52
+
53
+ # @return (Integer) Number of installs for this build that come from internal users
54
+ attr_accessor :internal_install_count
55
+
56
+ # @return (Integer) Number of installs for this build that come from external users
57
+ attr_accessor :external_install_count
58
+
59
+ # @return (Integer) Might be nil. The number of sessions for this build
60
+ attr_accessor :session_count
61
+
62
+ # @return (Integer) Might be nil. The number of crashes of this build
63
+ attr_accessor :crash_count
64
+
65
+ attr_mapping(
66
+ 'uploadDate' => :upload_date,
67
+ 'iconUrl' => :icon_url,
68
+ 'buildVersion' => :build_version,
69
+ 'trainVersion' => :train_version,
70
+ 'appName' => :app_name,
71
+ 'platform' => :platform,
72
+ 'id' => :id,
73
+ 'valid' => :valid,
74
+
75
+ 'installCount' => :install_count,
76
+ 'internalInstallCount' => :internal_install_count,
77
+ 'externalInstallCount' => :external_install_count,
78
+ 'sessionCount' => :session_count,
79
+ 'crashCount' => :crash_count,
80
+ 'internalExpiry' => :internal_expiry_date,
81
+ 'watchKitEnabled' => :watch_kit_enabled,
82
+ 'readyToInstall' => :ready_to_install,
83
+ )
84
+
85
+ class << self
86
+ # Create a new object based on a hash.
87
+ # This is used to create a new object based on the server response.
88
+ def factory(attrs)
89
+ self.new(attrs)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ # Example response
97
+ # "buildVersion": "0.9.10",
98
+ # "trainVersion": "0.9.10",
99
+ # "uploadDate": 1413966436000,
100
+ # "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",
101
+ # "appName": "Yeahaa",
102
+ # "platform": "ios",
103
+ # "betaEntitled": false,
104
+ # "id": 523299,
105
+ # "valid": true,
106
+ # "missingExportCompliance": false,
107
+ # "waitingForExportComplianceApproval": false,
108
+ # "addedInternalUsersCount": 0,
109
+ # "addedExternalUsersCount": 0,
110
+ # "invitedExternalUsersCount": 0,
111
+ # "invitedInternalUsersCount": 0,
112
+ # "acceptedInternalUsersCount": 0,
113
+ # "acceptedExternalUsersCount": 0,
114
+ # "installCount": 0,
115
+ # "internalInstallCount": 0,
116
+ # "externalInstallCount": 0,
117
+ # "sessionCount": null,
118
+ # "crashCount": null,
119
+ # "promotedVersion": null,
120
+ # "internalState": "noBetaEntitlement",
121
+ # "betaState": "noBetaEntitlement",
122
+ # "internalExpiry": 1416562036000,
123
+ # "externalExpiry": 0,
124
+ # "watchKitEnabled": false,
125
+ # "readyToInstall": false,
126
+ # "sdkBuildWhitelisted": true,
127
+ # "internalTesting": null,
128
+ # "externalTesting": null
@@ -0,0 +1,79 @@
1
+ module Spaceship
2
+ module Tunes
3
+ # Represents a build train of builds from iTunes Connect
4
+ # A build train is all builds for a given version number with different build numbers
5
+ class BuildTrain < TunesBase
6
+
7
+ # @return (Spaceship::Tunes::Application) A reference to the application
8
+ # this train is for
9
+ attr_accessor :application
10
+
11
+ # @return (Array) An array of all builds that are inside this train (Spaceship::Tunes::Build)
12
+ attr_reader :builds
13
+
14
+ # @return (String) The version number of this train
15
+ attr_reader :version_string
16
+
17
+ # @return (String) Platform (e.g. "ios")
18
+ attr_reader :platform
19
+
20
+ # @return (Bool) Is beta testing enabled for this train? Only one train can have enabled testing.
21
+ attr_reader :testing_enabled
22
+
23
+ # @return (Array) An array of all builds that are inside this train (Spaceship::Tunes::Build)
24
+ # I never got this to work to properly try and debug this
25
+ attr_reader :processing_builds
26
+
27
+ attr_mapping(
28
+ 'versionString' => :version_string,
29
+ 'platform' => :platform,
30
+ 'testing.value' => :testing_enabled
31
+ )
32
+
33
+ class << self
34
+ # Create a new object based on a hash.
35
+ # This is used to create a new object based on the server response.
36
+ def factory(attrs)
37
+ self.new(attrs)
38
+ end
39
+
40
+ # @param application (Spaceship::Tunes::Application) The app this train is for
41
+ # @param app_id (String) The unique Apple ID of this app
42
+ def all(application, app_id)
43
+ data = client.build_trains(app_id)
44
+ result = {}
45
+ data['trains'].each do |attrs|
46
+ attrs.merge!(application: application)
47
+ current = self.factory(attrs)
48
+ result[current.version_string] = current
49
+ end
50
+ result
51
+ end
52
+ end
53
+
54
+ # Setup all the builds and processing builds
55
+ def setup
56
+ @builds = self.raw_data['builds'].collect do |attrs|
57
+ attrs.merge!(build_train: self)
58
+ Tunes::Build.factory(attrs)
59
+ end
60
+
61
+ @processing_builds = self.raw_data['buildsInProcessing'].collect do |attrs|
62
+ attrs.merge!(build_train: self)
63
+ Tunes::Build.factory(attrs)
64
+ end
65
+ end
66
+
67
+ def update_testing_status!(new_value)
68
+ data = client.build_trains(self.application.apple_id)
69
+ data['trains'].each do |train|
70
+ train['testing']['value'] = false
71
+ train['testing']['value'] = new_value if train['versionString'] == version_string
72
+ end
73
+ result = client.update_build_trains!(application.apple_id, data)
74
+ self.testing_enabled = new_value
75
+ result
76
+ end
77
+ end
78
+ end
79
+ end