Skip to content

Commit d953bad

Browse files
committed
[build] implement steps for running failing rbe tests with debugging turned on
1 parent 7d96b28 commit d953bad

File tree

5 files changed

+159
-66
lines changed

5 files changed

+159
-66
lines changed

.github/workflows/bazel.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ on:
6161
required: false
6262
type: string
6363
default: ''
64+
download-name:
65+
description: name of artifact to download
66+
required: false
67+
type: string
68+
default: ''
69+
download-path:
70+
description: path of artifact to download
71+
required: false
72+
type: string
73+
default: ''
6474
upload-name:
6575
description: Name of artifact to upload
6676
required: false
@@ -160,6 +170,12 @@ jobs:
160170
- name: Setup curl for Ubuntu
161171
if: inputs.os == 'ubuntu'
162172
run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev
173+
- name: "Download artifact"
174+
if: ${{ inputs.download-name != '' && inputs.download-path != '' }}
175+
uses: actions/download-artifact@v4
176+
with:
177+
name: ${{ inputs.download-name }}
178+
path: ${{ inputs.download-path }}
163179
- name: Run Bazel
164180
run: ${{ inputs.run }}
165181
- name: Start SSH session

.github/workflows/ci-rbe.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ on:
77
- trunk
88
workflow_dispatch:
99

10+
env:
11+
BAZEL_LOG_FILE: bazel-logs/bazel_${{ github.workflow }}_${{ github.run_id }}.log
12+
1013
jobs:
1114
format:
1215
name: Format
@@ -26,4 +29,36 @@ jobs:
2629
name: All RBE tests
2730
caching: false
2831
ruby-version: jruby-9.4.12.0
32+
upload-name: bazel-logs
33+
upload-path: bazel-logs/bazel_${{ github.workflow }}_${{ github.run_id }}.log
2934
run: ./scripts/github-actions/ci-build.sh
35+
retry-remote:
36+
name: Retry Failed Tests on RBE
37+
needs: test
38+
if: always() && needs.test.result == 'failure' && github.repository_owner == 'seleniumhq' && startsWith(github.head_ref, 'renovate/') != true
39+
uses: ./.github/workflows/bazel.yml
40+
with:
41+
name: Retry failed tests
42+
caching: false
43+
ruby-version: jruby-9.4.12.0
44+
download-name: bazel-logs
45+
download-path: bazel-logs
46+
upload-name: remote-retry-logs
47+
upload-path: bazel-logs
48+
run: |
49+
./go retry_failed_tests "${BAZEL_LOG_FILE}" true
50+
retry-local:
51+
name: Retry Failed Tests on Local
52+
needs: test
53+
if: always() && needs.test.result == 'failure' && github.repository_owner == 'seleniumhq' && startsWith(github.head_ref, 'renovate/') != true
54+
uses: ./.github/workflows/bazel.yml
55+
with:
56+
name: Retry failed tests
57+
caching: false
58+
ruby-version: jruby-9.4.12.0
59+
download-name: bazel-logs
60+
download-path: bazel-logs
61+
upload-name: remote-local-logs
62+
upload-path: bazel-logs
63+
run: |
64+
./go retry_failed_tests "${BAZEL_LOG_FILE}" false

Rakefile

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -249,54 +249,68 @@ task test_py: [:py_prep_for_install_release, 'py:marionette_test']
249249
task build: %i[all firefox remote selenium tests]
250250

251251
desc 'Run on RBE'
252-
task :run_remote do |_task, arguments|
252+
task :run_remote [:target] do |_task, arguments|
253+
original_ruby_version = File.read('rb/.ruby-version').strip
253254
File.write('rb/.ruby-version', 'jruby-9.4.12.0')
254255

255256
Bazel.verbose = true
256-
log_file = 'bazel_20250314_110017.log'
257-
# log_file = "bazel_#{Time.now.strftime('%Y%m%d_%H%M%S')}.log"
257+
log_file = "bazel_#{Time.now.strftime('%Y%m%d_%H%M%S')}.log"
258258
Bazel.log_file = log_file
259259

260-
args = arguments.to_a.compact
261-
args.shift
262-
target = args.shift
263-
remote_args = ['--config=remote']
260+
target = arguments[:target]
261+
remote_args = arguments.extras + ['--config=remote']
264262

265263
has_filters = args.any? { |arg| arg.start_with?('--test_tag_filters=') }
266264
remote_args += args.map { |arg| arg.start_with?('--test_tag_filters=') ? "#{arg},-skip-remote,-remote" : arg }
267265
remote_args << '--test_tag_filters=-skip-remote,-remote' unless has_filters
268266

269267
begin
270-
# Toggle which line here is commented out for using existing logs or not
271-
# Bazel.execute(command, remote_args, target)
272-
raise 'Error to run previous failures'
273-
rescue StandardError => e
274-
failing_tests = []
275-
276-
File.readlines(log_file).reverse_each do |line|
277-
if line.match?(%r{//.+:.*FAILED})
278-
failing_tests << line.strip.split(' ')[0]
279-
elsif !failing_tests.empty? && line.match?(%r{//.+:.*PASSED})
280-
break
281-
else
282-
next
283-
end
268+
Bazel.execute(command, remote_args, target)
269+
rescue StandardError => _e
270+
Rake::Task['retry_failed_tests'].invoke(log_file, true)
271+
ensure
272+
File.write('rb/.ruby-version', original_ruby_version)
273+
end
274+
end
275+
276+
desc 'Retry failed tests from a log file'
277+
task :retry_failed_tests, [:log_file, :remote] do |_task, arguments|
278+
log_file = arguments[:log_file]
279+
raise 'No log file specified' unless log_file
280+
raise 'Log file does not exist' unless File.exist?(log_file)
281+
remote = arguments[:remote]
282+
Bazel.verbose = true
283+
284+
failing_tests = []
285+
286+
File.readlines(log_file).reverse_each do |line|
287+
if line.match?(%r{//.+:.*FAILED})
288+
failing_tests << line.strip.split(' ')[0]
289+
elsif !failing_tests.empty? && line.match?(%r{//.+:.*PASSED})
290+
break
284291
end
292+
end
285293

286-
puts "Found #{failing_tests.size} failing tests; Retrying"
294+
puts "Found #{failing_tests.size} failing tests; Retrying"
287295

288-
retry_args = %w[--test_output=streamed --test_env DEBUG=true]
289-
# retry_args += remote_args
296+
retry_args = arguments.extras + %w[--test_output=streamed --test_env DEBUG=true]
297+
retry_args << '--config=remote' if remote
290298

291-
failing_tests.each do |failed_target|
292-
target_name = failed_target.split('/').last.tr(':', '_')
293-
retry_logs = log_file.sub('.log', "#{target_name}_local_retry.log")
294-
Bazel.log_file = retry_logs
299+
retry_failures = false
300+
failing_tests.each do |failed_target|
301+
target_name = failed_target.split('/').last.tr(':', '_')
302+
target_name += remote ? '_remote' : '_local'
303+
retry_logs = log_file.sub('.log', "#{target_name}_retry.log")
304+
Bazel.log_file = retry_logs
305+
begin
295306
Bazel.execute('test', retry_args, failed_target)
296307
rescue StandardError => e
297-
puts "Failed retry of #{target}: #{e.message}"
308+
retry_failures = true
309+
puts "Failed retry of #{failed_target}: #{e.message}"
298310
end
299311
end
312+
313+
raise 'Some tests failed during retry' if retry_failures
300314
end
301315

302316
desc 'Clean build artifacts.'
@@ -342,7 +356,7 @@ task javadocs: %i[//java/src/org/openqa/selenium/grid:all-javadocs] do
342356
}
343357
344358
STYLE
345-
)
359+
)
346360
end
347361
end
348362

@@ -1205,7 +1219,7 @@ def updated_version(current, desired = nil, nightly = nil)
12051219
end
12061220

12071221
def update_gh_pages
1208-
@git.fetch('origin', {ref: 'gh-pages'})
1222+
@git.fetch('origin', { ref: 'gh-pages' })
12091223
@git.checkout('gh-pages', force: true)
12101224

12111225
%w[java rb py dotnet javascript].each do |language|

rake_tasks/bazel.rb

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,73 @@
77
require_relative 'selenium_rake/checks'
88

99
module Bazel
10-
def self.execute(kind, args, target, &block)
11-
verbose = Rake::FileUtilsExt.verbose_flag
10+
class << self
11+
attr_accessor :log_file, :verbose
1212

13-
if target.end_with?(':run')
14-
kind = 'run'
15-
target = target[0, target.length - 4]
13+
def verbose?
14+
defined?(verbose) ? verbose : Rake::FileUtilsExt.verbose_flag
1615
end
1716

18-
cmd = %w[bazel] + [kind, target] + (args || [])
19-
cmd_out = ''
20-
cmd_exit_code = 0
21-
22-
if SeleniumRake::Checks.windows?
23-
cmd += ['2>&1']
24-
cmd_line = cmd.join(' ')
25-
cmd_out = `#{cmd_line}`.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
26-
puts cmd_out if verbose
27-
cmd_exit_code = $CHILD_STATUS
28-
else
29-
Open3.popen2e(*cmd) do |stdin, stdouts, wait|
30-
is_running = true
31-
stdin.close
32-
while is_running
33-
begin
34-
stdouts.wait_readable
35-
line = stdouts.readpartial(512)
17+
def execute(kind, args, target, &block)
18+
if target.end_with?(':run')
19+
kind = 'run'
20+
target = target[0, target.length - 4]
21+
end
22+
23+
cmd = %w[bazel] + [kind, target] + (args || [])
24+
cmd_out = ''
25+
cmd_exit_code = 0
26+
27+
puts "Logging to: #{log_file}" if verbose? && log_file
28+
29+
if SeleniumRake::Checks.windows?
30+
cmd += ['2>&1']
31+
cmd_line = cmd.join(' ')
32+
cmd_out = `#{cmd_line}`.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
33+
puts cmd_out if verbose?
34+
File.write(log_file, cmd_out) if log_file
35+
cmd_exit_code = $CHILD_STATUS
36+
else
37+
puts "Executing:\n#{cmd.join(' ')}" if verbose?
38+
Open3.popen2e(*cmd) do |stdin, stdouts, wait|
39+
stdin.close
40+
log = log_file ? File.open(log_file, 'a') : nil
41+
42+
process_output(stdouts) do |line|
3643
cmd_out += line
37-
$stdout.print line if verbose
38-
rescue EOFError
39-
is_running = false
44+
$stdout.print line if verbose?
45+
log&.write(line)
46+
log&.flush
4047
end
48+
49+
log&.close
50+
cmd_exit_code = wait.value.exitstatus
4151
end
42-
cmd_exit_code = wait.value.exitstatus
4352
end
44-
end
4553

46-
raise "#{cmd.join(' ')} failed with exit code: #{cmd_exit_code}\nOutput: #{cmd_out}" if cmd_exit_code != 0
54+
raise "#{cmd.join(' ')} failed with exit code: #{cmd_exit_code}\nOutput: #{cmd_out}" if cmd_exit_code != 0
4755

48-
block&.call(cmd_out)
49-
return unless cmd_out =~ %r{\s+(bazel-bin/\S+)}
56+
block&.call(cmd_out)
57+
return unless cmd_out =~ %r{\s+(bazel-bin/\S+)}
5058

51-
out_artifact = Regexp.last_match(1)
52-
puts "#{target} -> #{out_artifact}" if out_artifact
53-
out_artifact
59+
out_artifact = Regexp.last_match(1)
60+
puts "#{target} -> #{out_artifact}" if out_artifact
61+
out_artifact
62+
end
63+
64+
private
65+
66+
def process_output(stdouts)
67+
is_running = true
68+
while is_running
69+
begin
70+
stdouts.wait_readable
71+
line = stdouts.readpartial(512)
72+
yield line
73+
rescue EOFError
74+
is_running = false
75+
end
76+
end
77+
end
5478
end
5579
end

scripts/github-actions/ci-build.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ set -eufo pipefail
44
# We want to see what's going on
55
set -x
66

7+
# Create the log directory if it doesn't exist
8+
LOG_DIR=$(dirname "$BAZEL_LOG_FILE")
9+
mkdir -p "$LOG_DIR"
10+
711
# Now run the tests. The engflow build uses pinned browsers
812
# so this should be fine
913
# shellcheck disable=SC2046
1014
bazel test --config=remote-ci --build_tests_only \
1115
--keep_going --flaky_test_attempts=2 \
12-
//... -- $(cat .skipped-tests | tr '\n' ' ')
16+
//... -- $(cat .skipped-tests | tr '\n' ' ') 2>&1 | tee "$BAZEL_LOG_FILE"
1317

1418
# Build the packages we want to ship to users
1519
bazel build --config=remote-ci --build_tag_filters=release-artifact //...

0 commit comments

Comments
 (0)