class Gym::DetectValues

This class detects all kinds of default values

Public Class Methods

archive_path_from_local_xcode_preferences() click to toggle source
# File gym/lib/gym/detect_values.rb, line 50
def self.archive_path_from_local_xcode_preferences
  day = Time.now.strftime("%F") # e.g. 2015-08-07
  archive_path = File.expand_path("~/Library/Developer/Xcode/Archives/#{day}/")

  return archive_path unless has_xcode_preferences_plist?

  custom_archive_path = xcode_preferences_dictionary['IDECustomDistributionArchivesLocation']
  return archive_path if custom_archive_path.to_s.length == 0

  return File.join(custom_archive_path, day)
end
detect_configuration() click to toggle source

Detects the available configurations (e.g. Debug, Release)

# File gym/lib/gym/detect_values.rb, line 161
def self.detect_configuration
  config = Gym.config
  configurations = Gym.project.configurations
  return if configurations.count == 0 # this is an optional value anyway

  if config[:configuration]
    # Verify the configuration is available
    unless configurations.include?(config[:configuration])
      UI.error("Couldn't find specified configuration '#{config[:configuration]}'.")
      config[:configuration] = nil
    end
  end
end
detect_platform() click to toggle source

Is it an iOS device or a Mac?

# File gym/lib/gym/detect_values.rb, line 145
def self.detect_platform
  return if Gym.config[:destination]

  platform = if Gym.project.tvos?
               "tvOS"
             elsif Gym.building_for_ios?
               "iOS"
             elsif Gym.building_for_mac?
               min_xcode8? ? "macOS" : "OS X"
             else
               "iOS"
             end
  Gym.config[:destination] = "generic/platform=#{platform}"
end
detect_scheme() click to toggle source
# File gym/lib/gym/detect_values.rb, line 136
def self.detect_scheme
  Gym.project.select_scheme
end
detect_selected_provisioning_profiles() click to toggle source

Since Xcode 9 you need to provide the explicit mapping of what provisioning profile to use for each target of your app

# File gym/lib/gym/detect_values.rb, line 79
def self.detect_selected_provisioning_profiles
  Gym.config[:export_options] ||= {}
  hash_to_use = (Gym.config[:export_options][:provisioningProfiles] || {}).dup || {} # dup so we can show the original values in `verbose` mode

  unless Gym.config[:skip_profile_detection]
    mapping_object = CodeSigningMapping.new(project: Gym.project)
    hash_to_use = mapping_object.merge_profile_mapping(primary_mapping: hash_to_use,
                                                       export_method: Gym.config[:export_method])
  end

  return if hash_to_use.count == 0 # We don't want to set a mapping if we don't have one
  Gym.config[:export_options][:provisioningProfiles] = hash_to_use
  UI.message("Detected provisioning profile mapping: #{hash_to_use}")
rescue => ex
  # We don't want to fail the build if the automatic detection doesn't work
  # especially since the mapping is optional for pre Xcode 9 setups
  if Helper.xcode_at_least?("9.0")
    UI.error("Couldn't automatically detect the provisioning profile mapping")
    UI.error("Since Xcode 9 you need to provide an explicit mapping of what")
    UI.error("provisioning profile to use for each target of your app")
    UI.error(ex)
    UI.verbose(ex.backtrace.join("\n"))
  end
end
detect_third_party_installer() click to toggle source

Detects name of a “3rd Party Mac Developer Installer” cert for the configured team id

# File gym/lib/gym/detect_values.rb, line 105
def self.detect_third_party_installer
  return if Gym.config[:installer_cert_name]

  team_id = Gym.config[:export_team_id] || Gym.project.build_settings(key: "DEVELOPMENT_TEAM")
  return if team_id.nil?

  case Gym.config[:export_method]
  when "app-store"
    prefix = "3rd Party Mac Developer Installer: "
  when "developer-id"
    prefix = "Developer ID Installer: "
  else
    return
  end

  output = Helper.backticks("security find-certificate -a -c \"#{prefix}\"", print: false)

  # Find matches, filter by team_id, prepend prefix for full cert name
  certs = output.scan(/"(?:#{prefix})(.*)"/)
  certs = certs.flatten.uniq.select do |cert|
    cert.include?(team_id)
  end.map do |cert|
    prefix + cert
  end

  if certs.first
    UI.verbose("Detected installer certificate to use: #{certs.first}")
    Gym.config[:installer_cert_name] = certs.first
  end
end
detect_toolchain() click to toggle source

The toolchain parameter is used if you don't use the default toolchain of Xcode (e.g. Swift 2.3 with Xcode 8)

# File gym/lib/gym/detect_values.rb, line 176
def self.detect_toolchain
  return unless Gym.config[:toolchain]

  # Convert the aliases to the full string to make it easier for the user #justfastlanethings
  if Gym.config[:toolchain].to_s == "swift_2_3"
    Gym.config[:toolchain] = "com.apple.dt.toolchain.Swift_2_3"
  end
end
ensure_export_options_is_hash() click to toggle source
# File gym/lib/gym/detect_values.rb, line 185
def self.ensure_export_options_is_hash
  return if Gym.config[:export_options].nil? || Gym.config[:export_options].kind_of?(Hash)

  # Reads options from file
  plist_file_path = Gym.config[:export_options]
  UI.user_error!("Couldn't find plist file at path #{File.expand_path(plist_file_path)}") unless File.exist?(plist_file_path)
  hash = Plist.parse_xml(plist_file_path)
  UI.user_error!("Couldn't read provided plist at path #{File.expand_path(plist_file_path)}") if hash.nil?
  # Convert keys to symbols
  Gym.config[:export_options] = keys_to_symbols(hash)
end
has_xcode_preferences_plist?() click to toggle source

this file only exists when you edit the Xcode preferences to set custom values

# File gym/lib/gym/detect_values.rb, line 65
def self.has_xcode_preferences_plist?
  File.exist?(xcode_preference_plist_path)
end
keys_to_symbols(hash) click to toggle source
# File gym/lib/gym/detect_values.rb, line 197
def self.keys_to_symbols(hash)
  # Convert keys to symbols
  hash = hash.each_with_object({}) do |(k, v), memo|
    memo[k.b.to_s.to_sym] = v
    memo
  end
  hash
end
min_xcode8?() click to toggle source
# File gym/lib/gym/detect_values.rb, line 140
def self.min_xcode8?
  Helper.xcode_at_least?("8.0")
end
set_additional_default_values() click to toggle source

This is needed as these are more complex default values Returns the finished config object

# File gym/lib/gym/detect_values.rb, line 11
def self.set_additional_default_values
  config = Gym.config

  # First, try loading the Gymfile from the current directory
  config.load_configuration_file(Gym.gymfile_name)

  # Detect the project
  FastlaneCore::Project.detect_projects(config)
  Gym.project = FastlaneCore::Project.new(config)

  # Go into the project's folder, as there might be a Gymfile there
  project_path = File.expand_path("..", Gym.project.path)
  unless File.expand_path(".") == project_path
    Dir.chdir(project_path) do
      config.load_configuration_file(Gym.gymfile_name)
    end
  end

  ensure_export_options_is_hash

  detect_scheme
  detect_platform # we can only do that *after* we have the scheme
  detect_selected_provisioning_profiles # we can only do that *after* we have the platform
  detect_configuration
  detect_toolchain
  detect_third_party_installer

  config[:output_name] ||= Gym.project.app_name

  config[:build_path] ||= archive_path_from_local_xcode_preferences

  # Make sure the output name is valid and remove a trailing `.ipa` extension
  # as it will be added by gym for free
  config[:output_name].gsub!(".ipa", "")
  config[:output_name].gsub!(File::SEPARATOR, "_")

  return config
end
xcode_preference_plist_path() click to toggle source
# File gym/lib/gym/detect_values.rb, line 69
def self.xcode_preference_plist_path
  File.expand_path("~/Library/Preferences/com.apple.dt.Xcode.plist")
end
xcode_preferences_dictionary(path = xcode_preference_plist_path) click to toggle source
# File gym/lib/gym/detect_values.rb, line 73
def self.xcode_preferences_dictionary(path = xcode_preference_plist_path)
  CFPropertyList.native_types(CFPropertyList::List.new(file: path).value)
end