fastlane-plugin-create_simulator_devices 0.0.12 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e4f2a4d905fad425dc7b871cb55ee0ea48c0d36b8417d26d6cfa1a49fd97737
4
- data.tar.gz: 1f123387acdf4df42f374ec7ba14d2c0aed1f30587c1c2ba8c9f362a848641fe
3
+ metadata.gz: fbcf5d008c0e2e248db6b53d80c89c681cd516837439e1da34e95375c135e934
4
+ data.tar.gz: adc56432be831c59c299204092d96392f3a9483d08ae625a6c5d31695d58a3f0
5
5
  SHA512:
6
- metadata.gz: 7183aeb1d262c2b7faeadb35750ecf0f04982ef9a978b2e397ec66c5fac5a5a10b94494a525355b74711a25a26a8f7c5a1af2415c57fb6d2db2ff7776461dd16
7
- data.tar.gz: 9404401a0f27c170011f87e3707a901f0ac3ae1294ce7ebceb1519648b94b3e6e74cd049b520d288471160852d0c1cf1bc931a05ca8413fa177624da82b60cf3
6
+ metadata.gz: ded9ef76090109dd7f69d96384625e3899bed635d8d59aee8213954cfe33003be2874de36b0b8aae3bf16cf7e10a27bd59adfd51a9cd4d7d3a2600061bf39d8e
7
+ data.tar.gz: 02cf2720d898e0cb315bb37d13eb1d86a9b10815635def22781465a3a268e1119b836bf39da22793b4c07d317565f67f118a329511035d478865ab3b3accf285
@@ -4,6 +4,7 @@ require 'fastlane'
4
4
  require 'spaceship'
5
5
  require_relative '../helpers/create_simulator_devices/runner'
6
6
  require_relative '../helpers/create_simulator_devices/models'
7
+ require_relative '../helpers/create_simulator_devices/models/device_naming_style'
7
8
 
8
9
  module Fastlane
9
10
  module Actions
@@ -22,12 +23,15 @@ module Fastlane
22
23
  UI.user_error!('No devices specified') if required_devices.nil? || required_devices.empty?
23
24
 
24
25
  shell_helper = CreateSimulatorDevices::ShellHelper.new(print_command: params[:print_command], print_command_output: params[:print_command_output], action_context: self)
25
- runtime_helper = CreateSimulatorDevices::RuntimeHelper.new(cache_dir: params[:cache_dir], shell_helper:, verbose:)
26
+ runtime_helper = CreateSimulatorDevices::RuntimeHelper.new(cache_dir: params[:cache_dir], shell_helper: shell_helper, verbose: verbose)
26
27
 
27
28
  runner = CreateSimulatorDevices::Runner.new(
28
29
  runtime_helper: runtime_helper,
29
30
  shell_helper: shell_helper,
30
- verbose: verbose
31
+ verbose: verbose,
32
+ can_rename_devices: params[:rename_devices],
33
+ can_delete_duplicate_devices: params[:delete_duplicate_devices],
34
+ device_naming_style: params[:device_naming_style].to_sym
31
35
  )
32
36
 
33
37
  runner.run(required_devices)
@@ -52,7 +56,7 @@ module Fastlane
52
56
  )"
53
57
  end
54
58
 
55
- def self.available_options
59
+ def self.available_options # rubocop:disable Metrics/MethodLength
56
60
  [
57
61
  ::FastlaneCore::ConfigItem.new(key: :devices,
58
62
  env_name: 'SCAN_DEVICES',
@@ -80,7 +84,29 @@ module Fastlane
80
84
  description: 'Print xcrun simctl commands output',
81
85
  type: Boolean,
82
86
  optional: true,
83
- default_value: false)
87
+ default_value: false),
88
+ ::FastlaneCore::ConfigItem.new(key: :rename_devices,
89
+ env_name: 'CREATE_SIMULATOR_DEVICES_RENAME_DEVICES',
90
+ description: 'Rename devices if needed',
91
+ type: Boolean,
92
+ optional: true,
93
+ default_value: false),
94
+ ::FastlaneCore::ConfigItem.new(key: :delete_duplicate_devices,
95
+ env_name: 'CREATE_SIMULATOR_DEVICES_DELETE_DUPLICATE_DEVICES',
96
+ description: 'Delete duplicate devices',
97
+ type: Boolean,
98
+ optional: true,
99
+ default_value: false),
100
+ ::FastlaneCore::ConfigItem.new(key: :device_naming_style,
101
+ env_name: 'CREATE_SIMULATOR_DEVICES_DEVICE_NAMING_STYLE',
102
+ description: 'Device naming style',
103
+ type: String,
104
+ optional: true,
105
+ default_value: CreateSimulatorDevices::DeviceNamingStyle::SCAN.to_s,
106
+ verify_block: proc do |value|
107
+ allowed_values = CreateSimulatorDevices::DeviceNamingStyle::ALL
108
+ UI.user_error!("Invalid device naming style: #{value}. Allowed values: #{allowed_values.map(&:to_s).join(', ')}") unless allowed_values.include?(value.to_sym)
109
+ end)
84
110
  ]
85
111
  end
86
112
 
@@ -58,11 +58,19 @@ module Fastlane
58
58
  return self == other unless lhs_is_beta && rhs_is_beta && @build_version.length == rhs_build_version.to_s.length
59
59
 
60
60
  # Take only leading chars up to the first letter included e.g. 22C146 -> 22C
61
- minor_version == rhs_build_version.minor_version
61
+ major == rhs_build_version.major && minor == rhs_build_version.minor && patch == rhs_build_version.patch
62
62
  end
63
63
 
64
- def minor_version
65
- AppleBuildVersion.new(@build_version.match(/^[0-9]+[A-Z]+/)[0])
64
+ def major
65
+ @build_version.match(/^([0-9]+)([A-Z][0-9]{2,3})([0-9]+)/)[1]
66
+ end
67
+
68
+ def minor
69
+ @build_version.match(/^([0-9]+)([A-Z][0-9]{2,3})([0-9]+)/)[2]
70
+ end
71
+
72
+ def patch
73
+ @build_version.match(/^([0-9]+)([A-Z][0-9]{2,3})([0-9]+)/)[3]
66
74
  end
67
75
 
68
76
  def <(other)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fastlane
4
+ module CreateSimulatorDevices
5
+ class DeviceNamingStyle
6
+ SCAN = :scan
7
+ RUN_TESTS = :run_tests
8
+ SNAPSHOT = :snapshot
9
+ CAPTURE_IOS_SCREENSHOTS = :capture_ios_screenshots
10
+
11
+ ALL = [SCAN, RUN_TESTS, SNAPSHOT, CAPTURE_IOS_SCREENSHOTS].freeze
12
+ end
13
+ end
14
+ end
@@ -8,6 +8,7 @@ require_relative 'models/xcodebuild/sdk'
8
8
  require_relative 'models/required_device'
9
9
  require_relative 'models/required_runtime'
10
10
  require_relative 'models/apple_build_version'
11
+ require_relative 'models/device_naming_style'
11
12
  require 'fastlane'
12
13
 
13
14
  module Fastlane
@@ -3,20 +3,24 @@
3
3
  require_relative 'runtime_helper'
4
4
  require 'fastlane'
5
5
  require_relative 'shared_values'
6
+ require_relative 'models/device_naming_style'
6
7
 
7
8
  module Fastlane
8
9
  # Create simulator devices.
9
10
  module CreateSimulatorDevices
10
11
  # Does all the work to create simulator devices.
11
- class Runner
12
+ class Runner # rubocop:disable Metrics/ClassLength
12
13
  UI = ::Fastlane::UI unless defined?(UI)
13
14
 
14
- attr_accessor :shell_helper, :verbose, :runtime_helper
15
+ attr_accessor :shell_helper, :verbose, :runtime_helper, :can_rename_devices, :can_delete_duplicate_devices, :device_naming_style
15
16
 
16
- def initialize(runtime_helper:, shell_helper:, verbose:)
17
+ def initialize(runtime_helper:, shell_helper:, verbose:, can_rename_devices:, can_delete_duplicate_devices:, device_naming_style:) # rubocop:disable Metrics/ParameterLists
17
18
  self.shell_helper = shell_helper
18
19
  self.verbose = verbose
19
20
  self.runtime_helper = runtime_helper
21
+ self.can_rename_devices = can_rename_devices
22
+ self.can_delete_duplicate_devices = can_delete_duplicate_devices
23
+ self.device_naming_style = device_naming_style
20
24
  end
21
25
 
22
26
  def run(devices)
@@ -50,11 +54,11 @@ module Fastlane
50
54
 
51
55
  log_matched_devices(matched_devices: matched_devices)
52
56
 
53
- Actions.lane_context[Actions::SharedValues::AVAILABLE_SIMULATOR_DEVICES] = matched_devices
54
-
55
- matched_devices_names = matched_devices.map(&:description)
57
+ matched_devices_names = matched_devices.map { |matched_device| returning_device_name_for_required_device(matched_device) }
56
58
  UI.message("Available simulator devices: #{matched_devices_names.join(', ')}")
57
59
 
60
+ Actions.lane_context[Actions::SharedValues::AVAILABLE_SIMULATOR_DEVICES] = matched_devices_names
61
+
58
62
  matched_devices_names
59
63
  end
60
64
 
@@ -85,14 +89,91 @@ module Fastlane
85
89
 
86
90
  simctl_devices = shell_helper.simctl_devices_for_runtimes[required_device.simctl_runtime.identifier.to_sym]
87
91
 
88
- return [] if simctl_devices.nil?
92
+ return nil if simctl_devices.nil?
89
93
 
90
94
  # Find the device with the same name as the required device.
91
95
  devices_with_same_type = simctl_devices
92
96
  .select { |simctl_device| simctl_device.device_type_identifier == required_device.device_type.identifier }
93
97
 
94
- devices_with_same_type
95
- .detect { |simctl_device| simctl_device.name == required_device.device_type.name }
98
+ preferred_device_name = device_name_for_required_device(required_device)
99
+
100
+ # Prefer device with the same name that includes the runtime version.
101
+ matching_device = devices_with_same_type.detect { |simctl_device| simctl_device.name == preferred_device_name }
102
+
103
+ if can_rename_devices
104
+ # Otherwise, if rename is enabled, use the first device with the same type.
105
+ matching_device ||= devices_with_same_type.first
106
+ rename_device_if_needed(matching_device, preferred_device_name)
107
+ end
108
+
109
+ delete_duplicate_devices(devices_with_same_type, matching_device) if can_delete_duplicate_devices
110
+
111
+ matching_device
112
+ end
113
+
114
+ def rename_device_if_needed(matching_device, preferred_device_name)
115
+ return if matching_device.nil? || matching_device.name == preferred_device_name
116
+
117
+ UI.message("Renaming device #{matching_device.name} (udid: #{matching_device.udid}) to #{preferred_device_name}")
118
+ shell_helper.rename_device(udid: matching_device.udid, name: preferred_device_name)
119
+ matching_device.name = preferred_device_name
120
+ end
121
+
122
+ def delete_duplicate_devices(matching_devices, matching_device)
123
+ return if matching_device.nil?
124
+
125
+ matching_devices
126
+ .reject { |simctl_device| simctl_device.udid == matching_device.udid }
127
+ .each do |simctl_device|
128
+ UI.message("Deleting duplicate device #{simctl_device.name} (udid: #{simctl_device.udid})")
129
+ shell_helper.delete_device(udid: simctl_device.udid)
130
+ end
131
+ end
132
+
133
+ # Returns the device name for the required device.
134
+ #
135
+ # This name is used in the simctl device name.
136
+ def device_name_for_required_device(required_device)
137
+ case device_naming_style
138
+ when DeviceNamingStyle::SCAN, DeviceNamingStyle::RUN_TESTS
139
+ # scan modifies the device name by removing the runtime version when searching for a passed device name.
140
+ # E.g.:
141
+ # * given "iPhone 15 (17.0)" match will search for simulator named "iPhone 15" with the SDK version 17.0.
142
+ # * given "iPhone 15" match will search for simulator named "iPhone 15" with the default SDK version.
143
+ # So we need to name the device by the device type name for scan to find the correct device.
144
+ required_device.device_type.name
145
+ when DeviceNamingStyle::SNAPSHOT, DeviceNamingStyle::CAPTURE_IOS_SCREENSHOTS
146
+ # snapshot nither does not modify the device name when searching for a passed device name nor extracts the runtime version from the device name.
147
+ # E.g.:
148
+ # * given "iPhone 15 (17.0)" match will search for device named exactly "iPhone 15 (17.0)".
149
+ # * given "iPhone 15" match will search for device named exactly "iPhone 15".
150
+ # So we need to return the full device name for the required device for snapshot to find the correct device.
151
+ runtime_build = required_device.simctl_runtime.build_version
152
+ build_suffix = runtime_build.beta? ? "-#{runtime_build}" : ''
153
+ "#{required_device.device_type.name} (#{required_device.simctl_runtime.version}#{build_suffix})"
154
+ end
155
+ end
156
+
157
+ # Returns the device name for the required device.
158
+ #
159
+ # This name is used when passing the device name to the scan or snapshot.
160
+ def returning_device_name_for_required_device(required_device)
161
+ case device_naming_style
162
+ when DeviceNamingStyle::SCAN, DeviceNamingStyle::RUN_TESTS
163
+ # scan respects the runtime version in the devices list, so we need to return the full device name for the required device, otherwise the default SDK version will be used.
164
+ # E.g.:
165
+ # * given "iPhone 15 (17.0)" match will search for simulator named "iPhone 15" with the SDK version 17.0.
166
+ # * given "iPhone 15" match will search for simulator named "iPhone 15" with the default SDK version.
167
+ # So we need to return the device name and the required runtime version for scan to find the correct device.
168
+ "#{required_device.simctl_device.name} (#{required_device.required_runtime.product_version})"
169
+ when DeviceNamingStyle::SNAPSHOT, DeviceNamingStyle::CAPTURE_IOS_SCREENSHOTS
170
+ # snapshot does not modify the device name when searching for a passed device name nor extracts the runtime version from the device name.
171
+ # E.g.:
172
+ # * given "iPhone 15 (17.0)" match will search for device named exactly "iPhone 15 (17.0)".
173
+ # * given "iPhone 15" match will search for device named exactly "iPhone 15" .
174
+ # So we need to return the full device name for the required device for snapshot to find the correct device.
175
+ required_device.simctl_device.name
176
+ end
96
177
  end
97
178
 
98
179
  def create_missing_devices(required_devices)
@@ -109,7 +190,7 @@ module Fastlane
109
190
  UI.message('Creating missing devices')
110
191
  missing_devices.each do |missing_device|
111
192
  shell_helper.create_device(
112
- missing_device.device_type.name,
193
+ device_name_for_required_device(missing_device),
113
194
  missing_device.device_type.identifier,
114
195
  missing_device.simctl_runtime.identifier
115
196
  )
@@ -161,7 +161,12 @@ module Fastlane
161
161
  # shipped with Xcode betas and use the same product version.
162
162
  # E.g. Xcode 26.0 Beta 3 has iOS 26.0 (23A5287e) SDK, but
163
163
  # xcodebuild downloads iphonesimulator_26.0_23A5287g.dmg as latest.
164
- runtime_dmg_search_pattern += missing_runtime.product_build_version.minor_version.to_s if missing_runtime.product_build_version
164
+ product_build_version = missing_runtime.product_build_version
165
+ if product_build_version
166
+ runtime_dmg_search_pattern += product_build_version.major.to_s
167
+ runtime_dmg_search_pattern += product_build_version.minor.to_s
168
+ runtime_dmg_search_pattern += product_build_version.patch.to_s
169
+ end
165
170
  runtime_dmg_search_pattern += '*.dmg'
166
171
 
167
172
  if verbose
@@ -66,7 +66,7 @@ module Fastlane
66
66
  @simctl_device_types
67
67
  end
68
68
 
69
- def delete_device(udid)
69
+ def delete_device(udid:)
70
70
  UI.message("Deleting device #{udid}...")
71
71
  sh(command: "xcrun simctl delete #{udid.shellescape}")
72
72
  end
@@ -130,6 +130,11 @@ module Fastlane
130
130
  sh(command: "xcrun simctl create #{name.shellescape} #{device_type_identifier.shellescape} #{runtime_identifier.shellescape}")
131
131
  end
132
132
 
133
+ def rename_device(udid:, name:)
134
+ UI.message("Renaming device with udid #{udid} to #{name}")
135
+ sh(command: "xcrun simctl rename #{udid.shellescape} #{name.shellescape}")
136
+ end
137
+
133
138
  def delete_runtime(runtime_identifier)
134
139
  UI.message("Deleting runtime #{runtime_identifier}...")
135
140
  sh(command: "xcrun simctl runtime delete #{runtime_identifier.shellescape}")
@@ -150,8 +155,12 @@ module Fastlane
150
155
  missing_runtime.os_name.shellescape
151
156
  ]
152
157
 
153
- command << '-buildVersion'
154
- command << missing_runtime.product_version.to_s.shellescape
158
+ is_beta = missing_runtime.product_build_version.nil? ? false : missing_runtime.product_build_version.beta?
159
+
160
+ unless is_beta
161
+ command << '-buildVersion'
162
+ command << missing_runtime.product_version.to_s.shellescape
163
+ end
155
164
 
156
165
  sh(command: command.join(' '), print_command: true, print_command_output: true)
157
166
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fastlane
4
4
  module CreateSimulatorDevices
5
- VERSION = '0.0.12'
5
+ VERSION = '0.0.13'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-create_simulator_devices
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vitalii Budnik
@@ -22,6 +22,7 @@ files:
22
22
  - lib/fastlane/plugin/create_simulator_devices/actions/create_simulator_devices_action.rb
23
23
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models.rb
24
24
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models/apple_build_version.rb
25
+ - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models/device_naming_style.rb
25
26
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models/required_device.rb
26
27
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models/required_runtime.rb
27
28
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models/simctl/device.rb