fastlane-plugin-create_simulator_devices 0.0.13 → 0.0.15

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: fbcf5d008c0e2e248db6b53d80c89c681cd516837439e1da34e95375c135e934
4
- data.tar.gz: adc56432be831c59c299204092d96392f3a9483d08ae625a6c5d31695d58a3f0
3
+ metadata.gz: 6b2c73d26a678b6c2871d2749da24233ff2d889d4b089eee2cbf25edf5b8de4d
4
+ data.tar.gz: 16a9a49267d3820cac3ca95ee16160657f589d785bf56b040d37ae9b92b8c865
5
5
  SHA512:
6
- metadata.gz: ded9ef76090109dd7f69d96384625e3899bed635d8d59aee8213954cfe33003be2874de36b0b8aae3bf16cf7e10a27bd59adfd51a9cd4d7d3a2600061bf39d8e
7
- data.tar.gz: 02cf2720d898e0cb315bb37d13eb1d86a9b10815635def22781465a3a268e1119b836bf39da22793b4c07d317565f67f118a329511035d478865ab3b3accf285
6
+ metadata.gz: ca21d83129049ad9a69689ed417bf4b333b55b3a08facc8c09d2992bf475da42818b53367a28a56423c8887073c5922f883d433c36688f79f44165c744e6a072
7
+ data.tar.gz: 145a144f2da681665e846dfdc7a348ef52883df996f64c6498d17a08edb6fe86c9959e119a5bb16d51b6ae2c8f64cb21831db666603eb9bc2fbb5567939a063a
@@ -31,7 +31,8 @@ module Fastlane
31
31
  verbose: verbose,
32
32
  can_rename_devices: params[:rename_devices],
33
33
  can_delete_duplicate_devices: params[:delete_duplicate_devices],
34
- device_naming_style: params[:device_naming_style].to_sym
34
+ device_naming_style: params[:device_naming_style].to_sym,
35
+ remove_cached_runtimes: params[:remove_cached_runtimes]
35
36
  )
36
37
 
37
38
  runner.run(required_devices)
@@ -106,7 +107,13 @@ module Fastlane
106
107
  verify_block: proc do |value|
107
108
  allowed_values = CreateSimulatorDevices::DeviceNamingStyle::ALL
108
109
  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)
110
+ end),
111
+ ::FastlaneCore::ConfigItem.new(key: :remove_cached_runtimes,
112
+ env_name: 'CREATE_SIMULATOR_DEVICES_REMOVE_CACHED_RUNTIMES',
113
+ description: 'Remove cached runtimes after successful installation',
114
+ type: Boolean,
115
+ optional: true,
116
+ default_value: true)
110
117
  ]
111
118
  end
