name: Bazel

# Note this workflow was originally derived from:
# https://github.com/cerisier/toolchains_llvm_bootstrapped/blob/main/.github/workflows/ci.yaml

on:
  pull_request: {}
  push:
    branches:
      - main
  workflow_dispatch:

concurrency:
  # Cancel previous actions from the same PR or branch except 'main' branch.
  # See https://docs.github.com/en/actions/using-jobs/using-concurrency and https://docs.github.com/en/actions/learn-github-actions/contexts for more info.
  group: concurrency-group::${{ github.workflow }}::${{ github.event.pull_request.number > 0 && format('pr-{0}', github.event.pull_request.number) || github.ref_name }}${{ github.ref_name == 'main' && format('::{0}', github.run_id) || ''}}
  cancel-in-progress: ${{ github.ref_name != 'main' }}
jobs:
  test:
    timeout-minutes: 60
    strategy:
      fail-fast: false
      matrix:
        include:
          # macOS
          - os: macos-15-xlarge
            target: aarch64-apple-darwin
          - os: macos-15-xlarge
            target: x86_64-apple-darwin

          # Linux
          - os: ubuntu-24.04
            target: x86_64-unknown-linux-gnu
          - os: ubuntu-24.04
            target: x86_64-unknown-linux-musl
          # 2026-02-27 Bazel tests have been flaky on arm in CI.
          # Disable until we can investigate and stabilize them.
          # - os: ubuntu-24.04-arm
          #   target: aarch64-unknown-linux-musl
          # - os: ubuntu-24.04-arm
          #   target: aarch64-unknown-linux-gnu

          # Windows
          - os: windows-latest
            target: x86_64-pc-windows-gnullvm
    runs-on: ${{ matrix.os }}

    # Configure a human readable name for each job
    name: Local Bazel build on ${{ matrix.os }} for ${{ matrix.target }}

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Set up Bazel CI
        id: setup_bazel
        uses: ./.github/actions/setup-bazel-ci
        with:
          target: ${{ matrix.target }}
          install-test-prereqs: "true"

      - name: Check MODULE.bazel.lock is up to date
        if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
        shell: bash
        run: ./scripts/check-module-bazel-lock.sh

      - name: bazel test //...
        env:
          BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
        shell: bash
        run: |
          bazel_targets=(
            //...
            # Keep standalone V8 library targets out of the ordinary Bazel CI
            # path. V8 consumers under `//codex-rs/...` still participate
            # transitively through `//...`.
            -//third_party/v8:all
          )

          ./.github/scripts/run-bazel-ci.sh \
            --print-failed-test-logs \
            --use-node-test-env \
            -- \
            test \
            --test_tag_filters=-argument-comment-lint \
            --test_verbose_timeout_warnings \
            --build_metadata=COMMIT_SHA=${GITHUB_SHA} \
            -- \
            "${bazel_targets[@]}"

      # Save bazel repository cache explicitly; make non-fatal so cache uploading
      # never fails the overall job. Only save when key wasn't hit.
      - name: Save bazel repository cache
        if: always() && !cancelled() && steps.setup_bazel.outputs.cache-hit != 'true'
        continue-on-error: true
        uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
        with:
          path: |
            ~/.cache/bazel-repo-cache
          key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}

  clippy:
    timeout-minutes: 60
    strategy:
      fail-fast: false
      matrix:
        include:
          # Keep Linux lint coverage on x64 and add the arm64 macOS path that
          # the Bazel test job already exercises. Add Windows gnullvm as well
          # so PRs get Bazel-native lint signal on the same Windows toolchain
          # that the Bazel test job uses.
          - os: ubuntu-24.04
            target: x86_64-unknown-linux-gnu
          - os: macos-15-xlarge
            target: aarch64-apple-darwin
          - os: windows-latest
            target: x86_64-pc-windows-gnullvm
    runs-on: ${{ matrix.os }}
    name: Bazel clippy on ${{ matrix.os }} for ${{ matrix.target }}

    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Set up Bazel CI
        id: setup_bazel
        uses: ./.github/actions/setup-bazel-ci
        with:
          target: ${{ matrix.target }}

      - name: bazel build --config=clippy //codex-rs/...
        env:
          BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
        shell: bash
        run: |
          # Keep the initial Bazel clippy scope on codex-rs and out of the
          # V8 proof-of-concept target for now.
          ./.github/scripts/run-bazel-ci.sh \
            -- \
            build \
            --config=clippy \
            --build_metadata=COMMIT_SHA=${GITHUB_SHA} \
            --build_metadata=TAG_job=clippy \
            -- \
            //codex-rs/... \
            -//codex-rs/v8-poc:all

      # Save bazel repository cache explicitly; make non-fatal so cache uploading
      # never fails the overall job. Only save when key wasn't hit.
      - name: Save bazel repository cache
        if: always() && !cancelled() && steps.setup_bazel.outputs.cache-hit != 'true'
        continue-on-error: true
        uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
        with:
          path: |
            ~/.cache/bazel-repo-cache
          key: bazel-cache-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }}
