Class: Spaceship::Portal::ProvisioningProfile

Inherits:
Spaceship::PortalBase show all
Defined in:
lib/spaceship/portal/provisioning_profile.rb

Overview

Represents a provisioning profile of the Apple Dev Portal

Direct Known Subclasses

AdHoc, AppStore, Development, Direct, InHouse

Defined Under Namespace

Classes: AdHoc, AppStore, Development, Direct, InHouse

Instance Attribute Summary collapse

Attributes inherited from Base

#client, #raw_data

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Spaceship::PortalBase

client

Methods inherited from Base

attr_accessor, attr_mapping, #attributes, attributes, #initialize, #inspect, mapping_module, method_missing, set_client, #setup, #to_s

Constructor Details

This class inherits a constructor from Spaceship::Base

Instance Attribute Details

#appApp

A reference to the app this profile is for. You can then easily access the value directly

Examples:

Example Value

<Spaceship::App
  @app_id="2UMR2S6PAA"
  @name="App Name"
  @platform="ios"
  @prefix="5A997XSAAA"
  @bundle_id="com.krausefx.app"
  @is_wildcard=false
  @dev_push_enabled=false
  @prod_push_enabled=false>

Usage

profile.app.name

Returns:

  • (App)

    The app this profile is for



88
89
90
# File 'lib/spaceship/portal/provisioning_profile.rb', line 88

def app
  @app
end

#certificatesArray

Returns A list of certificates used for this profile.

Examples:

Example Value

[
 <Spaceship::Certificate::Production
   @status=nil
   @id="XC5PH8D4AA"
   @name="iOS Distribution"
   @created=nil
   @expires=#<DateTime: 2015-11-25T22:45:50+00:00 ((2457352j,81950s,0n),+0s,2299161j)>
   @owner_type="team"
   @owner_name=nil
   @owner_id=nil
   @type_display_id="R58UK2EWAA">]
]

Usage

profile.certificates.first.id

Returns:

  • (Array)

    A list of certificates used for this profile



107
108
109
# File 'lib/spaceship/portal/provisioning_profile.rb', line 107

def certificates
  @certificates
end

#devicesArray

Returns A list of devices this profile is enabled for. This will always be [] for AppStore profiles.

Examples:

Example Value

<Spaceship::Device
  @id="WXQ7V239BE"
  @name="Grahams iPhone 4s"
  @udid="ba0ac7d70f7a14c6fa02ef0e02f4fe9c5178e2f7"
  @platform="ios"
  @status="c">]

Usage

profile.devices.first.name

Returns:

  • (Array)

    A list of devices this profile is enabled for. This will always be [] for AppStore profiles



122
123
124
# File 'lib/spaceship/portal/provisioning_profile.rb', line 122

def devices
  @devices
end

#distribution_methodString

Returns The profile distribution type. You probably want to use the class type to detect the profile type instead of this string.

Examples:

AppStore Profile

"store"

AdHoc Profile

"adhoc"

Development Profile

"limited"

Mac Developer ID Profile

"direct"

Returns:

  • (String)

    The profile distribution type. You probably want to use the class type to detect the profile type instead of this string.



34
35
36
# File 'lib/spaceship/portal/provisioning_profile.rb', line 34

def distribution_method
  @distribution_method
end

#expiresDateTime

Returns The date and time of when the profile expires.

Examples:

#<DateTime: 2015-11-25T22:45:50+00:00 ((2457352j,81950s,0n),+0s,2299161j)>

Returns:

  • (DateTime)

    The date and time of when the profile expires.



22
23
24
# File 'lib/spaceship/portal/provisioning_profile.rb', line 22

def expires
  @expires
end

#idString

Returns The ID generated by the Dev Portal You’ll probably not really need this value.

Examples:

"2MAY7NPHAA"

Returns:

  • (String)

    The ID generated by the Dev Portal You’ll probably not really need this value



9
10
11
# File 'lib/spaceship/portal/provisioning_profile.rb', line 9

def id
  @id
end

#managing_appObject

No information about this attribute



69
70
71
# File 'lib/spaceship/portal/provisioning_profile.rb', line 69

def managing_app
  @managing_app
end

#nameString

Returns The name of this profile.

Examples:

"com.krausefx.app AppStore"

Returns:

  • (String)

    The name of this profile



39
40
41
# File 'lib/spaceship/portal/provisioning_profile.rb', line 39

def name
  @name
end

#platformString

Returns The supported platform for this profile.

Examples:

"ios"

Returns:

  • (String)

    The supported platform for this profile



66
67
68
# File 'lib/spaceship/portal/provisioning_profile.rb', line 66

def platform
  @platform
end

#profile_detailsObject

This is the second level request, which is done before creating the object this includes information about the devices and the certificates more information on this issue github.com/fastlane/fastlane/issues/6137



127
128
129
# File 'lib/spaceship/portal/provisioning_profile.rb', line 127

def profile_details
  @profile_details
end

#statusString

Returns The status of this profile.

Examples:

Active (profile is fine)

"Active"

Expired (time ran out)

"Expired"

Invalid (e.g. code signing identity not available any more)

"Invalid"

Returns:

  • (String)

    The status of this profile



48
49
50
# File 'lib/spaceship/portal/provisioning_profile.rb', line 48

def status
  @status
end

#typeString

Returns The type of the profile (development or distribution). You’ll probably not need this value.

Examples:

Distribution

"iOS Distribution"

Development

"iOS Development"

Returns:

  • (String)

    The type of the profile (development or distribution). You’ll probably not need this value



56
57
58
# File 'lib/spaceship/portal/provisioning_profile.rb', line 56

def type
  @type
end

#uuidString

Returns The UDID of this provisioning profile This value is used for example for code signing It is also contained in the actual profile.

Examples:

"23d7df3b-9767-4e85-a1ea-1df4d8f32fec"

Returns:

  • (String)

    The UDID of this provisioning profile This value is used for example for code signing It is also contained in the actual profile



16
17
18
# File 'lib/spaceship/portal/provisioning_profile.rb', line 16

def uuid
  @uuid
end

#versionString

Returns This will always be “2”.

Examples:

"2"

Returns:

  • (String)

    This will always be “2”



61
62
63
# File 'lib/spaceship/portal/provisioning_profile.rb', line 61

def version
  @version
end

Class Method Details

.all(mac: false) ⇒ Array

Returns all profiles registered for this account If you’re calling this from a subclass (like AdHoc), this will only return the profiles that are of this type

Returns:

  • (Array)

    Returns all profiles registered for this account If you’re calling this from a subclass (like AdHoc), this will only return the profiles that are of this type



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/spaceship/portal/provisioning_profile.rb', line 252

def all(mac: false)
  profiles = client.provisioning_profiles(mac: mac).map do |profile|
    self.factory(profile)
  end

  # filter out the profiles managed by xcode
  profiles.delete_if(&:managed_by_xcode?)

  return profiles if self == ProvisioningProfile

  # To distinguish between AppStore and AdHoc profiles, we need to send
  # a details request (see `fetch_details`). This is an expensive operation
  # which we can't do for every single provisioning profile
  # Instead we'll treat App Store profiles the same way as Ad Hoc profiles
  # Spaceship::ProvisioningProfile::AdHoc.all will return the same array as
  # Spaceship::ProvisioningProfile::AppStore.all, containing only AppStore
  # profiles. To determine if it's an Ad Hoc profile, you can use the
  # is_adhoc? method on the profile.
  klass = self
  klass = AppStore if self == AdHoc

  # only return the profiles that match the class
  return profiles.select do |profile|
    profile.class == klass
  end
end

.create!(name: nil, bundle_id: nil, certificate: nil, devices: [], mac: false, sub_platform: nil) ⇒ ProvisioningProfile

Create a new provisioning profile

Parameters:

  • name (String) (defaults to: nil)

    : The name of the provisioning profile on the Dev Portal

  • bundle_id (String) (defaults to: nil)

    : The app identifier, this paramter is required

  • certificate (Certificate) (defaults to: nil)

    : The certificate that should be used with this provisioning profile. You can also pass an array of certificates to this method. This will only work for development profiles

  • devices (Array) (defaults to: [])

    (optional): An array of Device objects that should be used in this profile. It is recommend to not pass devices as spaceship will automatically add all devices for AdHoc and Development profiles and add none for AppStore and Enterprise Profiles

  • mac (Bool) (defaults to: false)

    (optional): Pass true if you’re making a Mac provisioning profile

  • sub_platform (String) (defaults to: nil)

    Used to create tvOS profiles at the moment. Value should equal ‘tvOS’ or nil.

Returns:



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/spaceship/portal/provisioning_profile.rb', line 202

def create!(name: nil, bundle_id: nil, certificate: nil, devices: [], mac: false, sub_platform: nil)
  raise "Missing required parameter 'bundle_id'" if bundle_id.to_s.empty?
  raise "Missing required parameter 'certificate'. e.g. use `Spaceship::Certificate::Production.all.first`" if certificate.to_s.empty?

  app = Spaceship::App.find(bundle_id, mac: mac)
  raise "Could not find app with bundle id '#{bundle_id}'" unless app

  # Fill in sensible default values
  name ||= [bundle_id, self.pretty_type].join(' ')

  if self == AppStore || self == InHouse || self == Direct
    # Distribution Profiles MUST NOT have devices
    devices = []
  end

  certificate_parameter = certificate.collect(&:id) if certificate.kind_of? Array
  certificate_parameter ||= [certificate.id]

  # Fix https://github.com/KrauseFx/fastlane/issues/349
  certificate_parameter = certificate_parameter.first if certificate_parameter.count == 1

  if devices.nil? or devices.count == 0
    if self == Development or self == AdHoc
      # For Development and AdHoc we usually want all compatible devices by default
      if mac
        devices = Spaceship::Device.all_macs
      elsif sub_platform == 'tvOS'
        devices = Spaceship::Device.all_apple_tvs
      else
        devices = Spaceship::Device.all_ios_profile_devices
      end
    end
  end

  profile = client.with_retry do
    client.create_provisioning_profile!(name,
                                        self.type,
                                        app.app_id,
                                        certificate_parameter,
                                        devices.map(&:id),
                                        mac: mac,
                                        sub_platform: sub_platform)
  end

  self.new(profile)
end

.factory(attrs) ⇒ Object

Create a new object based on a hash. This is used to create a new object based on the server response.



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/spaceship/portal/provisioning_profile.rb', line 156

def factory(attrs)
  # available values of `distributionMethod` at this point: ['adhoc', 'store', 'limited', 'direct']
  klass = case attrs['distributionMethod']
          when 'limited'
            Development
          when 'store'
            AppStore
          when 'inhouse'
            InHouse
          when 'direct'
            Direct # Mac-only
          else
            raise "Can't find class '#{attrs['distributionMethod']}'"
          end

  # eagerload the Apps using the same client if we have to.
  attrs['appId'] = App.set_client(@client).factory(attrs['appId'])

  klass.client = @client
  obj = klass.new(attrs)

  return obj
end

.find_by_bundle_id(bundle_id, mac: false) ⇒ Array

Returns an array of provisioning profiles matching the bundle identifier Returns [] if no profiles were found This may also contain invalid or expired profiles

Returns:

  • (Array)

    Returns an array of provisioning profiles matching the bundle identifier Returns [] if no profiles were found This may also contain invalid or expired profiles



283
284
285
286
287
# File 'lib/spaceship/portal/provisioning_profile.rb', line 283

def find_by_bundle_id(bundle_id, mac: false)
  all(mac: mac).find_all do |profile|
    profile.app.bundle_id == bundle_id
  end
end

.pretty_typeString

Returns The human readable name of this profile type.

Examples:

"AppStore"
"AdHoc"
"Development"
"InHouse"

Returns:

  • (String)

    The human readable name of this profile type.



186
187
188
# File 'lib/spaceship/portal/provisioning_profile.rb', line 186

def pretty_type
  name.split('::').last
end

.typeString

Returns The profile type used for web requests to the Dev Portal.

Examples:

"limited"
"store"
"adhoc"
"inhouse"

Returns:

  • (String)

    The profile type used for web requests to the Dev Portal



150
151
152
# File 'lib/spaceship/portal/provisioning_profile.rb', line 150

def type
  raise "You cannot create a ProvisioningProfile without a type. Use a subclass."
end

Instance Method Details

#certificate_valid?Bool

Is the certificate of this profile available?

Returns:

  • (Bool)

    is the certificate valid?



400
401
402
403
404
405
406
407
408
# File 'lib/spaceship/portal/provisioning_profile.rb', line 400

def certificate_valid?
  return false if (certificates || []).count == 0
  certificates.each do |c|
    if Spaceship::Certificate.all(mac: mac?).collect(&:id).include?(c.id)
      return true
    end
  end
  return false
end

#delete!Object

Delete the provisioning profile



337
338
339
# File 'lib/spaceship/portal/provisioning_profile.rb', line 337

def delete!
  client.delete_provisioning_profile!(self.id, mac: mac?)
end

#downloadString

Download the current provisioning profile. This will not store the provisioning profile on the file system. Instead this method will return the content of the profile.

Examples:

File.write("path.mobileprovision", profile.download)

Returns:

  • (String)

    The content of the provisioning profile You’ll probably want to store it on the file system



332
333
334
# File 'lib/spaceship/portal/provisioning_profile.rb', line 332

def download
  client.download_provisioning_profile(self.id, mac: mac?)
end

#is_adhoc?Bool

Returns Is this current provisioning profile adhoc? AppStore and AdHoc profiles are the same except that AdHoc has devices.

Returns:

  • (Bool)

    Is this current provisioning profile adhoc? AppStore and AdHoc profiles are the same except that AdHoc has devices



448
449
450
451
452
# File 'lib/spaceship/portal/provisioning_profile.rb', line 448

def is_adhoc?
  return false unless self.kind_of?(AppStore) || self.kind_of?(AdHoc)

  return devices.count > 0
end

#mac?Bool

Returns Is this a Mac provisioning profile?.

Returns:

  • (Bool)

    Is this a Mac provisioning profile?



422
423
424
# File 'lib/spaceship/portal/provisioning_profile.rb', line 422

def mac?
  platform == 'mac'
end

#managed_by_xcode?Bool

Returns Is this profile managed by Xcode?.

Returns:

  • (Bool)

    Is this profile managed by Xcode?



417
418
419
# File 'lib/spaceship/portal/provisioning_profile.rb', line 417

def managed_by_xcode?
  managing_app == 'Xcode'
end

#repair!ProvisioningProfile

Repair an existing provisioning profile alias to update!

Returns:

  • (ProvisioningProfile)

    A new provisioning profile, as the repair method will generate a profile with a new ID



345
346
347
# File 'lib/spaceship/portal/provisioning_profile.rb', line 345

def repair!
  update!
end

#update!ProvisioningProfile

Updates the provisioning profile from the local data e.g. after you added new devices to the profile This will also update the code signing identity if necessary

Returns:

  • (ProvisioningProfile)

    A new provisioning profile, as the repair method will generate a profile with a new ID



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/spaceship/portal/provisioning_profile.rb', line 354

def update!
  # sigh handles more specific filtering and validation steps that make this logic OK
  #
  # This is the minimum protection needed for people using spaceship directly
  unless certificate_valid?
    if mac?
      if self.kind_of? Development
        self.certificates = [Spaceship::Certificate::MacDevelopment.all.first]
      elsif self.kind_of? Direct
        self.certificates = [Spaceship::Certificate::DeveloperIDApplication.all.first]
      else
        self.certificates = [Spaceship::Certificate::MacAppDistribution.all.first]
      end
    else
      if self.kind_of? Development
        self.certificates = [Spaceship::Certificate::Development.all.first]
      elsif self.kind_of? InHouse
        self.certificates = [Spaceship::Certificate::InHouse.all.first]
      else
        self.certificates = [Spaceship::Certificate::Production.all.first]
      end
    end
  end

  client.with_retry do
    client.repair_provisioning_profile!(
      id,
      name,
      distribution_method,
      app.app_id,
      certificates.map(&:id),
      devices.map(&:id),
      mac: mac?
    )
  end

  # We need to fetch the provisioning profile again, as the ID changes
  profile = Spaceship::ProvisioningProfile.all(mac: mac?).find do |p|
    p.name == self.name # we can use the name as it's valid
  end

  return profile
end

#valid?Bool

Returns Is the current provisioning profile valid? To also verify the certificate call certificate_valid?.

Returns:

  • (Bool)

    Is the current provisioning profile valid? To also verify the certificate call certificate_valid?



412
413
414
# File 'lib/spaceship/portal/provisioning_profile.rb', line 412

def valid?
  return status == 'Active'
end