@@ -24,11 +24,99 @@ devices = {
2424 } ,
2525 "visionos" => {
2626 1 => [ "Apple Vision Pro (at 2732x2048) (1.2)" ] ,
27- 2 => [ "Apple Vision Pro (2.5)" ] ,
27+ 2 => [ "Apple Vision Pro (at 2732x2048) ( 2.5)" ] ,
2828 26 => [ "Apple Vision Pro (26.0)" ] ,
2929 } ,
3030}
3131
32+ before_all do |lane , options |
33+ create_simulators
34+ end
35+
36+ lane :create_simulators do
37+ require 'json'
38+
39+ # map Fastfile platform keys to display names used by CoreSimulator runtimes
40+ platforms_to_os = {
41+ "ios" => "iOS" ,
42+ "tvos" => "tvOS" ,
43+ "watchos" => "watchOS" ,
44+ "visionos" => "visionOS" ,
45+ }
46+
47+ # Build lookup tables from CoreSimulator for robust name→identifier mapping
48+ begin
49+ devtypes_json = sh ( "xcrun simctl list -j devicetypes" , log : false )
50+ runtimes_json = sh ( "xcrun simctl list -j runtimes" , log : false )
51+ devtypes = JSON . parse ( devtypes_json ) [ "devicetypes" ] || [ ]
52+ runtimes = JSON . parse ( runtimes_json ) [ "runtimes" ] || [ ]
53+ rescue => e
54+ UI . message ( "Failed to read simctl lists: #{ e } " )
55+ devtypes = [ ]
56+ runtimes = [ ]
57+ end
58+
59+ device_name_to_id = { }
60+ devtypes . each do |dt |
61+ name = dt [ "name" ]
62+ id = dt [ "identifier" ]
63+ device_name_to_id [ name ] = id if name && id
64+ end
65+
66+ runtime_name_to_id = { }
67+ runtimes . each do |rt |
68+ next unless rt [ "isAvailable" ]
69+ name = rt [ "name" ] # e.g. "iOS 16.4"
70+ id = rt [ "identifier" ] # e.g. "com.apple.CoreSimulator.SimRuntime.iOS-16-4"
71+ runtime_name_to_id [ name ] = id if name && id
72+ end
73+
74+ # Fallback builders when exact matches are not present in the lookup tables
75+ build_device_type_id = proc do |device_name |
76+ # Remove parentheses but keep their contents, replace spaces with hyphens, drop non-word chars except hyphens
77+ s = device_name . gsub ( /[()]/ , '' )
78+ s = s . gsub ( /\s +/ , '-' )
79+ s = s . gsub ( /[^A-Za-z0-9-]/ , '' )
80+ "com.apple.CoreSimulator.SimDeviceType." + s
81+ end
82+
83+ build_runtime_id = proc do |os_name , version |
84+ "com.apple.CoreSimulator.SimRuntime." + os_name + "-" + version . tr ( '.' , '-' )
85+ end
86+
87+ devices . each do |platform , versions |
88+ os_name = platforms_to_os [ platform ]
89+ next if os_name . nil?
90+
91+ versions . values . flatten . each do |descriptor |
92+ # descriptor examples:
93+ # "iPhone 14 Pro (16.4)"
94+ # "iPad Pro (11-inch) (4th generation) (16.4)"
95+ # "Apple Vision Pro (2.5)"
96+ begin
97+ # Strip only the trailing " (x.y)" to get the device name
98+ device_name = descriptor . sub ( /\s *\( [^()]+\) \s *\z / , '' )
99+ runtime_version = descriptor [ /\( ([^)]+)\) \s *\z / , 1 ]
100+ if runtime_version . nil?
101+ UI . message ( "Could not parse runtime version from '#{ descriptor } ', skipping" )
102+ next
103+ end
104+
105+ runtime_name = "#{ os_name } #{ runtime_version } "
106+
107+ device_type_id = device_name_to_id [ device_name ] || build_device_type_id . call ( device_name )
108+ runtime_id = runtime_name_to_id [ runtime_name ] || build_runtime_id . call ( os_name , runtime_version )
109+
110+ sim_name = descriptor # keep the nice human-readable name
111+
112+ sh ( %(xcrun simctl create "#{ sim_name } " "#{ device_type_id } " "#{ runtime_id } " || true) )
113+ rescue => e
114+ UI . message ( "Skipping #{ descriptor } : #{ e } " )
115+ end
116+ end
117+ end
118+ end
119+
32120lane :build do |options |
33121 platform = options [ :platform ] . to_s . downcase
34122 version = options [ :version ] . to_i
0 commit comments