name: CI

on:
  pull_request:
    paths-ignore:
      - 'docs/decisions/**'
  push:
    branches:
      - trunk
  schedule:
    - cron: "0 */12 * * *"
  workflow_dispatch:
  workflow_call:

concurrency:
  group: ci-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  build-index:
    name: Build Index
    if: (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/trunk'
    uses: ./.github/workflows/ci-build-index.yml

  check:
    name: Check Targets
    if: >
      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
      cache-name: bazel-test-file-index
      run: |
        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
          if [ -n "${{ github.event.pull_request.base.sha }}" ]; then
            BASE_SHA="HEAD^1"
          elif [ "${{ github.ref }}" = "refs/heads/trunk" ]; then
            BASE_SHA="${{ github.event.before }}"
          else
            ahead=$(gh api "repos/${{ github.repository }}/compare/trunk...${{ github.ref_name }}" --jq .ahead_by)
            git fetch --no-tags --depth=$((ahead + 1)) origin "${{ github.ref_name }}"
            BASE_SHA="HEAD~$ahead"
          fi
          if git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
            ./go bazel:affected_targets "${BASE_SHA}..HEAD" bazel-test-file-index
          else
            ./go bazel:affected_targets bazel-test-file-index
          fi
        fi
      artifact-name: check-targets
      artifact-path: bazel-targets.txt

  read-targets:
    name: Read Targets
    needs: check
    runs-on: ubuntu-latest
    outputs:
      java: ${{ steps.read.outputs.java }}
      grid: ${{ steps.read.outputs.grid }}
      py: ${{ steps.read.outputs.py }}
      rb_targets: ${{ steps.read.outputs.rb_targets }}
      dotnet: ${{ steps.read.outputs.dotnet }}
      rust: ${{ steps.read.outputs.rust }}
    steps:
      - name: Download targets
        uses: actions/download-artifact@v8
        with:
          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() {
            local pattern=$1 tag=$2
            if [[ "$targets" == *"${pattern}/"* ]] || [[ "$targets" == *"${pattern}:"* ]] || [[ "$COMMIT_MESSAGES" == *"[$tag]"* ]] || [[ "$PR_TITLE" == *"[$tag]"* ]]; then
              echo "$tag=true" >> "$GITHUB_OUTPUT"
            fi
          }
          process_binding() {
            local pattern=$1 tag=$2
            local lang_targets
            lang_targets=$(echo "$targets" | tr ' ' '\n' | awk -v p="^${pattern}[:/]" '$0 ~ p' | tr '\n' ' ' | sed 's/ *$//')
            if [ -n "$lang_targets" ]; then
              echo "${tag}_targets=$lang_targets" >> "$GITHUB_OUTPUT"
            fi
          }
          check_binding "//java" "java"
          check_binding "openqa/selenium/grid" "grid"
          check_binding "//py" "py"
          check_binding "//dotnet" "dotnet"
          check_binding "//rust" "rust"
          process_binding "//rb" "rb"
  dotnet:
    name: .NET
    needs: read-targets
    uses: ./.github/workflows/ci-dotnet.yml
    if: needs.read-targets.outputs.dotnet != ''

  java:
    name: Java
    needs: read-targets
    uses: ./.github/workflows/ci-java.yml
    if: needs.read-targets.outputs.java != ''

  grid:
    name: Grid
    needs: read-targets
    uses: ./.github/workflows/ci-grid.yml
    if: needs.read-targets.outputs.grid != ''

  python:
    name: Python
    needs: read-targets
    uses: ./.github/workflows/ci-python.yml
    if: needs.read-targets.outputs.py != ''

  ruby:
    name: Ruby
    needs: read-targets
    uses: ./.github/workflows/ci-ruby.yml
    if: needs.read-targets.outputs.rb_targets != ''
    with:
      targets: ${{ needs.read-targets.outputs.rb_targets }}

  rust:
    name: Rust
    needs: read-targets
    uses: ./.github/workflows/ci-rust.yml
    secrets:
      SELENIUM_CI_TOKEN: ${{ secrets.SELENIUM_CI_TOKEN }}
    if: needs.read-targets.outputs.rust != ''

  ci-success:
    name: CI Success
    if: always()
    needs: [check, read-targets, dotnet, java, grid, python, ruby, rust]
    runs-on: ubuntu-latest
    steps:
      - name: Verify required jobs succeeded
        run: |
          if ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}; then
            echo "One or more required jobs failed"
            exit 1
          fi