112
119
 
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fastlane'
4
+ require 'spaceship'
5
+ require_relative '../helpers/create_simulator_devices/shell_helper'
6
+ require_relative '../helpers/create_simulator_devices/runner'
7
+ require_relative '../helpers/create_simulator_devices/models/device_naming_style'
8
+ require_relative '../helpers/gather_simctl_diagnose/runner'
9
+
10
+ module Fastlane
11
+ module Actions
12
+ GatherSimctlDiagnose = ::Fastlane::GatherSimctlDiagnose
13
+ CreateSimulatorDevices = ::Fastlane::CreateSimulatorDevices
14
+
15
+ # Gather simctl diagnose data.
16
+ class GatherSimctlDiagnoseAction < Fastlane::Action
17
+ UI = ::Fastlane::UI unless defined?(UI)
18
+
19
+ attr_accessor :shell_helper
20
+
21
+ def self.run(params)
22
+ verbose = params[:verbose]
23
+ params[:devices] = params[:devices].split(',').map(&:strip) if params[:devices].is_a?(String)
24
+ required_devices = params[:devices]
25
+ UI.user_error!('No devices specified') if required_devices.nil? || required_devices.empty?
26
+
27
+ shell_helper = CreateSimulatorDevices::ShellHelper.new(print_command: params[:print_command], print_command_output: params[:print_command_output], action_context: self)
28
+ runtime_helper = CreateSimulatorDevices::RuntimeHelper.new(cache_dir: nil, shell_helper: shell_helper, verbose: verbose)
29
+
30
+ create_simulator_devices_runner = ::Fastlane::CreateSimulatorDevices::Runner.new(
31
+ runtime_helper: runtime_helper,
32
+ shell_helper: shell_helper,
33
+ verbose: verbose,
34
+ can_rename_devices: false,
35
+ can_delete_duplicate_devices: false,
36
+ device_naming_style: params[:device_naming_style].to_sym,
37
+ remove_cached_runtimes: false
38
+ )
39
+
40
+ runner = GatherSimctlDiagnose::Runner.new(
41
+ runtime_helper: runtime_helper,
42
+ shell_helper: shell_helper,
43
+ verbose: verbose,
44
+ device_naming_style: params[:device_naming_style].to_sym,
45
+ create_simulator_devices_runner: create_simulator_devices_runner,
46
+ output_dir: params[:output_dir],
47
+ timeout: params[:timeout],
48
+ include_all_device_logs: params[:include_all_device_logs],
49
+ include_booted_device_data_directory: params[:include_booted_device_data_directory]
50
+ )
51
+
52
+ runner.run(required_devices)
53
+ end
54
+
55
+ #####################################################
56
+ # @!group Documentation
57
+ #####################################################
58
+
59
+ def self.description
60
+ 'Gathers simctl diagnose data'
61
+ end
62
+
63
+ def self.details
64
+ "This action gathers simctl diagnose data.
65
+
66
+ Usage sample:
67
+
68
+ gather_simctl_diagnose(
69
+ devices: ['iPhone 15 (17.0)', 'iPhone 16', 'iPhone 14 (16.3)']
70
+ output_dir: 'diagnose'
71
+ )"
72
+ end
73
+
74
+ def self.available_options # rubocop:disable Metrics/MethodLength
75
+ [
76
+ ::FastlaneCore::ConfigItem.new(key: :devices,
77
+ env_name: 'SCAN_DEVICES',
78
+ description: 'A list of simulator devices to install (e.g. "iPhone 16")',
79
+ is_string: false,
80
+ default_value: 'iPhone 16'),
81
+ ::FastlaneCore::ConfigItem.new(key: :verbose,
82
+ env_name: 'VERBOSE',
83
+ description: 'Verbose output',
84
+ type: Boolean,
85
+ optional: true,
86
+ default_value: ::FastlaneCore::Globals.verbose?,
87
+ default_value_dynamic: true),
88
+ ::FastlaneCore::ConfigItem.new(key: :output_dir,
89
+ env_name: 'GATHER_SIMCTL_DIAGNOSE_OUTPUT_DIR',
90
+ description: 'Output directory',
91
+ type: String,
92
+ optional: false),
93
+ ::FastlaneCore::ConfigItem.new(key: :print_command,
94
+ description: 'Print xcrun simctl commands',
95
+ type: Boolean,
96
+ optional: true,
97
+ default_value: false),
98
+ ::FastlaneCore::ConfigItem.new(key: :print_command_output,
99
+ description: 'Print xcrun simctl commands output',
100
+ type: Boolean,
101
+ optional: true,
102
+ default_value: false),
103
+ ::FastlaneCore::ConfigItem.new(key: :device_naming_style,
104
+ env_name: 'CREATE_SIMULATOR_DEVICES_DEVICE_NAMING_STYLE',
105
+ description: 'Device naming style',
106
+ type: String,
107
+ optional: true,
108
+ default_value: CreateSimulatorDevices::DeviceNamingStyle::SCAN.to_s,
109
+ verify_block: proc do |value|
110
+ allowed_values = CreateSimulatorDevices::DeviceNamingStyle::ALL
111
+ UI.user_error!("Invalid device naming style: #{value}. Allowed values: #{allowed_values.map(&:to_s).join(', ')}") unless allowed_values.include?(value.to_sym)
112
+ end),
113
+ ::FastlaneCore::ConfigItem.new(key: :timeout,
114
+ env_name: 'GATHER_SIMCTL_DIAGNOSE_TIMEOUT',
115
+ description: 'Timeout',
116
+ type: Integer,
117
+ optional: true,
118
+ default_value: 300),
119
+ ::FastlaneCore::ConfigItem.new(key: :include_all_device_logs,
120
+ env_name: 'GATHER_SIMCTL_DIAGNOSE_INCLUDE_ALL_DEVICE_LOGS',
121
+ description: 'Include all device logs',
122
+ type: Boolean,
123
+ optional: true,
124
+ default_value: false),
125
+ ::FastlaneCore::ConfigItem.new(key: :include_booted_device_data_directory,
126
+ env_name: 'GATHER_SIMCTL_DIAGNOSE_INCLUDE_BOOTED_DEVICE_DATA_DIRECTORY',
127
+ description: 'Include booted device data directory. Warning: May include private information, app data containers, and increases the size of the archive! Default is NOT to collect the data container',
128
+ type: Boolean,
129
+ optional: true,
130
+ default_value: false)
131
+ ]
132
+ end
133
+
134
+ def self.output
135
+ [
136
+ ['GATHER_SIMCTL_DIAGNOSE_OUTPUT_FILE', 'Output archive file with simctl diagnose data']
137
+ ]
138
+ end
139
+
140
+ def self.return_value
141
+ 'Returns a path to the output archive file with simctl diagnose data'
142
+ end
143
+
144
+ def self.authors
145
+ ['nekrich']
146
+ end
147
+
148
+ def self.is_supported?(_platform) # rubocop:disable Naming/PredicatePrefix
149
+ true
150
+ end
151
+ end
152
+ end
153
+ end
@@ -12,15 +12,16 @@ module Fastlane
12
12
  class Runner # rubocop:disable Metrics/ClassLength
