class MotionProvisioning::ProvisioningProfile

Attributes

platform[RW]
type[RW]

Public Instance Methods

client() click to toggle source
# File lib/motion-provisioning/provisioning_profile.rb, line 6
def client
  MotionProvisioning.client
end
profile_type() click to toggle source

The kind of provisioning profile we're interested in

# File lib/motion-provisioning/provisioning_profile.rb, line 125
def profile_type
  return @profile_type if @profile_type
  @profile_type = Spaceship::Portal.provisioning_profile.app_store
  @profile_type = Spaceship::Portal.provisioning_profile.in_house if client.in_house?
  @profile_type = Spaceship::Portal.provisioning_profile.ad_hoc if self.type == :adhoc
  @profile_type = Spaceship::Portal.provisioning_profile.development if self.type == :development
  @profile_type
end
provisioning_profile(bundle_id, app_name, platform, type) click to toggle source
# File lib/motion-provisioning/provisioning_profile.rb, line 10
def provisioning_profile(bundle_id, app_name, platform, type)
  self.type = type
  self.platform = platform
  output_path = MotionProvisioning.output_path
  provisioning_profile_path = File.join(output_path, "#{bundle_id}_#{platform}_#{type}_provisioning_profile.mobileprovision")
  provisioning_profile_name = "(MotionProvisioning) #{bundle_id} #{platform} #{type}"
  certificate_type = type == :development ? :development : :distribution
  certificate_platform = platform == :mac ? :mac : :ios
  certificate_path = File.join(output_path, "#{certificate_platform}_#{certificate_type}_certificate.cer")
  if !File.exist?(certificate_path)
    Utils.log('Error', "Couldn't find the certificate in path '#{certificate_path}'.")
    Utils.log('Error', "Make sure you're configuring the certificate *before* the provisioning profile in the Rakefile.")
    abort
  end

  if File.exist?(provisioning_profile_path) && ENV['recreate_profile'].nil?
    mobileprovision = MobileProvision.new(provisioning_profile_path)
    if mobileprovision.valid?(certificate_path, MotionProvisioning.entitlements)
      Utils.log('Info', "Using provisioning profile '#{mobileprovision.name}'.")
      return provisioning_profile_path
    end
  end

  client # ensure a client is created and logged in

  app = Application.find_or_create(bundle_id: bundle_id, name: app_name, mac: platform == :mac)

  profile = profile_type.find_by_bundle_id(bundle_id: bundle_id, mac: platform == :mac, sub_platform: ('tvOS' if platform == :tvos)).detect do |profile|
    next if profile.platform.downcase.include?("tvos") && platform != :tvos
    next if !profile.platform.downcase.include?("tvos") && platform == :tvos
    profile.name == provisioning_profile_name
  end

  # Offer to register devices connected to the current computer
  force_repair = false
  if ENV['MOTION_PROVISIONING_NO_REGISTER_DEVICES'].nil? && [:development, :adhoc].include?(type) && [:ios, :tvos].include?(platform)
    ids = `/Library/RubyMotion/bin/ios/deploy -D`.split("\n")

    # If there is a profile, we check the device is included.
    # Otherwise check if the device is registered in the Developer Portal.
    if profile
      profile_devices = profile.devices.map(&:udid).map(&:downcase)
      ids.each do |id|
        next if profile_devices.include?(id.downcase)
        answer = Utils.ask("Info", "This computer is connected to an iOS device with ID '#{id}' which is not included in the profile. Do you want to register it? (Y/n):")
        if answer.yes?
          Utils.log('Info', "Registering device with ID '#{id}'")
          Spaceship::Portal::Device.create!(name: 'iOS Device', udid: id)
          force_repair = true
        end
      end
    else
      ids.each do |id|
        existing = Spaceship::Portal::Device.find_by_udid(id)
        next if existing
        answer = Utils.ask("Info", "This computer is connected to an iOS device with ID '#{id}' which is not registered in the Developer Portal. Do you want to register it? (Y/n):")
        if answer.yes?
          Utils.log('Info', "Registering device with ID '#{id}'")
          client.create_device!('iOS Device', id)
        end
      end
    end
  end

  certificates = if type == :development
      client.development_certificates(mac: platform == :mac).map { |c| Spaceship::Portal::Certificate.factory(c) }
    else
      certificate_platform = platform == :mac ? :mac : :ios
      certificate_sha1 = OpenSSL::Digest::SHA1.new(File.read(File.join(output_path, "#{certificate_platform}_distribution_certificate.cer")))
      cert = client.distribution_certificates(mac: platform == :mac).detect do |c|
        # Compare downloaded cert content against local cert content to make sure they match
        OpenSSL::Digest::SHA1.new(c['certContent'].read) == certificate_sha1
      end

      if cert.nil?
        Utils.log('Error', 'Your distribution certificate is invalid. Recreate it by setting the env variable "recreate_certificate=1" and running the command again.')
        abort
      end

      # Distribution profiles can only contain one certificate
      [Spaceship::Portal::Certificate.factory(cert)]
    end

  if profile.nil?
    sub_platform = platform == :tvos ? 'tvOS' : nil
    Utils.log('Info', 'Could not find any existing profiles, creating a new one.')

    begin
      profile = profile_type.create!(name: provisioning_profile_name, bundle_id: bundle_id,
        certificate: certificates , devices: nil, mac: platform == :mac, sub_platform: sub_platform)
    rescue => ex
      if ex.to_s.include?("Your team has no devices")
        Utils.log("Error", "Your team has no devices for which to generate a provisioning profile. Connect a device to use for development or manually add device IDs by running: rake \"motion-provisioning:add-device[device_name,device_id]\"")
        abort
      end
      raise ex
    end
  elsif profile.status != 'Active' || profile.certificates.map(&:id) != certificates.map(&:id) || force_repair
    Utils.log('Info', "Repairing provisioning profile '#{profile.name}'.")
    profile.certificates = certificates
    devices = case platform
      when :tvos then Spaceship::Device.all_apple_tvs
      when :mac then Spaceship::Device.all_macs
      else Spaceship::Device.all_ios_profile_devices
      end
    profile.devices = type == :distribution ? [] : devices
    profile = profile.repair!
  end

  Utils.log('Info', "Using provisioning profile '#{profile.name}'.")
  File.write(provisioning_profile_path, profile.download)
  provisioning_profile_path
end