Class: Fastlane::CreateSimulatorDevices::RuntimeHelper
- Inherits:
-
Object
- Object
- Fastlane::CreateSimulatorDevices::RuntimeHelper
- Defined in:
- lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb
Overview
Helper class for managing simulator runtimes.
Constant Summary collapse
- UI =
::Fastlane::UI
- SDK_PLATFORM_TO_OS_NAME =
{ 'iphonesimulator' => 'iOS', 'appletvsimulator' => 'tvOS', 'watchsimulator' => 'watchOS', 'xrsimulator' => 'xrOS' }.freeze
Instance Attribute Summary collapse
-
#cache_dir ⇒ Object
Returns the value of attribute cache_dir.
-
#shell_helper ⇒ Object
Returns the value of attribute shell_helper.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
Instance Method Summary collapse
- #available_runtime_for_required_device(required_device) ⇒ Object
- #available_runtime_matching_needed_runtime?(needed_runtime) ⇒ Boolean
- #cached_runtime_file(missing_runtime) ⇒ Object
- #delete_unusable_runtimes ⇒ Object
- #download_and_install_missing_runtime(missing_runtime) ⇒ Object
-
#initialize(cache_dir:, shell_helper:, verbose:) ⇒ RuntimeHelper
constructor
A new instance of RuntimeHelper.
- #install_missing_runtime(missing_runtime, cached_runtime_file) ⇒ Object
- #install_missing_runtimes(required_devices) ⇒ Object
-
#max_available_simulator_sdks ⇒ Object
Returns a hash where key is platform string and value is sdk version.
- #missing_runtimes(needed_runtimes) ⇒ Object
- #required_runtime_for_device(required_device, runtime_version) ⇒ Object
- #runtime_build_version_for_filename(filename) ⇒ Object
Constructor Details
#initialize(cache_dir:, shell_helper:, verbose:) ⇒ RuntimeHelper
Returns a new instance of RuntimeHelper.
14 15 16 17 18 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 14 def initialize(cache_dir:, shell_helper:, verbose:) self.cache_dir = cache_dir self.shell_helper = shell_helper self.verbose = verbose end |
Instance Attribute Details
#cache_dir ⇒ Object
Returns the value of attribute cache_dir.
12 13 14 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 12 def cache_dir @cache_dir end |
#shell_helper ⇒ Object
Returns the value of attribute shell_helper.
12 13 14 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 12 def shell_helper @shell_helper end |
#verbose ⇒ Object
Returns the value of attribute verbose.
12 13 14 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 12 def verbose @verbose end |
Instance Method Details
#available_runtime_for_required_device(required_device) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 86 def available_runtime_for_required_device(required_device) available_runtime = available_runtime_matching_needed_runtime?(required_device.required_runtime) if available_runtime.nil? UI.important("Runtime #{required_device.required_runtime.description} not found. Skipping simulator creation for #{required_device.description}...") return nil end # Check if the runtime supports the device type. if available_runtime.supported_device_types .none? { |supported_device_type| supported_device_type.identifier == required_device.device_type.identifier } UI.important("Device type #{required_device.device_type.name} is not supported by runtime #{available_runtime.identifier}. Skipping simulator creation for #{required_device.description}...") return nil end if available_runtime.nil? UI.important("Runtime #{required_device.required_runtime.description} not found. Skipping simulator creation for #{required_device.description}...") return nil end available_runtime end |
#available_runtime_matching_needed_runtime?(needed_runtime) ⇒ Boolean
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 72 def available_runtime_matching_needed_runtime?(needed_runtime) matching_runtimes = shell_helper.available_runtimes .select do |available_runtime| next false if needed_runtime.os_name != available_runtime.platform || needed_runtime.product_version != available_runtime.version needed_runtime.product_build_version = [needed_runtime.product_build_version, available_runtime.build_version].compact.max needed_runtime.product_build_version.almost_equal?(available_runtime.build_version) end matching_runtimes.max_by { |available_runtime| [available_runtime.version, available_runtime.build_version] } end |
#cached_runtime_file(missing_runtime) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 143 def cached_runtime_file(missing_runtime) FileUtils.mkdir_p(cache_dir) runtime_dmg_search_pattern = "#{cache_dir}/#{missing_runtime.sdk_platform}_#{missing_runtime.product_version}_" # Remove the last character of the build version if it is the latest beta. # Apple can create a new Runtime version and block product build version # shipped with Xcode betas and use the same product version. # E.g. Xcode 26.0 Beta 3 has iOS 26.0 (23A5287e) SDK, but # xcodebuild downloads iphonesimulator_26.0_23A5287g.dmg as latest. runtime_dmg_search_pattern += missing_runtime.product_build_version.to_s.chop if missing_runtime.product_build_version runtime_dmg_search_pattern += '*.dmg' runtime_file = Dir .glob(runtime_dmg_search_pattern) .max_by { |filename| runtime_build_version_for_filename(filename) } return nil if runtime_file.nil? missing_runtime.product_build_version ||= runtime_build_version_for_filename(runtime_file) UI.("Found existing #{missing_runtime.runtime_name} runtime image in #{cache_dir}: #{runtime_file}") runtime_file end |
#delete_unusable_runtimes ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 27 def delete_unusable_runtimes deletable_runtimes = shell_helper.installed_runtimes_with_state .select { |runtime| runtime.unusable? && runtime.deletable? } return if deletable_runtimes.empty? deletable_runtimes.each do |runtime| shell_helper.delete_runtime(runtime.identifier) end shell_helper.available_runtimes(force: true) end |
#download_and_install_missing_runtime(missing_runtime) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 120 def download_and_install_missing_runtime(missing_runtime) UI.("Attempting to install #{missing_runtime.runtime_name} runtime.") downloaded_runtime_file = cached_runtime_file(missing_runtime) if downloaded_runtime_file.nil? shell_helper.download_runtime(missing_runtime, cache_dir) downloaded_runtime_file = cached_runtime_file(missing_runtime) end shell_helper.import_runtime(downloaded_runtime_file, missing_runtime.runtime_name) end |
#install_missing_runtime(missing_runtime, cached_runtime_file) ⇒ Object
109 110 111 112 113 114 115 116 117 118 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 109 def install_missing_runtime(missing_runtime, cached_runtime_file) runtime_name = missing_runtime.runtime_name if missing_runtime.product_build_version.nil? UI.important("Failed to find runtime build version for #{runtime_name}") return end shell_helper.import_runtime(cached_runtime_file, runtime_name) end |
#install_missing_runtimes(required_devices) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 40 def install_missing_runtimes(required_devices) needed_runtimes = required_devices.filter_map(&:required_runtime).uniq missing_runtimes = missing_runtimes(needed_runtimes) return if missing_runtimes.empty? missing_runtimes.each do |missing_runtime| download_and_install_missing_runtime(missing_runtime) end # Update available_runtimes after installing the runtimes. shell_helper.installed_runtimes_with_state shell_helper.available_runtimes(force: true) # Check if missing runtimes are available after installing missing_runtimes = missing_runtimes(missing_runtimes) # List missing runtimes after attempt to install the runtimes. missing_runtimes(missing_runtimes) .each do |missing_runtime| UI.important("Failed to find/download/install runtime #{missing_runtime.runtime_name}") end end |
#max_available_simulator_sdks ⇒ Object
Returns a hash where key is platform string and value is sdk version.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 191 def max_available_simulator_sdks return @max_available_simulator_sdks unless @max_available_simulator_sdks.nil? @max_available_simulator_sdks = shell_helper.available_sdks # Only simulators .filter { |sdk| sdk.platform.include?('simulator') } # Calculate max version for each product name .each_with_object({}) do |sdk, sdk_versions| os_name = SDK_PLATFORM_TO_OS_NAME[sdk.platform] stored_sdk = sdk_versions[os_name] sdk_versions[os_name] = sdk if stored_sdk.nil? || sdk.product_version > stored_sdk.product_version end @max_available_simulator_sdks end |
#missing_runtimes(needed_runtimes) ⇒ Object
65 66 67 68 69 70 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 65 def missing_runtimes(needed_runtimes) needed_runtimes.select do |needed_runtime| # Check if available runtimes contain the needed runtime. available_runtime_matching_needed_runtime?(needed_runtime).nil? end end |
#required_runtime_for_device(required_device, runtime_version) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 169 def required_runtime_for_device(required_device, runtime_version) sdk = max_available_simulator_sdks[required_device.os_name] # If the runtime version is the same as the SDK version, use the SDK build version. # This will allow to use different runtimes for the same version but different Xcode beta versions. product_build_version = sdk.product_build_version if runtime_version.nil? || sdk.product_version == runtime_version if !runtime_version.nil? && runtime_version > sdk.product_version UI.important("Runtime version for #{required_device.device_type.name} (#{runtime_version}) is higher than maximum supported by the Xcode: #{sdk.product_version}") return nil end RequiredRuntime.new( sdk_platform: sdk.platform, os_name: required_device.os_name, product_version: runtime_version || sdk.product_version, product_build_version:, is_latest: sdk.product_build_version.almost_equal?(product_build_version) ) end |
#runtime_build_version_for_filename(filename) ⇒ Object
133 134 135 136 137 138 139 140 141 |
# File 'lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb', line 133 def runtime_build_version_for_filename(filename) return nil unless filename # iphonesimulator_18.4_22E238.dmg # Format: iphonesimulator_VERSION_BUILD.dmg build_version = File.basename(filename, '.dmg').split('_').last AppleBuildVersion.new(build_version) end |