13
13
  UI = ::Fastlane::UI unless defined?(UI)
14
14
 
15
- attr_accessor :shell_helper, :verbose, :runtime_helper, :can_rename_devices, :can_delete_duplicate_devices, :device_naming_style
15
+ attr_accessor :shell_helper, :verbose, :runtime_helper, :can_rename_devices, :can_delete_duplicate_devices, :device_naming_style, :remove_cached_runtimes
16
16
 
17
- def initialize(runtime_helper:, shell_helper:, verbose:, can_rename_devices:, can_delete_duplicate_devices:, device_naming_style:) # rubocop:disable Metrics/ParameterLists
17
+ def initialize(runtime_helper:, shell_helper:, verbose:, can_rename_devices:, can_delete_duplicate_devices:, device_naming_style:, remove_cached_runtimes:) # rubocop:disable Metrics/ParameterLists
18
18
  self.shell_helper = shell_helper
19
19
  self.verbose = verbose
20
20
  self.runtime_helper = runtime_helper
21
21
  self.can_rename_devices = can_rename_devices
22
22
  self.can_delete_duplicate_devices = can_delete_duplicate_devices
23
23
  self.device_naming_style = device_naming_style
24
+ self.remove_cached_runtimes = remove_cached_runtimes
24
25
  end
25
26
 
26
27
  def run(devices)
@@ -43,7 +44,7 @@ module Fastlane
43
44
  end
44
45
 
45
46
  # Install missing runtimes if needed.
46
- runtime_helper.install_missing_runtimes(required_devices)
47
+ runtime_helper.install_missing_runtimes(required_devices, remove_cached_runtimes: remove_cached_runtimes)
47
48
 
48
49
  # Create missing devices for required devices.
49
50
  create_missing_devices(required_devices)
@@ -39,7 +39,7 @@ module Fastlane
39
39
  shell_helper.simctl_devices_for_runtimes(force: true)
40
40
  end
41
41
 
42
- def install_missing_runtimes(required_devices)
42
+ def install_missing_runtimes(required_devices, remove_cached_runtimes:)
43
43
  needed_runtimes = required_devices.filter_map(&:required_runtime).uniq
44
44
 
45
45
  missing_runtimes = missing_runtimes(needed_runtimes)
@@ -50,7 +50,7 @@ module Fastlane
50
50
  end
51
51
 
52
52
  missing_runtimes.each do |missing_runtime|
53
- download_and_install_missing_runtime(missing_runtime)
53
+ download_and_install_missing_runtime(missing_runtime, remove_cached_runtimes: remove_cached_runtimes)
54
54
  end
55
55
 
56
56
  # Update simctl_runtimes after installing the runtimes.
@@ -128,7 +128,7 @@ module Fastlane
128
128
  simctl_runtime
129
129
  end
130
130
 
131
- def download_and_install_missing_runtime(missing_runtime)
131
+ def download_and_install_missing_runtime(missing_runtime, remove_cached_runtimes:)
132
132
  UI.message("Attempting to install #{missing_runtime.runtime_name} runtime.")
133
133
 
134
134
  downloaded_runtime_file = cached_runtime_file(missing_runtime)
@@ -139,6 +139,8 @@ module Fastlane
139
139
  end
140
140
 
141
141
  shell_helper.import_runtime(downloaded_runtime_file, missing_runtime.runtime_name)
142
+
143
+ FileUtils.rm_rf(downloaded_runtime_file) if remove_cached_runtimes
142
144
  end
143
145
 
144
146
  def runtime_build_version_for_filename(filename)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fastlane'
