Class: Gym::DetectValues

Inherits:
Object
  • Object
show all
Defined in:
gym/lib/gym/detect_values.rb

Overview

This class detects all kinds of default values

Class Method Summary collapse

Class Method Details

.archive_path_from_local_xcode_preferencesObject


50
51
52
53
54
55
56
57
58
59
60
# 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_configurationObject

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


158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'gym/lib/gym/detect_values.rb', line 158

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_platformObject

Is it an iOS device or a Mac?


145
146
147
148
149
150
151
152
153
154
155
# File 'gym/lib/gym/detect_values.rb', line 145

def self.detect_platform
  return if Gym.config[:destination]
  platform = if Gym.project.mac? || Gym.building_mac_catalyst_for_mac?
               min_xcode8? ? "macOS" : "OS X"
             elsif Gym.project.tvos?
               "tvOS"
             else
               "iOS"
             end
  Gym.config[:destination] = "generic/platform=#{platform}"
end

.detect_schemeObject


136
137
138
# File 'gym/lib/gym/detect_values.rb', line 136

def self.detect_scheme
  Gym.project.select_scheme
end

.detect_selected_provisioning_profilesObject

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


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# 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_installerObject

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


105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# 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_toolchainObject

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


173
174
175
176
177
178
179
180
# File 'gym/lib/gym/detect_values.rb', line 173

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_hashObject


182
183
184
185
186
187
188
189
190
191
192
# File 'gym/lib/gym/detect_values.rb', line 182

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?Boolean

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

Returns:


65
66
67
# 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) ⇒ Object


194
195
196
197
198
199
200
201
# File 'gym/lib/gym/detect_values.rb', line 194

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?Boolean

Returns:


140
141
142
# File 'gym/lib/gym/detect_values.rb', line 140

def self.min_xcode8?
  Helper.xcode_at_least?("8.0")
end

.set_additional_default_valuesObject

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


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
# 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_pathObject


69
70
71
# 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) ⇒ Object


73
74
75
# 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