spaceship 0.0.15 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/assets/languageMapping.json +224 -0
- data/lib/spaceship.rb +20 -63
- data/lib/spaceship/base.rb +71 -14
- data/lib/spaceship/client.rb +9 -274
- data/lib/spaceship/launcher.rb +1 -1
- data/lib/spaceship/portal/app.rb +125 -0
- data/lib/spaceship/portal/certificate.rb +273 -0
- data/lib/spaceship/portal/device.rb +102 -0
- data/lib/spaceship/portal/portal.rb +6 -0
- data/lib/spaceship/portal/portal_base.rb +13 -0
- data/lib/spaceship/portal/portal_client.rb +289 -0
- data/lib/spaceship/portal/provisioning_profile.rb +369 -0
- data/lib/spaceship/portal/spaceship.rb +94 -0
- data/lib/spaceship/{ui → portal/ui}/select_team.rb +0 -0
- data/lib/spaceship/tunes/app_screenshot.rb +28 -0
- data/lib/spaceship/tunes/app_status.rb +63 -0
- data/lib/spaceship/tunes/app_submission.rb +149 -0
- data/lib/spaceship/tunes/app_version.rb +337 -0
- data/lib/spaceship/tunes/application.rb +253 -0
- data/lib/spaceship/tunes/build.rb +128 -0
- data/lib/spaceship/tunes/build_train.rb +79 -0
- data/lib/spaceship/tunes/language_converter.rb +44 -0
- data/lib/spaceship/tunes/language_item.rb +54 -0
- data/lib/spaceship/tunes/processing_build.rb +30 -0
- data/lib/spaceship/tunes/spaceship.rb +26 -0
- data/lib/spaceship/tunes/tester.rb +177 -0
- data/lib/spaceship/tunes/tunes.rb +12 -0
- data/lib/spaceship/tunes/tunes_base.rb +15 -0
- data/lib/spaceship/tunes/tunes_client.rb +360 -0
- data/lib/spaceship/version.rb +1 -1
- metadata +27 -7
- data/lib/spaceship/app.rb +0 -125
- data/lib/spaceship/certificate.rb +0 -271
- data/lib/spaceship/device.rb +0 -100
- 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
|