class Sigh::Resign

Resigns an existing ipa file

Public Class Methods

resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path) click to toggle source
# File sigh/lib/sigh/resign.rb, line 18
def self.resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
  self.new.resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
end

Public Instance Methods

ask_for_signing_identity() click to toggle source
# File sigh/lib/sigh/resign.rb, line 182
def ask_for_signing_identity
  print_available_identities
  UI.input('Signing Identity: ')
end
create_provisioning_options(provisioning_profiles) click to toggle source
# File sigh/lib/sigh/resign.rb, line 136
def create_provisioning_options(provisioning_profiles)
  # provisioning_profiles is passed either a hash (to be able to resign extensions/nested apps):
  # (in that case the underlying resign.sh expects values given as "-p at.fastlane=/folder/mobile.mobileprovision -p at.fastlane.today=/folder/mobile.mobileprovision")
  #   {
  #     "at.fastlane" => "/folder/mobile.mobileprovision",
  #     "at.fastlane.today" => "/folder/mobile.mobileprovision"
  #   }
  # or an array
  # (resign.sh also takes "-p /folder/mobile.mobileprovision" as a param)
  #   [
  #        "/folder/mobile.mobileprovision"
  #   ]
  provisioning_profiles.map do |app_id, app_id_prov|
    if app_id_prov
      app_id_prov = File.expand_path(app_id_prov)
    else
      app_id = File.expand_path(app_id)
    end
    "-p #{[app_id, app_id_prov].compact.map(&:shellescape).join('=')}"
  end.join(' ')
end
find_ipa() click to toggle source
# File sigh/lib/sigh/resign.rb, line 112
def find_ipa
  Dir[File.join(Dir.pwd, '*.ipa')].sort { |a, b| File.mtime(a) <=> File.mtime(b) }.first
end
find_provisioning_profile() click to toggle source
# File sigh/lib/sigh/resign.rb, line 116
def find_provisioning_profile
  Dir[File.join(Dir.pwd, '*.mobileprovision')].sort { |a, b| File.mtime(a) <=> File.mtime(b) }.first
end
find_resign_path() click to toggle source
# File sigh/lib/sigh/resign.rb, line 108
def find_resign_path
  File.join(Sigh::ROOT, 'lib', 'assets', 'resign.sh')
end
find_signing_identity(signing_identity) click to toggle source
# File sigh/lib/sigh/resign.rb, line 120
def find_signing_identity(signing_identity)
  signing_identity_input = signing_identity
  until (signing_identity = sha1_for_signing_identity(signing_identity_input))
    UI.error("Couldn't find signing identity '#{signing_identity_input}'.")
    signing_identity_input = ask_for_signing_identity
  end

  signing_identity
end
get_inputs(options, args) click to toggle source
# File sigh/lib/sigh/resign.rb, line 88
def get_inputs(options, args)
  ipa = args.first || find_ipa || UI.input('Path to ipa file: ')
  signing_identity = options.signing_identity || ask_for_signing_identity
  provisioning_profiles = options.provisioning_profile || find_provisioning_profile || UI.input('Path to provisioning file: ')
  entitlements = options.entitlements || nil
  version = options.version_number || nil
  display_name = options.display_name || nil
  short_version = options.short_version || nil
  bundle_version = options.bundle_version || nil
  new_bundle_id = options.new_bundle_id || nil
  use_app_entitlements = options.use_app_entitlements || nil
  keychain_path = options.keychain_path || nil

  if options.provisioning_name
    UI.important("The provisioning_name (-n) option is not applicable to resign. You should use provisioning_profile (-p) instead")
  end

  return ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path
end
installed_identities() click to toggle source

Hash of available signing identities

# File sigh/lib/sigh/resign.rb, line 188
def installed_identities
  available = request_valid_identities
  ids = {}
  available.split("\n").each do |current|
    begin
      sha1 = current.match(/[a-zA-Z0-9]{40}/).to_s
      name = current.match(/.*\"(.*)\"/)[1]
      ids[sha1] = name
    rescue
      nil
    end # the last line does not match
  end

  ids
end
installed_identity_descriptions() click to toggle source
# File sigh/lib/sigh/resign.rb, line 208
def installed_identity_descriptions
  descriptions = []
  installed_identities.group_by { |sha1, name| name }.each do |name, identities|
    descriptions << name
    # Show SHA-1 for homonymous identities
    descriptions += identities.map do |sha1, _|
      "\t#{sha1}"
    end
  end
  descriptions
end
print_available_identities() click to toggle source
request_valid_identities() click to toggle source
# File sigh/lib/sigh/resign.rb, line 204
def request_valid_identities
  `security find-identity -v -p codesigning`
end
resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path) click to toggle source
# File sigh/lib/sigh/resign.rb, line 22
def resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
  resign_path = find_resign_path

  if keychain_path
    keychain_path_absolute = File.expand_path(keychain_path)

    current_keychains = `security list-keychains`
    current_keychains.delete!("\n")

    unless current_keychains.include?(keychain_path_absolute)
      previous_keychains = current_keychains
      `security list-keychains -s #{current_keychains} '#{keychain_path_absolute}'`
    end
  end

  signing_identity = find_signing_identity(signing_identity)

  unless provisioning_profiles.kind_of?(Enumerable)
    provisioning_profiles = [provisioning_profiles]
  end

  # validate that we have valid values for all these params, we don't need to check signing_identity because `find_signing_identity` will only ever return a valid value
  validate_params(resign_path, ipa, provisioning_profiles)
  entitlements = "-e #{entitlements.shellescape}" if entitlements

  provisioning_options = create_provisioning_options(provisioning_profiles)
  version = "-n #{version}" if version
  display_name = "-d #{display_name.shellescape}" if display_name
  short_version = "--short-version #{short_version}" if short_version
  bundle_version = "--bundle-version #{bundle_version}" if bundle_version
  verbose = "-v" if FastlaneCore::Globals.verbose?
  bundle_id = "-b '#{new_bundle_id}'" if new_bundle_id
  use_app_entitlements_flag = "--use-app-entitlements" if use_app_entitlements
  specific_keychain = "--keychain-path #{keychain_path.shellescape}" if keychain_path

  command = [
    resign_path.shellescape,
    ipa.shellescape,
    signing_identity.shellescape,
    provisioning_options, # we are aleady shellescaping this above, when we create the provisioning_options from the provisioning_profiles
    entitlements,
    version,
    display_name,
    short_version,
    bundle_version,
    use_app_entitlements_flag,
    verbose,
    bundle_id,
    specific_keychain,
    ipa.shellescape # Output path must always be last argument
  ].join(' ')

  puts(command.magenta)
  puts(`#{command}`)

  if $?.to_i == 0
    UI.success("Successfully signed #{ipa}!")
    true
  else
    UI.error("Something went wrong while code signing #{ipa}")
    false
  end
ensure
  `security list-keychains -s #{previous_keychains}` if previous_keychains
end
run(options, args) click to toggle source
# File sigh/lib/sigh/resign.rb, line 9
def run(options, args)
  # get the command line inputs and parse those into the vars we need...
  ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path = get_inputs(options, args)
  # ... then invoke our programmatic interface with these vars
  unless resign(ipa, signing_identity, provisioning_profiles, entitlements, version, display_name, short_version, bundle_version, new_bundle_id, use_app_entitlements, keychain_path)
    UI.user_error!("Failed to re-sign .ipa")
  end
end
sha1_for_signing_identity(signing_identity) click to toggle source
# File sigh/lib/sigh/resign.rb, line 130
def sha1_for_signing_identity(signing_identity)
  identities = installed_identities
  return signing_identity if identities.keys.include?(signing_identity)
  identities.key(signing_identity)
end
validate_ipa_file(ipa) click to toggle source
# File sigh/lib/sigh/resign.rb, line 168
def validate_ipa_file(ipa)
  UI.user_error!("ipa file could not be found or is not an ipa file (#{ipa})") unless File.exist?(ipa) && ipa.end_with?('.ipa')
end
validate_params(resign_path, ipa, provisioning_profiles) click to toggle source
# File sigh/lib/sigh/resign.rb, line 158
def validate_params(resign_path, ipa, provisioning_profiles)
  validate_resign_path(resign_path)
  validate_ipa_file(ipa)
  provisioning_profiles.each { |fst, snd| validate_provisioning_file(snd || fst) }
end
validate_provisioning_file(provisioning_profile) click to toggle source
# File sigh/lib/sigh/resign.rb, line 172
def validate_provisioning_file(provisioning_profile)
  unless File.exist?(provisioning_profile) && provisioning_profile.end_with?('.mobileprovision')
    UI.user_error!("Provisioning profile file could not be found or is not a .mobileprovision file (#{provisioning_profile})")
  end
end
validate_resign_path(resign_path) click to toggle source
# File sigh/lib/sigh/resign.rb, line 164
def validate_resign_path(resign_path)
  UI.user_error!('Could not find resign.sh file. Please try re-installing the gem') unless File.exist?(resign_path)
end