fastlane-plugin-maestro_orchestration 0.1.2 → 0.1.3

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: 8a7c5dbca859567bb493407556a8f57fdcfa6c7ed7adb62283fab7b4eae6d9d2
4
- data.tar.gz: 92419becfc82aabadf3086bc016937b3562c775e55d93c2af90d4641d6156a66
3
+ metadata.gz: 31054bd007a386794670905de05851f52f08ec754a2ace35738005dcafc761f5
4
+ data.tar.gz: f34f027a6eceed37ba8c6de14a5fb5f06c59dce196cdc59e5b6944147820772e
5
5
  SHA512:
6
- metadata.gz: fea7514fa69e381fb3c7e2498bc317a26f109357b55ba6fabcb80af3fc2205064709665fedbba0661a5d82c1ab9eff6d5d5d1b3db10850ebd3d37e026cfa0a7c
7
- data.tar.gz: 2b0a06c1410d717711657dccfed51f982dc25e4012ce13afe098673b32427fbfe70b8eb3c68d0f663acef6874d67fefc4129a97bb665ed97ea738fff51f29c0d
6
+ metadata.gz: 542ab46c6d2b8f30f77b6a5800829443a96d1427c5db632c399bacbc3f1dec302421de6f81d7768b7c82e90047ec7892c33a2c02e2052a878d34f84934dbf4d7
7
+ data.tar.gz: 2c2e163734d8e63bc4177ed4f86edbb20a05503ef8af892f159f047eceb13114df54424d18585ad678304f903e41e396062a9ed8f6ff4a82d113c2dcfad9ecaf
data/README.md CHANGED
@@ -28,15 +28,12 @@ Executes Maestro test suites within your Fastlane lanes, facilitating automated
28
28
  | `device_type` | `MAESTRO_IOS_DEVICE` | The iOS simulator device type for new simulator (e.g., iPhone #, iPad, etc...). <br> **Default value:** 'com.apple.CoreSimulator.SimDeviceType.iPhone-15'|
29
29
 
30
30
  ## Parameters `Android`
31
-
31
+ For Android, we utilize the [Android Emulator Runner](https://github.com/ReactiveCircus/android-emulator-runner
32
+ ) by ReactiveCircus, which efficiently manages the setup and initialization of the emulator.
32
33
  | Parameter | Env Name | Notes |
33
34
  | ------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
34
35
  | `sdk_dir` | `MAESTRO_ANDROID_SDK_DIR` | Path to the Android SDK DIR. <br> **Required** `ENV["ANDROID_HOME"]`, `ENV["ANDROID_SDK_ROOT"]`, `~/Library/Android/sdk` |
35
36
  | `maestro_flow_file` | `MAESTRO_IOS_FLOW_FILE` | The path to the Maestro flows YAML file. <br> **Required** |
36
- | `emulator_name` | `MAESTRO_AVD_NAME` | Name of the AVD. <br> **Default value:** 'Maestro\_Android\_Emulator' |
37
- | `emulator_package` | `MAESTRO_AVD_PACKAGE` | The selected system image of the emulator. <br> **Default value:** 'system-images;android-35;google_apis_playstore;arm64-v8a' |
38
- | `emulator_device` | `MAESTRO_AVD_DEVICE` | Type of android device. <br> **Default value:** 'pixel_7_pro' |
39
- | `emulator_port` | `MAESTRO_AVD_PORT` | Port of the emulator. <br> **Default value:** 5554 |
40
37
 
41
38
  ### 2. `maestro_orchestartion_s3_upload`
42
39
  Uploads a folder of files (such as screenshots) to an S3 bucket, organizing them based on the app version, theme, and device type.
@@ -7,7 +7,7 @@ module Fastlane
7
7
  module Actions
8
8
  class MaestroOrchestrationAndroidAction < Action
9
9
  def self.run(params)
10
- required_params = [:emulator_package, :emulator_device, :maestro_flow_file]
10
+ required_params = [:maestro_flow_file]
11
11
  missing_params = required_params.select { |param| params[param].nil? }
12
12
 
13
13
  if missing_params.any?
@@ -21,8 +21,7 @@ module Fastlane
21
21
 
22
22
  adb = Helper::AdbHelper.new
23
23
 
24
- setup_emulator(params)
25
- sleep(5)
24
+ sleep(5) # Give time emulator to boot
26
25
  demo_mode(params)
27
26
  install_android_app(params)
28
27
 
@@ -46,82 +45,6 @@ module Fastlane
46
45
  UI.success("Android emulator killed. Process finished.")
47
46
  end
48
47
 
49
- def self.setup_emulator(params)
50
- emulator = Helper::EmulatorHelper.new
51
- adb = Helper::AdbHelper.new
52
- avdmanager = Helper::AvdHelper.new
53
-
54
- UI.message("Stop all running emulators...")
55
- devices = adb.load_all_devices
56
- UI.success("Devices: #{devices}")
57
-
58
- if devices.empty?
59
- UI.message("No running emulators found.")
60
- else
61
- devices.each do |device|
62
- UI.message("Stopping emulator: #{device.serial}")
63
- adb.trigger(command: "emu kill", serial: device.serial)
64
- sleep(10)
65
- system("Stopped emulator: #{device.serial}")
66
- end
67
- end
68
- UI.message("Waiting for all emulators to stop...")
69
- sleep(10)
70
-
71
- # Check if there is an AVD with this name, if so, delete it
72
- UI.message("Checking if AVD exists with name: #{params[:emulator_name]}...")
73
- avd_exists = `#{avdmanager.avdmanager_path} list avd`.include?(params[:emulator_name])
74
-
75
- if avd_exists
76
- UI.message("AVD found, deleting existing AVD: #{params[:emulator_name]}...")
77
- avdmanager.delete_avd(name: params[:emulator_name])
78
- else
79
- UI.message("No existing AVD found with that name.")
80
- end
81
-
82
- UI.message("Setting up new Android emulator...")
83
- avdmanager.create_avd(name: params[:emulator_name], package: params[:emulator_package], device: params[:emulator_device])
84
-
85
- UI.message("Starting Android emulator...")
86
- emulator.start_emulator(name: params[:emulator_name], port: params[:emulator_port])
87
- adb.trigger(command: "wait-for-device", serial: "emulator-#{params[:emulator_port]}")
88
-
89
- max_retries = 10
90
- booted = Helper::MaestroOrchestrationHelper.wait_for_emulator_to_boot(adb, max_retries, "emulator-#{params[:emulator_port]}")
91
-
92
- unless booted
93
- UI.error("Emulator failed to boot after #{max_retries} attempts. Restarting ADB server...")
94
- adb.trigger(command: "kill-server")
95
-
96
- # Shut down the current emulator, delete it, create a new one, and restart ADB server
97
- UI.message("Shutting down current emulator and deleting the AVD...")
98
- adb.trigger(command: "emu kill", serial: "emulator-#{params[:emulator_port]}")
99
- sleep(5) # Ensure the emulator is killed
100
- avdmanager.delete_avd(name: params[:emulator_name])
101
-
102
- UI.message("Creating new AVD...")
103
- avdmanager.create_avd(name: params[:emulator_name], package: params[:emulator_package], device: params[:emulator_device])
104
-
105
- UI.message("Restarting ADB server...")
106
- adb.trigger(command: "start-server")
107
- UI.message("ADB server restarted. Starting new emulator...")
108
-
109
- # Start the newly created emulator
110
- emulator.start_emulator(name: params[:emulator_name], port: params[:emulator_port])
111
- adb.trigger(command: "wait-for-device", serial: "emulator-#{params[:emulator_port]}")
112
-
113
- # Retry boot process after restarting ADB server
114
- booted = Helper::MaestroOrchestrationHelper.wait_for_emulator_to_boot(adb, max_retries, "emulator-#{params[:emulator_port]}")
115
- end
116
-
117
- if booted
118
- UI.success("Emulator is online and fully booted!")
119
- else
120
- UI.error("Emulator failed to boot even after restarting AVD and ADB server.")
121
- raise "Failed to boot emulator. Please check emulator logs and configuration."
122
- end
123
- end
124
-
125
48
  def self.demo_mode(params)
126
49
  adb = Helper::AdbHelper.new
127
50
  adb.load_all_devices
@@ -144,10 +67,14 @@ module Fastlane
144
67
  adb.load_all_devices
145
68
  serial = adb.devices.first.serial
146
69
 
70
+ UI.message("Generating 'assembleRelease' build...")
71
+ # Trigger the 'assembleRelease' build
72
+ system("./gradlew assembleRelease")
73
+ # After building, try to find the APK file in the release output directory
147
74
  apk_path = Dir["app/build/outputs/apk/release/*.apk"].first
148
-
75
+ # If still not found after building, raise an error
149
76
  if apk_path.nil?
150
- UI.user_error!("Error: APK file not found in build outputs.")
77
+ UI.user_error!("Error: APK file not found in build outputs even after running assembleRelease.")
151
78
  end
152
79
 
153
80
  UI.message("Found APK file at: #{apk_path}")
@@ -171,41 +98,6 @@ module Fastlane
171
98
  UI.user_error!("No ANDROID_SDK_DIR given, pass using `sdk_dir: 'sdk_dir'`") unless value && !value.empty?
172
99
  end
173
100
  ),
174
- FastlaneCore::ConfigItem.new(
175
- key: :emulator_name,
176
- env_name: "MAESTRO_AVD_NAME",
177
- description: "Name of the AVD",
178
- default_value: "Maestro_Android_Emulator",
179
- optional: true
180
- ),
181
- FastlaneCore::ConfigItem.new(
182
- key: :emulator_package,
183
- env_name: "MAESTRO_AVD_PACKAGE",
184
- description: "The selected system image of the emulator",
185
- default_value: "system-images;android-35;google_apis_playstore;arm64-v8a",
186
- optional: true
187
- ),
188
- FastlaneCore::ConfigItem.new(
189
- key: :emulator_device,
190
- env_name: "MAESTRO_AVD_DEVICE",
191
- description: "Device",
192
- default_value: "pixel_7_pro",
193
- optional: true
194
- ),
195
- FastlaneCore::ConfigItem.new(
196
- key: :location,
197
- env_name: "MAESTRO_AVD_LOCATION",
198
- description: "Set location of the emulator '<longitude> <latitude>'",
199
- default_value: "28.0362979, -82.4930012",
200
- optional: true
201
- ),
202
- FastlaneCore::ConfigItem.new(
203
- key: :emulator_port,
204
- env_name: "MAESTRO_AVD_PORT",
205
- description: "Port of the emulator",
206
- default_value: "5554",
207
- optional: true
208
- ),
209
101
  FastlaneCore::ConfigItem.new(
210
102
  key: :maestro_flow_file,
211
103
  env_name: "MAESTRO_ANDROID_FLOW_FILE",
@@ -10,8 +10,35 @@ module Fastlane
10
10
  # class methods that you define here become available in your action
11
11
  # as `Helper::MaestroOrchestrationHelper.your_method`
12
12
  #
13
- def self.show_message
14
- UI.message("Hello from the maestro_orchestration plugin helper!")
13
+ def self.stop_all_emulators(adb)
14
+ UI.message("Stop all running emulators...")
15
+ devices = adb.load_all_devices
16
+ UI.success("Devices: #{devices}")
17
+
18
+ devices.each do |device|
19
+ UI.message("Stopping emulator: #{device.serial}")
20
+ adb.trigger(command: "emu kill", serial: device.serial)
21
+ sleep(10)
22
+ end
23
+ UI.message("Waiting for all emulators to stop...")
24
+ sleep(10)
25
+ end
26
+
27
+ def self.handle_boot_failure(params, avdmanager, adb, emulator)
28
+ adb.trigger(command: "kill-server")
29
+ adb.trigger(command: "emu kill", serial: "emulator-#{params[:emulator_port]}")
30
+ sleep(5)
31
+ avdmanager.delete_avd(name: params[:emulator_name])
32
+
33
+ UI.message("Creating new AVD...")
34
+ avdmanager.create_avd(name: params[:emulator_name], package: params[:emulator_package], device: params[:emulator_device])
35
+
36
+ UI.message("Restarting ADB server...")
37
+ adb.trigger(command: "start-server")
38
+ UI.message("ADB server restarted. Starting new emulator...")
39
+
40
+ emulator.start_emulator(name: params[:emulator_name], port: params[:emulator_port])
41
+ adb.trigger(command: "wait-for-device", serial: "emulator-#{params[:emulator_port]}")
15
42
  end
16
43
 
17
44
  def self.wait_for_emulator_to_boot(adb, max_retries, serial)
@@ -85,104 +112,5 @@ module Fastlane
85
112
  UI.error("Error removing file #{file_path}: #{e.message}")
86
113
  end
87
114
  end
88
-
89
- class AvdHelper
90
- # Path to the avd binary
91
- attr_accessor :avdmanager_path
92
- # Available AVDs
93
- attr_accessor :avds
94
-
95
- def initialize(avdmanager_path: nil)
96
- android_home = ENV.fetch('ANDROID_HOME', nil) || ENV.fetch('ANDROID_SDK_ROOT', nil)
97
- if (avdmanager_path.nil? || avdmanager_path == "avdmanager") && android_home
98
- # First search for cmdline-tools dir
99
- cmdline_tools_path = File.join(android_home, "cmdline-tools")
100
-
101
- # Find the first available 'bin' folder within cmdline-tools
102
- available_path = Dir.glob(File.join(cmdline_tools_path, "*", "bin")).first
103
- raise "No valid bin path found in #{cmdline_tools_path}" unless available_path
104
-
105
- avdmanager_path = File.join(available_path, "avdmanager")
106
- end
107
-
108
- self.avdmanager_path = Helper.get_executable_path(File.expand_path(avdmanager_path))
109
- end
110
-
111
- def trigger(command: nil)
112
- raise "avdmanager_path is not set" unless avdmanager_path
113
-
114
- # Build and execute the command
115
- command = [avdmanager_path.shellescape, command].compact.join(" ").strip
116
- Action.sh(command)
117
- end
118
-
119
- # Create a new AVD
120
- def create_avd(name:, package:, device: "pixel_7_pro")
121
- raise "AVD name is required" if name.nil? || name.empty?
122
- raise "System image package is required" if package.nil? || package.empty?
123
-
124
- command = [
125
- "create avd",
126
- "-n #{name.shellescape}",
127
- "-f",
128
- "-k \"#{package}\"",
129
- "-d #{device.shellescape}"
130
- ].join(" ")
131
-
132
- trigger(command: command)
133
- end
134
-
135
- # Delete an existing AVD
136
- def delete_avd(name:)
137
- raise "AVD name is required" if name.nil? || name.empty?
138
-
139
- command = [
140
- "delete avd",
141
- "-n #{name.shellescape}"
142
- ].join(" ")
143
-
144
- trigger(command: command)
145
- end
146
- end
147
-
148
- class EmulatorHelper
149
- attr_accessor :emulator_path
150
-
151
- def initialize(emulator_path: nil)
152
- android_home = ENV.fetch('ANDROID_HOME', nil) || ENV.fetch('ANDROID_SDK_ROOT', nil)
153
- if (emulator_path.nil? || emulator_path == "avdmanager") && android_home
154
- emulator_path = File.join(android_home, "emulator", "emulator")
155
- end
156
-
157
- self.emulator_path = Helper.get_executable_path(File.expand_path(emulator_path))
158
- end
159
-
160
- def trigger(command: nil)
161
- raise "emulator_path is not set" unless emulator_path
162
-
163
- # Build and execute the command
164
- command = [emulator_path.shellescape, command].compact.join(" ").strip
165
- Action.sh(command)
166
- end
167
-
168
- # Start an emulator instance
169
- def start_emulator(name:, port:)
170
- raise "Emulator name is required" if name.nil? || name.empty?
171
- raise "Port is required" if port.nil? || port.to_s.empty?
172
-
173
- command = [
174
- "-avd #{name.shellescape}",
175
- "-port #{port.shellescape}",
176
- "-wipe-data",
177
- "-no-boot-anim",
178
- "-no-snapshot",
179
- "-no-audio",
180
- "> /dev/null 2>&1 &"
181
- ].join(" ")
182
-
183
- UI.message("Starting emulator #{name} on port #{port}...")
184
- trigger(command: command)
185
- end
186
- end
187
115
  end
188
116
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module MaestroOrchestration
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-maestro_orchestration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nemanja Risteski
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-02-04 00:00:00.000000000 Z
10
+ date: 2025-02-13 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: fastlane-plugin-android_emulator