bugsnag-maze-runner 8.9.0 → 8.10.0

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: 03c53d6f8594ce559c2f2fb6296617d9b9f18227220b3a1148f297de154b8d60
4
- data.tar.gz: 3ce0a4585f6caac3ed1291f8a9ca8921926dbe551dd298ea6d8c8299136a67c5
3
+ metadata.gz: f0ea35795ffa2a45ce5190bde9317c508e631958504e47da4c8eaac20a5244b6
4
+ data.tar.gz: 90220645b3c2bcc5cfbb9823792bc8aee868e8fd6054fc7f6384dde01d55c5ea
5
5
  SHA512:
6
- metadata.gz: cf7ef0e05814ee96ddcc363de952c0f56cce6c98721ef3bf79ad7ade296d7390d5dc513efb1ac83645aba734a957c685fea9290d4980cf0de5986544340d34ae
7
- data.tar.gz: 7a967300d0dfcba750dfbce12c31a70e3793d98c822d35de70ec9838658e8436bad3962668bd70a50ff087236c74b174332b899406e906f42cbdf2475b643aea
6
+ metadata.gz: da920e3f04b2ae46e0c6eaae5796569c267ca59f1e3f8371af49109488fe5cbda31b68f36e3bd7b44cd9fac182afdc0d0ccc818872c01cda8fcf1d4b7722a705
7
+ data.tar.gz: 2379fbc274fffdd37834b5041393403036ff4f995bcc20845e462d51fe20672e0b0abb53172bb5e5059ec2a013af4ba2e0f3ca941d7522125b293438b6ca40f3
@@ -9,6 +9,7 @@ module Maze
9
9
 
10
10
  def initialize
11
11
  @session_ids = []
12
+ @start_attempts = 0
12
13
  end
13
14
 
14
15
  def start_session
@@ -47,51 +48,38 @@ module Maze
47
48
  raise 'Method not implemented by this class'
48
49
  end
49
50
 
50
- def start_driver(config)
51
- retry_failure = retry_start_driver?
52
- driver = nil
53
- until Maze.driver
54
- begin
55
-
56
-
57
- # Proc to start the driver
58
- start_driver_closure = Proc.new do
59
- begin
60
- config.capabilities = device_capabilities
61
- driver = Maze::Driver::Appium.new config.appium_server_url,
62
- config.capabilities,
63
- config.locator
64
-
65
- result = driver.start_driver
66
- if result
67
- # Log details of this session
68
- $logger.info "Created Appium session: #{driver.session_id}"
69
- @session_ids << driver.session_id
70
- udid = driver.session_capabilities['udid']
71
- $logger.info "Running on device: #{udid}" unless udid.nil?
72
- end
73
- result
74
- rescue => error
75
- Bugsnag.notify error
76
- $logger.error "Session creation failed: #{error}"
77
- false
78
- end
79
- end
51
+ def attempt_start_driver(config)
52
+ config.capabilities = device_capabilities
53
+ driver = Maze::Driver::Appium.new config.appium_server_url,
54
+ config.capabilities,
55
+ config.locator
56
+
57
+ result = driver.start_driver
58
+ if result
59
+ # Log details of this session
60
+ $logger.info "Created Appium session: #{driver.session_id}"
61
+ @session_ids << driver.session_id
62
+ udid = driver.session_capabilities['udid']
63
+ $logger.info "Running on device: #{udid}" unless udid.nil?
64
+ end
65
+ driver
66
+ end
80
67
 
68
+ def start_driver(config, max_attempts = 5)
81
69
 
82
- # Invoke the proc, with or without retries
83
- if retry_failure
84
- wait = Maze::Wait.new(interval: 10, timeout: 60)
85
- success = wait.until(&start_driver_closure)
86
- else
87
- success = start_driver_closure.call
88
- end
70
+ attempts = 0
89
71
 
90
- unless success
91
- $logger.error 'Failed to create Appium driver, exiting'
92
- exit(::Maze::Api::ExitCode::SESSION_CREATION_FAILURE)
93
- end
72
+ while attempts < max_attempts && Maze.driver.nil?
73
+ attempts += 1
74
+ start_error = nil
75
+ begin
76
+ Maze.driver = attempt_start_driver(config)
77
+ rescue => error
78
+ $logger.error "Session creation failed: #{error}"
79
+ start_error = error
80
+ end
94
81
 
82
+ if Maze.driver
95
83
  # Infer OS version if necessary when running locally
96
84
  if Maze.config.farm == :local && Maze.config.os_version.nil?
97
85
  version = case Maze.config.os
@@ -103,23 +91,23 @@ module Maze
103
91
  $logger.info "Inferred OS version to be #{version}"
104
92
  Maze.config.os_version = version
105
93
  end
106
-
107
- Maze.driver = driver
108
- rescue ::Selenium::WebDriver::Error::UnknownError => original_exception
109
- $logger.warn "Attempt to acquire #{config.device} device from farm #{config.farm} failed"
110
- $logger.warn "Exception: #{original_exception.message}"
111
- if config.device_list.empty?
112
- $logger.error 'No further devices to try - raising original exception'
113
- raise original_exception
94
+ else
95
+ interval = handle_error(start_error)
96
+ if interval && attempts < max_attempts
97
+ $logger.warn "Failed to create Appium driver, retrying in #{interval} seconds"
98
+ Kernel::sleep interval
114
99
  else
115
- config.device = config.device_list.first
116
- config.device_list = config.device_list.drop(1)
117
- $logger.warn "Retrying driver initialisation using next device: #{config.device}"
100
+ $logger.error 'Failed to create Appium driver, exiting'
101
+ Kernel::exit(::Maze::Api::ExitCode::SESSION_CREATION_FAILURE)
118
102
  end
119
103
  end
120
104
  end
121
105
  end
122
106
 
107
+ def handle_error(error)
108
+ raise 'Method not implemented by this class'
109
+ end
110
+
123
111
  def start_scenario
124
112
  # Launch the app on macOS
125
113
  Maze.driver.get(Maze.config.app) if Maze.config.os == 'macos'
@@ -13,8 +13,29 @@ module Maze
13
13
  end
14
14
  end
15
15
 
16
- def retry_start_driver?
17
- false
16
+ def handle_error(error)
17
+ # Retry interval depends on the error message
18
+ return nil if error.nil?
19
+
20
+ interval = nil
21
+ notify = true
22
+
23
+ if error.message.include? 'no sessionId in returned payload'
24
+ # This will happen naturally due to a race condition in how we access devices
25
+ # Do not notify, but wait long enough for most ghost sessions on BitBar to terminate.
26
+ interval = 60
27
+ notify = false
28
+ elsif error.message.include? 'You reached the account concurrency limit'
29
+ # In theory this shouldn't happen, but back off if it does
30
+ interval = 300
31
+ elsif error.message.include? 'There are no devices available'
32
+ interval = 120
33
+ else
34
+ # Do not retry in any other case
35
+ end
36
+
37
+ Bugsnag.notify error if notify
38
+ interval
18
39
  end
19
40
 
20
41
  def start_scenario
@@ -29,12 +50,18 @@ module Maze
29
50
  end
30
51
 
31
52
  def device_capabilities
53
+ # Doubling up on capabilities in both the `appium:options` and `appium` sub dictionaries.
54
+ # See PLAT-11087
32
55
  config = Maze.config
33
56
  capabilities = {
34
57
  'appium:options' => {
35
58
  'noReset' => true,
36
59
  'newCommandTimeout' => 600
37
60
  },
61
+ 'appium' => {
62
+ 'noReset' => true,
63
+ 'newCommandTimeout' => 600
64
+ },
38
65
  'bitbar:options' => {
39
66
  # Some capabilities probably belong in the top level
40
67
  # of the hash, but BitBar picks them up from here.
@@ -20,8 +20,7 @@ module Maze
20
20
  $logger.trace "Got group ids #{device_group_ids} for #{device_or_group_names}"
21
21
  group_count, device = api_client.find_device_in_groups(device_group_ids)
22
22
  if device.nil?
23
- # TODO: Retry rather than fail, see PLAT-7377
24
- Maze::Helper.error_exit 'There are no devices available'
23
+ raise 'There are no devices available'
25
24
  else
26
25
  $logger.info "#{group_count} device(s) currently available in group(s) '#{device_or_group_names}'"
27
26
  end
@@ -92,6 +91,8 @@ module Maze
92
91
  end
93
92
 
94
93
  def make_android_hash(device)
94
+ # Doubling up on capabilities in both the `appium:options` and `appium` sub dictionaries.
95
+ # See PLAT-11087
95
96
  hash = {
96
97
  'platformName' => 'Android',
97
98
  'deviceName' => 'Android Phone',
@@ -100,6 +101,11 @@ module Maze
100
101
  'autoGrantPermissions' => true,
101
102
  'uiautomator2ServerInstallTimeout' => 60000
102
103
  },
104
+ 'appium' => {
105
+ 'automationName' => 'UiAutomator2',
106
+ 'autoGrantPermissions' => true,
107
+ 'uiautomator2ServerInstallTimeout' => 60000
108
+ },
103
109
  'bitbar:options' => {
104
110
  'device' => device,
105
111
  }
@@ -108,6 +114,8 @@ module Maze
108
114
  end
109
115
 
110
116
  def make_ios_hash(device)
117
+ # Doubling up on capabilities in both the `appium:options` and `appium` sub dictionaries.
118
+ # See PLAT-11087
111
119
  {
112
120
  'platformName' => 'iOS',
113
121
  'deviceName' => 'iPhone device',
@@ -115,6 +123,10 @@ module Maze
115
123
  'automationName' => 'XCUITest',
116
124
  'shouldTerminateApp' => 'true'
117
125
  },
126
+ 'appium' => {
127
+ 'automationName' => 'XCUITest',
128
+ 'shouldTerminateApp' => 'true'
129
+ },
118
130
  'bitbar:options' => {
119
131
  'device' => device
120
132
  }
@@ -15,8 +15,18 @@ module Maze
15
15
  end
16
16
  end
17
17
 
18
- def retry_start_driver?
19
- Maze.config.device_list.nil? || Maze.config.device_list.empty?
18
+ # On BrowserStack, wait 10 seconds before retrying if there is another device in the list
19
+ def handle_error(error)
20
+ Bugsnag.notify error unless error.nil?
21
+ if Maze.config.device_list.nil? || config.device_list.empty?
22
+ $logger.error 'No further devices to try'
23
+ nil
24
+ else
25
+ config.device = config.device_list.first
26
+ config.device_list = config.device_list.drop(1)
27
+ $logger.warn "Retrying driver initialisation using next device: #{config.device}"
28
+ 10
29
+ end
20
30
  end
21
31
 
22
32
  def start_scenario
@@ -48,6 +48,10 @@ module Maze
48
48
  capabilities
49
49
  end
50
50
 
51
+ def retry_start_driver?
52
+ false
53
+ end
54
+
51
55
  def log_run_intro
52
56
  # Nothing to do
53
57
  end
data/lib/maze.rb CHANGED
@@ -7,7 +7,7 @@ require_relative 'maze/timers'
7
7
  # Glues the various parts of MazeRunner together that need to be accessed globally,
8
8
  # providing an alternative to the proliferation of global variables or singletons.
9
9
  module Maze
10
- VERSION = '8.9.0'
10
+ VERSION = '8.10.0'
11
11
 
12
12
  class << self
13
13
  attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bugsnag-maze-runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.9.0
4
+ version: 8.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Kirkland
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-19 00:00:00.000000000 Z
11
+ date: 2023-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber