Class: MotionProvisioning::ProvisioningProfile

Inherits:
Object
  • Object
show all
Defined in:
lib/motion-provisioning/provisioning_profile.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#platformObject

Returns the value of attribute platform.



4
5
6
# File 'lib/motion-provisioning/provisioning_profile.rb', line 4

def platform
  @platform
end

#typeObject

Returns the value of attribute type.



4
5
6
# File 'lib/motion-provisioning/provisioning_profile.rb', line 4

def type
  @type
end

Instance Method Details

#clientObject



6
7
8
# File 'lib/motion-provisioning/provisioning_profile.rb', line 6

def client
  MotionProvisioning.client
end

#profile_typeObject

The kind of provisioning profile we’re interested in



125
126
127
128
129
130
131
132
# 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) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# 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