From 850a1b146b64ea29aa5ea3e9ebf5baf14913f515 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Wed, 21 Jan 2026 17:02:04 -0600 Subject: [PATCH 01/17] implement fast bazel target lookup --- .github/workflows/bazel.yml | 12 ++ .github/workflows/ci.yml | 112 ++++++++------ rake_tasks/bazel.rake | 139 +++++++++++++++++- scripts/github-actions/check-bazel-targets.sh | 108 -------------- 4 files changed, 219 insertions(+), 152 deletions(-) delete mode 100755 scripts/github-actions/check-bazel-targets.sh diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index e81a6161e8c92..b3975bb2e4a65 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -71,6 +71,11 @@ on: required: false type: number default: 1 + cache-name: + description: Name for cache restore (restores {name}.gz with key {name}-) + required: false + type: string + default: '' jobs: bazel: @@ -100,6 +105,13 @@ jobs: run: git pull origin "$GIT_REF" env: GIT_REF: ${{ github.ref }} + - name: Restore cache + if: inputs.cache-name != '' + uses: actions/cache/restore@v4 + with: + path: ${{ inputs.cache-name }}.gz + key: ${{ inputs.cache-name }}- + restore-keys: ${{ inputs.cache-name }}- - name: Free space if: inputs.os != 'windows' run: ./scripts/github-actions/free-disk-space.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12b316a36c447..2fac1be26880c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,22 +26,40 @@ jobs: check: name: Check Targets if: > + github.event_name != 'schedule' && github.event.repository.fork == false && (startsWith(github.head_ref, 'renovate/') != true || github.event_name == 'workflow_call') uses: ./.github/workflows/bazel.yml with: name: Check Targets - run: COMMIT_RANGE="${{ github.event.pull_request.base.sha || github.event.before }}...${{ github.event.pull_request.head.sha || github.sha }}" ./scripts/github-actions/check-bazel-targets.sh + cache-name: bazel-test-target-index fetch-depth: 50 + run: | + if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then + echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt + else + if [ -f bazel-test-target-index.gz ]; then + mkdir -p build + gunzip -c bazel-test-target-index.gz > build/bazel-test-target-index.json + echo "Restored cached index" + fi + ./go bazel:affected_targets "${{ github.event.pull_request.base.sha || github.event.before }}..HEAD" + fi artifact-name: check-targets artifact-path: bazel-targets.txt read-targets: name: Read Targets + if: ${{ !cancelled() && needs.check.result == 'success' }} needs: check runs-on: ubuntu-latest outputs: targets: ${{ steps.read.outputs.targets }} + java: ${{ steps.read.outputs.java }} + py: ${{ steps.read.outputs.py }} + rb: ${{ steps.read.outputs.rb }} + dotnet: ${{ steps.read.outputs.dotnet }} + rust: ${{ steps.read.outputs.rust }} steps: - name: Download targets uses: actions/download-artifact@v4 @@ -50,63 +68,73 @@ jobs: - name: Read targets id: read run: | - if [ -s bazel-targets.txt ]; then - { - echo "targets<> "$GITHUB_OUTPUT" - else - echo "targets=" >> "$GITHUB_OUTPUT" - fi - + targets=$(cat bazel-targets.txt 2>/dev/null || echo "") + check_binding() { + local pattern=$1 tag=$2 + if [[ "$targets" == *"$pattern"* ]] || [[ "$COMMIT_MESSAGES" == *"[$tag]"* ]] || [[ "$PR_TITLE" == *"[$tag]"* ]]; then + echo "$tag=true" >> "$GITHUB_OUTPUT" + fi + } + check_binding "//java/" "java" + check_binding "//py/" "py" + check_binding "//rb/" "rb" + check_binding "//dotnet/" "dotnet" + check_binding "//rust/" "rust" dotnet: name: .NET needs: read-targets uses: ./.github/workflows/ci-dotnet.yml if: > - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//dotnet') || - contains(join(github.event.commits.*.message), '[dotnet]') || - contains(github.event.pull_request.title, '[dotnet]') + !cancelled() && ( + github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || + contains(needs.read-targets.outputs.targets, '//dotnet') || + contains(join(github.event.commits.*.message), '[dotnet]') || + contains(github.event.pull_request.title, '[dotnet]') + ) java: name: Java needs: read-targets uses: ./.github/workflows/ci-java.yml if: > - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//java') || - contains(join(github.event.commits.*.message), '[java]') || - contains(github.event.pull_request.title, '[java]') + !cancelled() && ( + github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || + contains(needs.read-targets.outputs.targets, '//java') || + contains(join(github.event.commits.*.message), '[java]') || + contains(github.event.pull_request.title, '[java]') + ) python: name: Python needs: read-targets uses: ./.github/workflows/ci-python.yml if: > - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//py') || - contains(join(github.event.commits.*.message), '[py]') || - contains(github.event.pull_request.title, '[py]') + !cancelled() && ( + github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || + contains(needs.read-targets.outputs.targets, '//py') || + contains(join(github.event.commits.*.message), '[py]') || + contains(github.event.pull_request.title, '[py]') + ) ruby: name: Ruby needs: read-targets uses: ./.github/workflows/ci-ruby.yml if: > - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//rb') || - contains(join(github.event.commits.*.message), '[rb]') || - contains(github.event.pull_request.title, '[rb]') + !cancelled() && ( + github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || + contains(needs.read-targets.outputs.targets, '//rb') || + contains(join(github.event.commits.*.message), '[rb]') || + contains(github.event.pull_request.title, '[rb]') + ) rust: name: Rust @@ -115,9 +143,11 @@ jobs: secrets: SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} if: > - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//rust') || - contains(join(github.event.commits.*.message), '[rust]') || - contains(github.event.pull_request.title, '[rust]') + !cancelled() && ( + github.event_name == 'schedule' || + github.event_name == 'workflow_dispatch' || + github.event_name == 'workflow_call' || + contains(needs.read-targets.outputs.targets, '//rust') || + contains(join(github.event.commits.*.message), '[rust]') || + contains(github.event.pull_request.title, '[rust]') + ) diff --git a/rake_tasks/bazel.rake b/rake_tasks/bazel.rake index 6844ee856eb8e..d49b87d3cb674 100644 --- a/rake_tasks/bazel.rake +++ b/rake_tasks/bazel.rake @@ -1,12 +1,52 @@ # frozen_string_literal: true require 'json' +require 'set' -# ./go bazel:build_test_index --> 'build/bazel-test-target-index.json' -# ./go bazel:build_test_index index.json --> 'index.json' +# ./go bazel:affected_targets --> HEAD^..HEAD with default index +# ./go bazel:affected_targets abc123..def456 --> explicit range +# ./go bazel:affected_targets abc123..def456 my-index --> explicit range with custom index +# ./go bazel:affected_targets my-index --> HEAD^..HEAD with custom index +desc 'Find test targets affected by changes between revisions' +task :affected_targets do |_task, args| + values = args.to_a + index_file = values.find { |value| File.exist?(value) } + range = (values - [index_file]).first || 'HEAD' + index_file ||= 'build/bazel-test-target-index' + + base_rev, head_rev = if range.include?('..') + range.split('..', 2) + else + ["#{range}^", range] + end + + puts "Commit range: #{base_rev}..#{head_rev}" + + changed_files = `git diff --name-only #{base_rev} #{head_rev}`.split("\n").map(&:strip).reject(&:empty?) + puts "Changed files: #{changed_files.size}" + + targets = if File.exist?(index_file) + affected_targets_with_index(changed_files, index_file) + else + puts 'No index found, using directory-based fallback' + affected_targets_fallback(changed_files) + end + + if targets.empty? + puts 'No test targets affected' + File.write('bazel-targets.txt', '') + else + puts "Found #{targets.size} affected test targets" + File.write('bazel-targets.txt', targets.sort.join(' ')) + targets.sort.each { |t| puts t } + end +end + +# ./go bazel:build_test_index --> 'build/bazel-test-target-index' +# ./go bazel:build_test_index my-index --> 'my-index' desc 'Build test target index for faster affected target lookup' task :build_test_index, [:index_file] do |_task, args| - output = args[:index_file] || 'build/bazel-test-target-index.json' + output = args[:index_file] || 'build/bazel-test-target-index' index = {} tests = [] @@ -53,3 +93,96 @@ def bazel_label_to_package(label) label = label.sub(%r{^@selenium//}, '').sub(%r{^//}, '') label.split(':').first end + +def find_bazel_package(filepath) + path = File.dirname(filepath) + until path.empty? + return path if File.exist?(File.join(path, 'BUILD.bazel')) || File.exist?(File.join(path, 'BUILD')) + return nil if path == '.' + + path = File.dirname(path) + end + nil +end + +def affected_targets_with_index(changed_files, index_file) + puts "Using index: #{index_file}" + begin + index = JSON.parse(File.read(index_file)) + rescue JSON::ParserError => e + puts "Invalid JSON in index file: #{e.message}" + return affected_targets_fallback(changed_files) + end + + test_files, lib_files = changed_files.partition { |f| f.match?(%r{[_-]test\.rb$|_test\.py$|Test\.java$|Tests?\.cs$|\.test\.[jt]s$|_spec\.rb$}) } + + affected = Set.new + affected.merge(targets_from_tests(test_files)) + + lib_files.each do |filepath| + pkg = find_bazel_package(filepath) + affected.merge(targets_from_lookup(pkg, index, filepath)) + end + + affected.to_a +end + +def targets_from_lookup(pkg, index, filepath) + # ignore files not associated with bazel package + return [] if pkg.nil? + + # Root package is empty string, not '.' + pkg = '' if pkg == '.' + + # generate targets if package not in the index + test_targets = index[pkg] || query_package_dep(pkg) + + # dotnet tests depend on java server, but there are no remote tests, so safe to ignore + filepath.start_with?('java/') ? test_targets.reject { |t| t.start_with?('//dotnet/') } : test_targets +end + +def query_package_dep(pkg) + # Root package is empty string, not '.' + pkg = '' if pkg == '.' + puts "Package not in index, querying deps: //#{pkg}" + targets = [] + Bazel.execute('query', ['--output=label'], "kind('.*_test', deps(//#{pkg}:all))") do |out| + targets = out.lines.map(&:strip).select { |l| l.start_with?('//') } + end + targets +end + +def targets_from_tests(test_files) + test_files.select! { |f| File.exist?(f) } + return [] if test_files.empty? + + query = test_files.filter_map { |f| + pkg = find_bazel_package(f) + next if pkg.nil? + + # Bazel srcs often use paths relative to the package, not basenames. + rel = f.sub(%r{^#{Regexp.escape(pkg)}/}, '') + "attr(srcs, '#{rel}', //#{pkg}:*)" + }.join(' + ') + + return [] if query.empty? + + targets = [] + Bazel.execute('query', ['--output=label'], "kind('.*_test', #{query})") do |out| + targets = out.lines.map(&:strip).select { |l| l.start_with?('//') } + end + targets +end + +def affected_targets_fallback(changed_files) + targets = Set.new + top_level_dirs = changed_files.map { |f| f.split('/').first }.uniq + + return BINDING_TARGETS.values if top_level_dirs.intersect?(%w[common rust]) + + top_level_dirs.each do |dir| + targets << BINDING_TARGETS[dir] if BINDING_TARGETS[dir] + end + + targets.to_a +end diff --git a/scripts/github-actions/check-bazel-targets.sh b/scripts/github-actions/check-bazel-targets.sh deleted file mode 100755 index a68188002febe..0000000000000 --- a/scripts/github-actions/check-bazel-targets.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env bash -# Determines which test targets are affected by changed files - -set -euo pipefail - -COMMIT_RANGE=${COMMIT_RANGE:-"HEAD^..HEAD"} -echo "Commit range: ${COMMIT_RANGE}" - -cd "$(git rev-parse --show-toplevel)" - -affected_files=$(git diff --name-only "${COMMIT_RANGE}") -file_count=$(echo "${affected_files}" | wc -l | tr -d ' ') -echo "Changed files: ${file_count}" -if [[ -z "${affected_files}" ]]; then - echo "" > bazel-targets.txt - exit 0 -fi - -# Convert file paths to bazel labels -echo "Finding bazel labels for changed files..." -labels=() -for file in $affected_files; do - [[ -f "$file" ]] || continue - - dir=$(dirname "$file") - filename=$(basename "$file") - - while [[ "$dir" != "." && ! -f "$dir/BUILD.bazel" && ! -f "$dir/BUILD" ]]; do - filename="$(basename "$dir")/$filename" - dir=$(dirname "$dir") - done - - if [[ -f "$dir/BUILD.bazel" || -f "$dir/BUILD" ]]; then - labels+=("//${dir}:${filename}") - fi -done - -echo "Bazel labels: ${#labels[@]}" -if (( ${#labels[@]} == 0 )); then - echo "" > bazel-targets.txt - exit 0 -fi - -# Query all labels at once -source_targets=$(bazel query --keep_going --noshow_progress "set(${labels[*]})" 2>/dev/null || true) -target_count=$(echo "${source_targets}" | wc -l | tr -d ' ') -echo "Source targets: ${target_count}" -if [[ -z "${source_targets}" ]]; then - echo "" > bazel-targets.txt - exit 0 -fi - -# Query each binding and accumulate results -test_targets="" - -# Hack for Python since it takes CI 5 minutes to run rdeps for some reason only to always return all //py test targets -py_changed=false -for file in $affected_files; do - if [[ "$file" == py/* ]]; then - py_changed=true - break - fi -done - -if [[ "$py_changed" == true ]]; then - echo "Python files changed, adding all Python tests targets..." - result=$(bazel query --keep_going --noshow_progress \ - "kind(test, //py/...) except attr('tags','manual', //py/...) except attr('tags','lint', //py/...)" 2>/dev/null || true) - if [[ -n "$result" ]]; then - count=$(echo "$result" | wc -l | tr -d ' ') - echo "Finished //py/...: ${count} targets" - test_targets="$result" - else - echo "Finished //py/...: 0 targets" - fi -fi - -bindings=("//java/..." "//rb/..." "//dotnet/..." "//javascript/selenium-webdriver/...") - -for binding in "${bindings[@]}"; do - echo "Starting query for ${binding}..." - result=$(bazel query --keep_going --noshow_progress \ - "kind(test, rdeps(set(${binding}), set(${source_targets}))) \ - except attr('tags','manual', set(${binding})) \ - except attr('tags','lint', set(${binding}))" 2>/dev/null || true) - if [[ -n "$result" ]]; then - count=$(echo "$result" | wc -l | tr -d ' ') - echo "Finished ${binding}: ${count} targets" - test_targets="${test_targets}"$'\n'"${result}" - else - echo "Finished ${binding}: 0 targets" - fi -done - -echo "All queries complete" - -test_targets=$(echo "${test_targets}" | xargs -n1 | sort -u | xargs) - -if [[ -z "${test_targets}" ]]; then - echo "No test targets found for the changed files." - echo "" > bazel-targets.txt - exit 0 -fi - -echo "Found test targets:" -echo "${test_targets}" | xargs -n1 - -echo "${test_targets}" > bazel-targets.txt From 96a360804c794a84db9445a65eff1c1f79ef3fb7 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Wed, 21 Jan 2026 17:47:06 -0600 Subject: [PATCH 02/17] fix the conditional logic --- .github/workflows/ci.yml | 56 ++++++---------------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fac1be26880c..d17d825908174 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,6 @@ jobs: check: name: Check Targets if: > - github.event_name != 'schedule' && github.event.repository.fork == false && (startsWith(github.head_ref, 'renovate/') != true || github.event_name == 'workflow_call') uses: ./.github/workflows/bazel.yml @@ -50,11 +49,9 @@ jobs: read-targets: name: Read Targets - if: ${{ !cancelled() && needs.check.result == 'success' }} needs: check runs-on: ubuntu-latest outputs: - targets: ${{ steps.read.outputs.targets }} java: ${{ steps.read.outputs.java }} py: ${{ steps.read.outputs.py }} rb: ${{ steps.read.outputs.rb }} @@ -67,6 +64,9 @@ jobs: name: check-targets - name: Read targets id: read + env: + COMMIT_MESSAGES: ${{ join(github.event.commits.*.message, ' ') }} + PR_TITLE: ${{ github.event.pull_request.title }} run: | targets=$(cat bazel-targets.txt 2>/dev/null || echo "") check_binding() { @@ -84,57 +84,25 @@ jobs: name: .NET needs: read-targets uses: ./.github/workflows/ci-dotnet.yml - if: > - !cancelled() && ( - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//dotnet') || - contains(join(github.event.commits.*.message), '[dotnet]') || - contains(github.event.pull_request.title, '[dotnet]') - ) + if: needs.read-targets.outputs.dotnet != '' java: name: Java needs: read-targets uses: ./.github/workflows/ci-java.yml - if: > - !cancelled() && ( - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//java') || - contains(join(github.event.commits.*.message), '[java]') || - contains(github.event.pull_request.title, '[java]') - ) + if: needs.read-targets.outputs.java != '' python: name: Python needs: read-targets uses: ./.github/workflows/ci-python.yml - if: > - !cancelled() && ( - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//py') || - contains(join(github.event.commits.*.message), '[py]') || - contains(github.event.pull_request.title, '[py]') - ) + if: needs.read-targets.outputs.py != '' ruby: name: Ruby needs: read-targets uses: ./.github/workflows/ci-ruby.yml - if: > - !cancelled() && ( - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//rb') || - contains(join(github.event.commits.*.message), '[rb]') || - contains(github.event.pull_request.title, '[rb]') - ) + if: needs.read-targets.outputs.rb != '' rust: name: Rust @@ -142,12 +110,4 @@ jobs: uses: ./.github/workflows/ci-rust.yml secrets: SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }} - if: > - !cancelled() && ( - github.event_name == 'schedule' || - github.event_name == 'workflow_dispatch' || - github.event_name == 'workflow_call' || - contains(needs.read-targets.outputs.targets, '//rust') || - contains(join(github.event.commits.*.message), '[rust]') || - contains(github.event.pull_request.title, '[rust]') - ) + if: needs.read-targets.outputs.rust != '' From 26294d562e0d0812749c6365053945af2c05eb95 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Thu, 22 Jan 2026 19:42:59 -0600 Subject: [PATCH 03/17] run build-index on manual workflow dispatch --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d17d825908174..384ec74cb8640 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ permissions: jobs: build-index: name: Build Index - if: github.event_name == 'schedule' + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' uses: ./.github/workflows/ci-build-index.yml check: From 8d7fcca53d032ea9d1cae25bef54acd85d9ab81e Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Thu, 22 Jan 2026 21:50:06 -0600 Subject: [PATCH 04/17] add comment when check target script is skipped --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 384ec74cb8640..75c7ce45632e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,7 @@ jobs: fetch-depth: 50 run: | if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then + echo "Running all targets for ${{ github.event_name }} event" echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt else if [ -f bazel-test-target-index.gz ]; then From 1bae1e882aa5117ac532e32ae85f2aa38cd3b4ac Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Thu, 22 Jan 2026 21:53:15 -0600 Subject: [PATCH 05/17] remove indexing when manual executed --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 75c7ce45632e2..58f2caa5f8b80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: cache-name: bazel-test-target-index fetch-depth: 50 run: | - if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then + if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then echo "Running all targets for ${{ github.event_name }} event" echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt else From a35251dc6d6711ed5c8d4b91fe6ab1b1ce4c2199 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 09:02:40 -0600 Subject: [PATCH 06/17] WIP - just build index again --- .github/workflows/bazel.yml | 2 +- .github/workflows/ci-build-index.yml | 2 ++ .github/workflows/ci.yml | 9 ++------- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index b3975bb2e4a65..2bb2af8d15dfa 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -109,7 +109,7 @@ jobs: if: inputs.cache-name != '' uses: actions/cache/restore@v4 with: - path: ${{ inputs.cache-name }}.gz + path: ${{ inputs.cache-name }} key: ${{ inputs.cache-name }}- restore-keys: ${{ inputs.cache-name }}- - name: Free space diff --git a/.github/workflows/ci-build-index.yml b/.github/workflows/ci-build-index.yml index 092aa0b0c0e29..d246df4f15b9d 100644 --- a/.github/workflows/ci-build-index.yml +++ b/.github/workflows/ci-build-index.yml @@ -26,6 +26,8 @@ jobs: uses: actions/download-artifact@v4 with: name: bazel-test-target-index + - name: Debug - list files + run: ls -la && file bazel-test-target-index* - name: Cache index uses: actions/cache/save@v4 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58f2caa5f8b80..060a5123d6153 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,16 +34,11 @@ jobs: cache-name: bazel-test-target-index fetch-depth: 50 run: | - if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then + if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then echo "Running all targets for ${{ github.event_name }} event" echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt else - if [ -f bazel-test-target-index.gz ]; then - mkdir -p build - gunzip -c bazel-test-target-index.gz > build/bazel-test-target-index.json - echo "Restored cached index" - fi - ./go bazel:affected_targets "${{ github.event.pull_request.base.sha || github.event.before }}..HEAD" + ./go bazel:affected_targets "${{ github.event.pull_request.base.sha || github.event.before }}..HEAD" bazel-test-target-index fi artifact-name: check-targets artifact-path: bazel-targets.txt From a757f3350b0fb52882aaa4953b9474b0d0dcd777 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 10:18:11 -0600 Subject: [PATCH 07/17] WIP - now try to use the indexed file with workflow dispatch instead of building it --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 060a5123d6153..8fde065fcf376 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ permissions: jobs: build-index: name: Build Index - if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + if: github.event_name == 'schedule' uses: ./.github/workflows/ci-build-index.yml check: @@ -34,7 +34,7 @@ jobs: cache-name: bazel-test-target-index fetch-depth: 50 run: | - if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then + if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then echo "Running all targets for ${{ github.event_name }} event" echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt else From f6e8f7a94c7c37fc8ab39120dae0be9199769273 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 11:11:26 -0600 Subject: [PATCH 08/17] test: trigger remote tests from index --- java/src/org/openqa/selenium/remote/RemoteWebDriver.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java index c7e9a3559322b..a3e6b28af1029 100644 --- a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java +++ b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java @@ -114,6 +114,7 @@ public class RemoteWebDriver Interactive, PrintsPage, TakesScreenshot { + // Test change to trigger remote tests from index static { org.openqa.selenium.internal.Debug.configureLogger(); From 714d44c389587cb33c188ffcba38699b242e49e9 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 11:36:43 -0600 Subject: [PATCH 09/17] detect index file by existence in affected_targets args --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8fde065fcf376..1009bd4c1f6d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,12 @@ jobs: echo "Running all targets for ${{ github.event_name }} event" echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt else - ./go bazel:affected_targets "${{ github.event.pull_request.base.sha || github.event.before }}..HEAD" bazel-test-target-index + BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before }}" + if [ -n "$BASE_SHA" ]; then + ./go bazel:affected_targets "${BASE_SHA}..HEAD" bazel-test-target-index + else + ./go bazel:affected_targets bazel-test-target-index + fi fi artifact-name: check-targets artifact-path: bazel-targets.txt From 71742deb5d85b6f0d437d8b7eb194319d36266f5 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 11:37:06 -0600 Subject: [PATCH 10/17] revert test comment in RemoteWebDriver --- java/src/org/openqa/selenium/remote/RemoteWebDriver.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java index a3e6b28af1029..c7e9a3559322b 100644 --- a/java/src/org/openqa/selenium/remote/RemoteWebDriver.java +++ b/java/src/org/openqa/selenium/remote/RemoteWebDriver.java @@ -114,7 +114,6 @@ public class RemoteWebDriver Interactive, PrintsPage, TakesScreenshot { - // Test change to trigger remote tests from index static { org.openqa.selenium.internal.Debug.configureLogger(); From b20d1a4ad0bee71da95cdc654095406fb09ec6f2 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 12:01:44 -0600 Subject: [PATCH 11/17] python tests are all on //py: not nested with //py/ --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1009bd4c1f6d0..ca32a640d15d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,7 @@ jobs: fi } check_binding "//java/" "java" - check_binding "//py/" "py" + check_binding "//py:" "py" check_binding "//rb/" "rb" check_binding "//dotnet/" "dotnet" check_binding "//rust/" "rust" From 55925c945f26137321eb930e6fdc775fc20a1bfa Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 12:08:24 -0600 Subject: [PATCH 12/17] test: trigger grid tests from index --- java/src/org/openqa/selenium/grid/Main.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/src/org/openqa/selenium/grid/Main.java b/java/src/org/openqa/selenium/grid/Main.java index 8920af7b5bad0..686411f1cae89 100644 --- a/java/src/org/openqa/selenium/grid/Main.java +++ b/java/src/org/openqa/selenium/grid/Main.java @@ -16,6 +16,7 @@ // under the License. package org.openqa.selenium.grid; +// Test change to verify grid tests are triggered from index import static java.util.Comparator.comparing; From 198538c906759d3ec1406dbbd839ec6437bd5b60 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 20:41:39 -0600 Subject: [PATCH 13/17] build: switch index generation to linux Now that trunk has the fix for macOS-only archive rules, the index can be built on Linux which is faster and cheaper. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci-build-index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-build-index.yml b/.github/workflows/ci-build-index.yml index d246df4f15b9d..72bff2a18ddbf 100644 --- a/.github/workflows/ci-build-index.yml +++ b/.github/workflows/ci-build-index.yml @@ -12,7 +12,7 @@ jobs: uses: ./.github/workflows/bazel.yml with: name: Build Test Index - os: macos + os: linux run: ./go bazel:build_test_index bazel-test-target-index artifact-name: bazel-test-target-index artifact-path: bazel-test-target-index From 22a6404ba84a3ec6db3de9f636ed2e9d5d7ce971 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 20:56:46 -0600 Subject: [PATCH 14/17] workflow dispatch always re-indexes and always runs everything --- .github/workflows/ci-build-index.yml | 2 -- .github/workflows/ci.yml | 6 ++++-- java/src/org/openqa/selenium/grid/Main.java | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-build-index.yml b/.github/workflows/ci-build-index.yml index 72bff2a18ddbf..d6b1c3ebbfe25 100644 --- a/.github/workflows/ci-build-index.yml +++ b/.github/workflows/ci-build-index.yml @@ -26,8 +26,6 @@ jobs: uses: actions/download-artifact@v4 with: name: bazel-test-target-index - - name: Debug - list files - run: ls -la && file bazel-test-target-index* - name: Cache index uses: actions/cache/save@v4 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca32a640d15d4..23dd5fb987477 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ permissions: jobs: build-index: name: Build Index - if: github.event_name == 'schedule' + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' uses: ./.github/workflows/ci-build-index.yml check: @@ -34,7 +34,9 @@ jobs: cache-name: bazel-test-target-index fetch-depth: 50 run: | - if [ "${{ github.event_name }}" == "schedule" ] || [ "${{ github.event_name }}" == "workflow_call" ]; then + if [ "${{ github.event_name }}" == "schedule" ] || \ + [ "${{ github.event_name }}" == "workflow_call" ] || \ + [ "${{ github.event_name }}" == "workflow_dispatch" ]; then echo "Running all targets for ${{ github.event_name }} event" echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt else diff --git a/java/src/org/openqa/selenium/grid/Main.java b/java/src/org/openqa/selenium/grid/Main.java index 686411f1cae89..8920af7b5bad0 100644 --- a/java/src/org/openqa/selenium/grid/Main.java +++ b/java/src/org/openqa/selenium/grid/Main.java @@ -16,7 +16,6 @@ // under the License. package org.openqa.selenium.grid; -// Test change to verify grid tests are triggered from index import static java.util.Comparator.comparing; From a0a3f26dd4114ac17dca53af0eb2702e5087ca50 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 21:05:03 -0600 Subject: [PATCH 15/17] ubuntu not linux --- .github/workflows/ci-build-index.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-build-index.yml b/.github/workflows/ci-build-index.yml index d6b1c3ebbfe25..d023790ffaf23 100644 --- a/.github/workflows/ci-build-index.yml +++ b/.github/workflows/ci-build-index.yml @@ -12,7 +12,7 @@ jobs: uses: ./.github/workflows/bazel.yml with: name: Build Test Index - os: linux + os: ubuntu run: ./go bazel:build_test_index bazel-test-target-index artifact-name: bazel-test-target-index artifact-path: bazel-test-target-index From 13ff451698603c680617ee7a729332cff19364b8 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 21:48:49 -0600 Subject: [PATCH 16/17] python tests from the root --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23dd5fb987477..f5a95a8005def 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: [ "${{ github.event_name }}" == "workflow_call" ] || \ [ "${{ github.event_name }}" == "workflow_dispatch" ]; then echo "Running all targets for ${{ github.event_name }} event" - echo "//java/... //py/... //rb/... //dotnet/... //rust/..." > bazel-targets.txt + echo "//java/... //py:* //rb/... //dotnet/... //rust/..." > bazel-targets.txt else BASE_SHA="${{ github.event.pull_request.base.sha || github.event.before }}" if [ -n "$BASE_SHA" ]; then From aff056811bdb4509b56902fe9e6d145e95395625 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 23 Jan 2026 22:11:51 -0600 Subject: [PATCH 17/17] add explicit permissions to cache job --- .github/workflows/ci-build-index.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-build-index.yml b/.github/workflows/ci-build-index.yml index d023790ffaf23..ef7de04e14179 100644 --- a/.github/workflows/ci-build-index.yml +++ b/.github/workflows/ci-build-index.yml @@ -21,6 +21,7 @@ jobs: name: Cache Index needs: build runs-on: ubuntu-latest + permissions: {} steps: - name: Download index uses: actions/download-artifact@v4