4
+
5
+ module Fastlane
6
+ # Gather simctl diagnose data.
7
+ module GatherSimctlDiagnose
8
+ UI = ::Fastlane::UI unless defined?(UI)
9
+ end
10
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'module'
4
+ require 'fastlane'
5
+ require_relative 'shared_values'
6
+ require_relative '../create_simulator_devices/models/device_naming_style'
7
+
8
+ module Fastlane
9
+ # Gather simctl diagnose data.
10
+ module GatherSimctlDiagnose
11
+ # Does all the work to create simulator devices.
12
+ class Runner
13
+ UI = ::Fastlane::UI unless defined?(UI)
14
+
15
+ attr_accessor :shell_helper, :verbose, :runtime_helper, :device_naming_style, :create_simulator_devices_runner, :output_dir, :timeout, :include_all_device_logs, :include_booted_device_data_directory, :print_command, :print_command_output
16
+
17
+ def initialize( # rubocop:disable Metrics/ParameterLists
18
+ runtime_helper:,
19
+ shell_helper:,
20
+ verbose:,
21
+ device_naming_style:,
22
+ create_simulator_devices_runner:,
23
+ output_dir:,
24
+ timeout:,
25
+ include_all_device_logs:,
26
+ include_booted_device_data_directory:
27
+ )
28
+ self.shell_helper = shell_helper
29
+ self.verbose = verbose
30
+ self.runtime_helper = runtime_helper
31
+ self.device_naming_style = device_naming_style
32
+ self.create_simulator_devices_runner = create_simulator_devices_runner
33
+ self.output_dir = output_dir
34
+ self.timeout = timeout
35
+ self.include_all_device_logs = include_all_device_logs
36
+ self.include_booted_device_data_directory = include_booted_device_data_directory
37
+ end
38
+
39
+ def run(devices) # rubocop:disable Metrics/AbcSize
40
+ UI.message("Simulator devices to gather diagnose data: #{devices.join(', ')}")
41
+
42
+ # Create distict required devices from a given list of device strings.
43
+ required_devices = devices
44
+ .filter_map { |device| create_simulator_devices_runner.required_device_for_device(device) }
45
+ .uniq { |required_device| [required_device.device_type.name, required_device.required_runtime.product_version] }
46
+
47
+ if verbose
48
+ UI.message('Unique required devices:')
49
+ UI.message(" #{required_devices.map(&:description).join("\n ")}")
50
+ end
51
+
52
+ # Return distinct matched devices strings
53
+ matched_devices = create_simulator_devices_runner.find_runtime_and_device_for_required_devices(required_devices)
54
+ .reject { |required_device| required_device.simctl_device.nil? }
55
+
56
+ matched_devices_udids = matched_devices.map { |matched_device| matched_device.simctl_device.udid }
57
+ UI.message("Available simulator devices: #{matched_devices_udids.join(', ')}")
58
+
59
+ temp_output_dir = "#{File.expand_path(output_dir)}/simctl_diagnose_#{Time.now.strftime('%Y%m%d%H%M%S')}"
60
+
61
+ diagnose_args = matched_devices_udids.map { |udid| "--udid=#{udid}" }
62
+ diagnose_args << '-b' # Do NOT show the resulting archive in a Finder window upon completion.
63
+ diagnose_args << '--all-logs' if include_all_device_logs
64
+ diagnose_args << '--data-container' if include_booted_device_data_directory
65
+ diagnose_args << "--timeout=#{timeout}"
66
+
67
+ cmd_args = diagnose_args.map(&:shellescape).join(' ')
68
+
69
+ collect_diagnose_data_script_path = File.expand_path("#{__dir__}/scripts/collect_simctl_diagnose_data.sh")
70
+
71
+ shell_helper.sh(
72
+ command: "SIMCTL_DIAGNOSE_OUTPUT_FOLDER=#{temp_output_dir.shellescape} #{collect_diagnose_data_script_path.shellescape} #{cmd_args}",
73
+ print_command: verbose,
74
+ print_command_output: verbose
75
+ )
76
+
77
+ archive_name = "#{temp_output_dir}.tar.gz"
78
+ Actions.lane_context[Actions::SharedValues::GATHER_SIMCTL_DIAGNOSE_OUTPUT_FILE] = archive_name
79
+
80
+ archive_name
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env expect
2
+
3
+ # Runs xcrun simctl diagnose with given parameters.
4
+ # xcrun simctl diagnose needs user to press ENTER which is not possible to do in non-interactive shell.
5
+
6
+ spawn xcrun simctl diagnose {*}$argv
7
+ expect -exact "Press ENTER to continue\r\n"
8
+ send -- "\r"
9
+ expect eof
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Runs xcrun simctl diagnose with given parameters.
4
+ # Manages the output folder and the archive.
5
+ #
6
+ # When --data-container is passed simctl diagnose doesn't create archive,
7
+ # and w/o archive the artifacts step on CI hangs.
8
+ #
9
+ # For this case we handle the archive creation manually.
10
+
11
+ set -Eeo pipefail
12
+
13
+ export SIMCTL_DIAGNOSE_OUTPUT_FOLDER="${SIMCTL_DIAGNOSE_OUTPUT_FOLDER:-"logs/simctl_diagnose"}"
14
+
15
+ FOLDER_NAME="$(basename "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}")"
16
+ OUTPUT_FOLDER_PATH="$(dirname "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}")"
17
+
18
+ echo "Cleaning up previous simctl logs at ${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}"
19
+ rm -rf "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}" || true
20
+ rm -rf "${OUTPUT_FOLDER_PATH}/${FOLDER_NAME}."* || true
21
+ mkdir -p "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}"
22
+
23
+ echo "Collecting simctl logs to ${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}..."
24
+ "$(dirname "${0}")/$(basename "${0}" .sh).expect" "${@}" --output="${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}"
25
+
26
+ if [ -d "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}" ]; then
27
+ echo "Compressing simctl logs to ${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}.tar.gz..."
28
+ cd "${OUTPUT_FOLDER_PATH}"
29
+ tar -czf "${FOLDER_NAME}.tar.gz" "${FOLDER_NAME}"
30
+ echo "Removing folder ${FOLDER_NAME}"
31
+ # Remove folder becuse it contains symlinks and zip doesn't remove them and tar doesn't remove it at all.
32
+ rm -rf "${FOLDER_NAME}" || true
33
+ echo "Archive size: $(du -h "${FOLDER_NAME}.tar.gz" | cut -f1)"
34
+ elif [ -f "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}.zip" ]; then
35
+ echo "Archive size: $(du -h "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}.zip" | cut -f1)"
36
+ elif [ -f "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}.tar.gz" ]; then
37
+ echo "Archive size: $(du -h "${SIMCTL_DIAGNOSE_OUTPUT_FOLDER}.tar.gz" | cut -f1)"
38
+ fi
39
+
40
+ echo "Simctl logs collected successfully at $OUTPUT_FOLDER_PATH"
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fastlane'
4
+
5
+ module Fastlane
6
+ module Actions
7
+ module SharedValues
8
+ GATHER_SIMCTL_DIAGNOSE_OUTPUT_FILE = :GATHER_SIMCTL_DIAGNOSE_OUTPUT_FILE
9
+ end
10
+ end
11
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fastlane
4
4
  module CreateSimulatorDevices
