class Spaceship::Portal::ProvisioningProfile

Represents a provisioning profile of the Apple Dev Portal

Attributes

app[RW]

A reference to the app this profile is for. You can then easily access the value directly @return (App) The app this profile is for

@example 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>

@example Usage

profile.app.name
certificates[RW]

@return (Array) A list of certificates used for this profile @example 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">]
]

@example Usage

profile.certificates.first.id
devices[RW]

@return (Array) A list of devices this profile is enabled for.

This will always be [] for AppStore profiles

@example Example Value

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

@example Usage

profile.devices.first.name
distribution_method[RW]

@return (String) The profile distribution type. You probably want to

use the class type to detect the profile type instead of this string.

@example AppStore Profile

"store"

@example AdHoc Profile

"adhoc"

@example Development Profile

"limited"

@example Mac Developer ID Profile

"direct"
expires[RW]

@return (DateTime) The date and time of when the profile

expires.

@example

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

@return (String) The ID generated by the Dev Portal

You'll probably not really need this value

@example

"2MAY7NPHAA"
managing_app[RW]

No information about this attribute

name[RW]

@return (String) The name of this profile @example

"com.krausefx.app AppStore"
platform[RW]

@return (String) The supported platform for this profile @example

"ios"
profile_details[RW]

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

status[RW]

@return (String) The status of this profile @example Active (profile is fine)

"Active"

@example Expired (time ran out)

"Expired"

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

"Invalid"
type[RW]

@return (String) The type of the profile (development or distribution).

You'll probably not need this value

@example Distribution

"iOS Distribution"

@example Development

"iOS Development"
uuid[RW]

@return (String) The UDID of this provisioning profile

This value is used for example for code signing
It is also contained in the actual profile

@example

"23d7df3b-9767-4e85-a1ea-1df4d8f32fec"
version[RW]

@return (String) This will always be “2” @example

"2"

Public Class Methods

all(mac: false) click to toggle source

@return (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
# 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) click to toggle source

Create a new provisioning profile @param name (String): The name of the provisioning profile on the Dev Portal @param bundle_id (String): The app identifier, this paramter is required @param certificate (Certificate): 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

@param devices (Array) (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

@param mac (Bool) (optional): Pass true if you're making a Mac provisioning profile @param sub_platform (String) Used to create tvOS profiles at the moment. Value should equal 'tvOS' or nil. @return (ProvisioningProfile): The profile that was just created

# 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) click to toggle source

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

# 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) click to toggle source

@return (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
# 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_type() click to toggle source

@return (String) The human readable name of this profile type. @example

"AppStore"
"AdHoc"
"Development"
"InHouse"
# File lib/spaceship/portal/provisioning_profile.rb, line 186
def pretty_type
  name.split('::').last
end
type() click to toggle source

@return (String) The profile type used for web requests to the Dev Portal @example

"limited"
"store"
"adhoc"
"inhouse"
# File lib/spaceship/portal/provisioning_profile.rb, line 150
def type
  raise "You cannot create a ProvisioningProfile without a type. Use a subclass."
end

Public Instance Methods

certificate_valid?() click to toggle source

Is the certificate of this profile available? @return (Bool) is the certificate valid?

# 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!() click to toggle source

Delete the provisioning profile

# File lib/spaceship/portal/provisioning_profile.rb, line 337
def delete!
  client.delete_provisioning_profile!(self.id, mac: mac?)
end
download() click to toggle source

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. @return (String) The content of the provisioning profile

You'll probably want to store it on the file system

@example

File.write("path.mobileprovision", profile.download)
# File lib/spaceship/portal/provisioning_profile.rb, line 332
def download
  client.download_provisioning_profile(self.id, mac: mac?)
end
is_adhoc?() click to toggle source

@return (Bool) Is this current provisioning profile adhoc?

AppStore and AdHoc profiles are the same except that AdHoc has devices
# File lib/spaceship/portal/provisioning_profile.rb, line 452
def is_adhoc?
  return false unless self.kind_of?(AppStore) || self.kind_of?(AdHoc)

  return devices.count > 0
end
mac?() click to toggle source

@return (Bool) Is this a Mac provisioning profile?

# File lib/spaceship/portal/provisioning_profile.rb, line 422
def mac?
  platform == 'mac'
end
managed_by_xcode?() click to toggle source

@return (Bool) Is this profile managed by Xcode?

# File lib/spaceship/portal/provisioning_profile.rb, line 417
def managed_by_xcode?
  managing_app == 'Xcode'
end
repair!() click to toggle source

Repair an existing provisioning profile alias to update! @return (ProvisioningProfile) A new provisioning profile, as

the repair method will generate a profile with a new ID
# File lib/spaceship/portal/provisioning_profile.rb, line 345
def repair!
  update!
end
update!() click to toggle source

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 @return (ProvisioningProfile) A new provisioning profile, as

the repair method will generate a profile with a new ID
# 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?() click to toggle source

@return (Bool) Is the current provisioning profile valid?

To also verify the certificate call certificate_valid?
# File lib/spaceship/portal/provisioning_profile.rb, line 412
def valid?
  return status == 'Active'
end

Private Instance Methods

fetch_details() click to toggle source
# File lib/spaceship/portal/provisioning_profile.rb, line 460
def fetch_details
  # Since 15th September 2016 certificates and devices are hidden behind another request
  # see https://github.com/fastlane/fastlane/issues/6137 for more information
  self.profile_details ||= client.provisioning_profile_details(provisioning_profile_id: self.id, mac: mac?)
end