Permalink
Switch branches/tags
KrauseFx-patch-1 KrauseFx-patch-2 KrauseFx-patch-3 KrauseFx-patch-4 KrauseFx-patch-5 KrauseFx-patch-6 Tomoy-tomas_title_font_size add-context-for-scan-build-zip adding-changelog additional-options after-monogem app-icon-path before-monogem ci-test fastlane-janpio-managed_google_play fix-adp-probs fix-fastlane-version init janpio-4k_apple_tv janpio-circle_docs_artifact janpio-fix_coveralls janpio-fix_tunes2 janpio-is_compatible janpio-is_incompatible janpio-managed_google_play_extract_supply_client janpio-match_windows janpio-match_windows_2 janpio-more_itunes_transporter_tests janpio-more_require_work janpio-path_nil_appfile_rebased janpio-path_nil_old janpio-path_nil janpio-slim_fastlane_core janpio-validate_play_store_json_key_2 joshdholtz-download_dsym-fix-build-id joshdholtz-fix-latest_testflight_build_number joshdholtz-frameit-ipad-pro-10_5-and-9_7 joshdholtz-get-and-filter-by-adb-device-name joshdholtz-make-gym-mac-again joshdholtz-no-spaces-in-ipa-name joshdholtz-post_for_testflight_review-new-api joshdholtz-remote-and-lint-configitem-is_string joshdholtz-snapshot-rows-by-screenshot json-api kms lane-warning master mgrebenets/swiftlint-quiet minuscorp-patch-1 more-require-work require-relative-best-require scorpion35-reviews_uptodate screen-grid select-scheme-on-setup setup-ci-match-readonly silence snatchev/inspect-circular-references swift-optionality swift-run-script-quotes swiftlint-quiet tablexi-webpush_certificates-rebase update-docs update-release-url updatedet version-bump-2.74.3 wip-pilot-submit-for-testers xcode9-snapshot-ready-for-config-item
Nothing to show
Find file Copy path
205 lines (174 sloc) 8.04 KB
require 'shellwords'
require 'fastlane_core/globals'
require_relative 'module'
module Sigh
# Resigns an existing ipa file
class Resign
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
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
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
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
end
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
def find_resign_path
File.join(Sigh::ROOT, 'lib', 'assets', 'resign.sh')
end
def find_ipa
Dir[File.join(Dir.pwd, '*.ipa')].sort { |a, b| File.mtime(a) <=> File.mtime(b) }.first
end
def find_provisioning_profile
Dir[File.join(Dir.pwd, '*.mobileprovision')].sort { |a, b| File.mtime(a) <=> File.mtime(b) }.first
end
def find_signing_identity(signing_identity)
until (signing_identity = sha1_for_signing_identity(signing_identity))
UI.error("Couldn't find signing identity '#{signing_identity}'.")
signing_identity = ask_for_signing_identity
end
signing_identity
end
def sha1_for_signing_identity(signing_identity)
identities = installed_identities
return signing_identity if identities.keys.include?(signing_identity)
identities.key(signing_identity)
end
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
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
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
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
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
def print_available_identities
UI.message("Available identities: \n\t#{installed_identity_descriptions.join("\n\t")}\n")
end
def ask_for_signing_identity
print_available_identities
UI.input('Signing Identity: ')
end
# Hash of available signing identities
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
def request_valid_identities
`security find-identity -v -p codesigning`
end
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
end
end