5
- VERSION = '0.0.13'
5
+ VERSION = '0.0.15'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
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.13
4
+ version: 0.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vitalii Budnik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-29 00:00:00.000000000 Z
11
+ date: 2025-09-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: developers@setapp.com
@@ -20,6 +20,7 @@ files:
20
20
  - README.md
21
21
  - lib/fastlane/plugin/create_simulator_devices.rb
22
22
  - lib/fastlane/plugin/create_simulator_devices/actions/create_simulator_devices_action.rb
23
+ - lib/fastlane/plugin/create_simulator_devices/actions/gather_simctl_diagnose_action.rb
23
24
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models.rb
24
25
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models/apple_build_version.rb
25
26
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/models/device_naming_style.rb
@@ -34,6 +35,11 @@ files:
34
35
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/runtime_helper.rb
35
36
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/shared_values.rb
36
37
  - lib/fastlane/plugin/create_simulator_devices/helpers/create_simulator_devices/shell_helper.rb
38
+ - lib/fastlane/plugin/create_simulator_devices/helpers/gather_simctl_diagnose/module.rb
39
+ - lib/fastlane/plugin/create_simulator_devices/helpers/gather_simctl_diagnose/runner.rb
40
+ - lib/fastlane/plugin/create_simulator_devices/helpers/gather_simctl_diagnose/scripts/collect_simctl_diagnose_data.expect
41
+ - lib/fastlane/plugin/create_simulator_devices/helpers/gather_simctl_diagnose/scripts/collect_simctl_diagnose_data.sh
42
+ - lib/fastlane/plugin/create_simulator_devices/helpers/gather_simctl_diagnose/shared_values.rb
37
43
  - lib/fastlane/plugin/create_simulator_devices/version.rb
38
44
  homepage:
39
45
  licenses: