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,369 @@
1
+ module Spaceship
2
+ module Portal
3
+ # Represents a provisioning profile of the Apple Dev Portal
4
+ class ProvisioningProfile < PortalBase
5
+ # @return (String) The ID generated by the Dev Portal
6
+ # You'll probably not really need this value
7
+ # @example
8
+ # "2MAY7NPHAA"
9
+ attr_accessor :id
10
+
11
+ # @return (String) The UDID of this provisioning profile
12
+ # This value is used for example for code signing
13
+ # It is also contained in the actual profile
14
+ # @example
15
+ # "23d7df3b-9767-4e85-a1ea-1df4d8f32fec"
16
+ attr_accessor :uuid
17
+
18
+ # @return (DateTime) The date and time of when the profile
19
+ # expires.
20
+ # @example
21
+ # #<DateTime: 2015-11-25T22:45:50+00:00 ((2457352j,81950s,0n),+0s,2299161j)>
22
+ attr_accessor :expires
23
+
24
+ # @return (String) The profile distribution type. You probably want to
25
+ # use the class type to detect the profile type instead of this string.
26
+ # @example AppStore Profile
27
+ # "store"
28
+ # @example AdHoc Profile
29
+ # "adhoc"
30
+ # @example Development Profile
31
+ # "limited"
32
+ attr_accessor :distribution_method
33
+
34
+ # @return (String) The name of this profile
35
+ # @example
36
+ # "com.krausefx.app AppStore"
37
+ attr_accessor :name
38
+
39
+ # @return (String) The status of this profile
40
+ # @example Active (profile is fine)
41
+ # "Active"
42
+ # @example Expired (time ran out)
43
+ # "Expired"
44
+ # @example Invalid (e.g. code signing identity not available any more)
45
+ # "Invalid"
46
+ attr_accessor :status
47
+
48
+ # @return (String) The type of the profile (development or distribution).
49
+ # You'll probably not need this value
50
+ # @example Distribution
51
+ # "iOS Distribution"
52
+ # @example Development
53
+ # "iOS Development"
54
+ attr_accessor :type
55
+
56
+ # @return (String) This will always be "2"
57
+ # @example
58
+ # "2"
59
+ attr_accessor :version
60
+
61
+ # @return (String) The supported platform for this profile
62
+ # @example
63
+ # "ios"
64
+ attr_accessor :platform
65
+
66
+ # No information about this attribute
67
+ attr_accessor :managing_app
68
+
69
+ # A reference to the app this profile is for.
70
+ # You can then easily access the value directly
71
+ # @return (App) The app this profile is for
72
+ #
73
+ # @example Example Value
74
+ # <Spaceship::App
75
+ # @app_id="2UMR2S6PAA"
76
+ # @name="App Name"
77
+ # @platform="ios"
78
+ # @prefix="5A997XSAAA"
79
+ # @bundle_id="com.krausefx.app"
80
+ # @is_wildcard=false
81
+ # @dev_push_enabled=false
82
+ # @prod_push_enabled=false>
83
+ #
84
+ # @example Usage
85
+ # profile.app.name
86
+ attr_accessor :app
87
+
88
+ # @return (Array) A list of certificates used for this profile
89
+ # @example Example Value
90
+ # [
91
+ # <Spaceship::Certificate::Production
92
+ # @status=nil
93
+ # @id="XC5PH8D4AA"
94
+ # @name="iOS Distribution"
95
+ # @created=nil
96
+ # @expires=#<DateTime: 2015-11-25T22:45:50+00:00 ((2457352j,81950s,0n),+0s,2299161j)>
97
+ # @owner_type="team"
98
+ # @owner_name=nil
99
+ # @owner_id=nil
100
+ # @type_display_id="R58UK2EWAA">]
101
+ # ]
102
+ #
103
+ # @example Usage
104
+ # profile.certificates.first.id
105
+ attr_accessor :certificates
106
+
107
+ # @return (Array) A list of devices this profile is enabled for.
108
+ # This will always be [] for AppStore profiles
109
+ #
110
+ # @example Example Value
111
+ # <Spaceship::Device
112
+ # @id="WXQ7V239BE"
113
+ # @name="Grahams iPhone 4s"
114
+ # @udid="ba0ac7d70f7a14c6fa02ef0e02f4fe9c5178e2f7"
115
+ # @platform="ios"
116
+ # @status="c">]
117
+ #
118
+ # @example Usage
119
+ # profile.devices.first.name
120
+ attr_accessor :devices
121
+
122
+ attr_mapping({
123
+ 'provisioningProfileId' => :id,
124
+ 'UUID' => :uuid,
125
+ 'dateExpire' => :expires,
126
+ 'distributionMethod' => :distribution_method,
127
+ 'name' => :name,
128
+ 'status' => :status,
129
+ 'type' => :type,
130
+ 'version' => :version,
131
+ 'proProPlatform' => :platform,
132
+ 'managingApp' => :managing_app,
133
+ 'appId' => :app
134
+ })
135
+
136
+ class << self
137
+ # @return (String) The profile type used for web requests to the Dev Portal
138
+ # @example
139
+ # "limited"
140
+ # "store"
141
+ # "adhoc"
142
+ # "inhouse"
143
+ def type
144
+ raise "You cannot create a ProvisioningProfile without a type. Use a subclass."
145
+ end
146
+
147
+ # Create a new object based on a hash.
148
+ # This is used to create a new object based on the server response.
149
+ def factory(attrs)
150
+ # Ad Hoc Profiles look exactly like App Store profiles, but usually include devices
151
+ attrs['distributionMethod'] = 'adhoc' if attrs['distributionMethod'] == 'store' && attrs['devices'].size > 0
152
+ # available values of `distributionMethod` at this point: ['adhoc', 'store', 'limited']
153
+
154
+ klass = case attrs['distributionMethod']
155
+ when 'limited'
156
+ Development
157
+ when 'store'
158
+ AppStore
159
+ when 'adhoc'
160
+ AdHoc
161
+ when 'inhouse'
162
+ InHouse
163
+ else
164
+ raise "Can't find class '#{attrs['distributionMethod']}'"
165
+ end
166
+
167
+ attrs['appId'] = App.factory(attrs['appId'])
168
+ attrs['devices'].map! { |device| Device.factory(device) }
169
+ attrs['certificates'].map! { |cert| Certificate.factory(cert) }
170
+
171
+ klass.client = @client
172
+ klass.new(attrs)
173
+ end
174
+
175
+ # @return (String) The human readable name of this profile type.
176
+ # @example
177
+ # "AppStore"
178
+ # "AdHoc"
179
+ # "Development"
180
+ # "InHouse"
181
+ def pretty_type
182
+ name.split('::').last
183
+ end
184
+
185
+ # Create a new provisioning profile
186
+ # @param name (String): The name of the provisioning profile on the Dev Portal
187
+ # @param bundle_id (String): The app identifier, this paramter is required
188
+ # @param certificate (Certificate): The certificate that should be used with this
189
+ # provisioning profile. You can also pass an array of certificates to this method. This will
190
+ # only work for development profiles
191
+ # @param devices (Array) (optional): An array of Device objects that should be used in this profile.
192
+ # It is recommend to not pass devices as spaceship will automatically add all devices for AdHoc
193
+ # and Development profiles and add none for AppStore and Enterprise Profiles
194
+ # @return (ProvisioningProfile): The profile that was just created
195
+ def create!(name: nil, bundle_id: nil, certificate: nil, devices: [])
196
+ raise "Missing required parameter 'bundle_id'" if bundle_id.to_s.empty?
197
+ raise "Missing required parameter 'certificate'. e.g. use `Spaceship::Certificate::Production.all.first`" if certificate.to_s.empty?
198
+
199
+ app = Spaceship::App.find(bundle_id)
200
+ raise "Could not find app with bundle id '#{bundle_id}'" unless app
201
+
202
+ # Fill in sensible default values
203
+ name ||= [bundle_id, self.pretty_type].join(' ')
204
+
205
+ devices = [] if (self == AppStore or self == InHouse) # App Store Profiles MUST NOT have devices
206
+
207
+ certificate_parameter = certificate.collect { |c| c.id } if certificate.kind_of?Array
208
+ certificate_parameter ||= [certificate.id]
209
+
210
+ # Fix https://github.com/KrauseFx/fastlane/issues/349
211
+ certificate_parameter = certificate_parameter.first if certificate_parameter.count == 1
212
+
213
+ if devices.nil? or devices.count == 0
214
+ if self == Development or self == AdHoc
215
+ # For Development and AdHoc we usually want all devices by default
216
+ devices = Spaceship::Device.all
217
+ end
218
+ end
219
+
220
+ profile = client.create_provisioning_profile!(name,
221
+ self.type,
222
+ app.app_id,
223
+ certificate_parameter,
224
+ devices.map {|d| d.id} )
225
+ self.new(profile)
226
+ end
227
+
228
+ # @return (Array) Returns all profiles registered for this account
229
+ # If you're calling this from a subclass (like AdHoc), this will
230
+ # only return the profiles that are of this type
231
+ def all
232
+ profiles = client.provisioning_profiles.map do |profile|
233
+ self.factory(profile)
234
+ end
235
+
236
+ # filter out the profiles managed by xcode
237
+ profiles.delete_if do |profile|
238
+ profile.managed_by_xcode?
239
+ end
240
+
241
+ return profiles if self == ProvisioningProfile
242
+
243
+ # only return the profiles that match the class
244
+ profiles.select do |profile|
245
+ profile.class == self
246
+ end
247
+ end
248
+
249
+ # @return (Array) Returns an array of provisioning
250
+ # profiles matching the bundle identifier
251
+ # Returns [] if no profiles were found
252
+ # This may also contain invalid or expired profiles
253
+ def find_by_bundle_id(bundle_id)
254
+ all.find_all do |profile|
255
+ profile.app.bundle_id == bundle_id
256
+ end
257
+ end
258
+
259
+ end
260
+
261
+ # Represents a Development profile from the Dev Portal
262
+ class Development < ProvisioningProfile
263
+ def self.type
264
+ 'limited'
265
+ end
266
+ end
267
+
268
+ # Represents an AppStore profile from the Dev Portal
269
+ class AppStore < ProvisioningProfile
270
+ def self.type
271
+ 'store'
272
+ end
273
+ end
274
+
275
+ # Represents an AdHoc profile from the Dev Portal
276
+ class AdHoc < ProvisioningProfile
277
+ def self.type
278
+ 'adhoc'
279
+ end
280
+ end
281
+
282
+ # Represents an Enterprise InHouse profile from the Dev Portal
283
+ class InHouse < ProvisioningProfile
284
+ def self.type
285
+ 'inhouse'
286
+ end
287
+ end
288
+
289
+ # Download the current provisioning profile. This will *not* store
290
+ # the provisioning profile on the file system. Instead this method
291
+ # will return the content of the profile.
292
+ # @return (String) The content of the provisioning profile
293
+ # You'll probably want to store it on the file system
294
+ # @example
295
+ # File.write("path.mobileprovision", profile.download)
296
+ def download
297
+ client.download_provisioning_profile(self.id)
298
+ end
299
+
300
+ # Delete the provisioning profile
301
+ def delete!
302
+ client.delete_provisioning_profile!(self.id)
303
+ end
304
+
305
+ # Repair an existing provisioning profile
306
+ # alias to update!
307
+ # @return (ProvisioningProfile) A new provisioning profile, as
308
+ # the repair method will generate a profile with a new ID
309
+ def repair!
310
+ update!
311
+ end
312
+
313
+ # Updates the provisioning profile from the local data
314
+ # e.g. after you added new devices to the profile
315
+ # This will also update the code signing identity if necessary
316
+ # @return (ProvisioningProfile) A new provisioning profile, as
317
+ # the repair method will generate a profile with a new ID
318
+ def update!
319
+ unless certificate_valid?
320
+ if self.kind_of?Development
321
+ self.certificates = [Spaceship::Certificate::Development.all.first]
322
+ elsif self.kind_of?InHouse
323
+ self.certificates = [Spaceship::Certificate::InHouse.all.first]
324
+ else
325
+ self.certificates = [Spaceship::Certificate::Production.all.first]
326
+ end
327
+ end
328
+
329
+ client.repair_provisioning_profile!(
330
+ self.id,
331
+ self.name,
332
+ self.distribution_method,
333
+ self.app.app_id,
334
+ self.certificates.map { |c| c.id },
335
+ self.devices.map { |d| d.id }
336
+ )
337
+
338
+ # We need to fetch the provisioning profile again, as the ID changes
339
+ profile = Spaceship::ProvisioningProfile.all.find do |profile|
340
+ profile.name == self.name # we can use the name as it's valid
341
+ end
342
+
343
+ return profile
344
+ end
345
+
346
+ # Is the certificate of this profile available?
347
+ # @return (Bool) is the certificate valid?
348
+ def certificate_valid?
349
+ return false if (certificates || []).count == 0
350
+ certificates.each do |c|
351
+ if Spaceship::Certificate.all.collect { |s| s.id }.include?(c.id)
352
+ return true
353
+ end
354
+ end
355
+ return false
356
+ end
357
+
358
+ # @return (Bool) Is the current provisioning profile valid?
359
+ def valid?
360
+ return (status == 'Active' and certificate_valid?)
361
+ end
362
+
363
+ # @return (Bool) Is this profile managed by Xcode?
364
+ def managed_by_xcode?
365
+ managing_app == 'Xcode'
366
+ end
367
+ end
368
+ end
369
+ end
@@ -0,0 +1,94 @@
1
+ module Spaceship
2
+ module Portal
3
+ class << self
4
+ # This client stores the default client when using the lazy syntax
5
+ # Spaceship.app instead of using the spaceship launcher
6
+ attr_accessor :client
7
+
8
+ # Authenticates with Apple's web services. This method has to be called once
9
+ # to generate a valid session. The session will automatically be used from then
10
+ # on.
11
+ #
12
+ # This method will automatically use the username from the Appfile (if available)
13
+ # and fetch the password from the Keychain (if available)
14
+ #
15
+ # @param user (String) (optional): The username (usually the email address)
16
+ # @param password (String) (optional): The password
17
+ #
18
+ # @raise InvalidUserCredentialsError: raised if authentication failed
19
+ #
20
+ # @return (Spaceship::Client) The client the login method was called for
21
+ def login(user = nil, password = nil)
22
+ @client = PortalClient.login(user, password)
23
+ end
24
+
25
+ # Open up the team selection for the user (if necessary).
26
+ #
27
+ # If the user is in multiple teams, a team selection is shown.
28
+ # The user can then select a team by entering the number
29
+ #
30
+ # Additionally, the team ID is shown next to each team name
31
+ # so that the user can use the environment variable `FASTLANE_TEAM_ID`
32
+ # for future user.
33
+ #
34
+ # @return (String) The ID of the select team. You also get the value if
35
+ # the user is only in one team.
36
+ def select_team
37
+ @client.select_team
38
+ end
39
+
40
+ # Helper methods for managing multiple instances of spaceship
41
+
42
+ # @return (Class) Access the apps for the spaceship
43
+ def app
44
+ Spaceship::App.set_client(@client)
45
+ end
46
+
47
+ # @return (Class) Access the devices for the spaceship
48
+ def device
49
+ Spaceship::Device.set_client(@client)
50
+ end
51
+
52
+ # @return (Class) Access the certificates for the spaceship
53
+ def certificate
54
+ Spaceship::Certificate.set_client(@client)
55
+ end
56
+
57
+ # @return (Class) Access the provisioning profiles for the spaceship
58
+ def provisioning_profile
59
+ Spaceship::ProvisioningProfile.set_client(@client)
60
+ end
61
+ end
62
+ end
63
+
64
+ # Legacy code to support `Spaceship.app` without `Portal`
65
+ class << self
66
+ def login(user = nil, password = nil)
67
+ Spaceship::Portal.login(user, password)
68
+ end
69
+
70
+ def select_team
71
+ Spaceship::Portal.select_team
72
+ end
73
+
74
+ def app
75
+ Spaceship::Portal.app
76
+ end
77
+
78
+ def device
79
+ Spaceship::Portal.device
80
+ end
81
+
82
+ def certificate
83
+ Spaceship::Portal.certificate
84
+ end
85
+
86
+ def provisioning_profile
87
+ Spaceship::Portal.provisioning_profile
88
+ end
89
+
90
+ def client
91
+ Spaceship::Portal.client
92
+ end
93
+ end
94
+ end