mirror of
https://github.com/openai/codex.git
synced 2026-05-01 01:47:18 +00:00
## Why
The Bazel workflow has multiple jobs that run concurrently for the same
target triple. In particular, the Windows `test`, `clippy`, and
`verify-release-build` jobs could all miss and then attempt to save the
same Bazel repository cache key:
```text
bazel-cache-${target}-${lockhash}
```
Because `actions/cache` entries are immutable, only one job can reserve
that key. The others can report failures such as:
```text
Failed to save: Unable to reserve cache with key bazel-cache-x86_64-pc-windows-gnullvm-..., another job may be creating this cache.
```
Adding only the workflow name would not separate these jobs because they
all run inside the same `Bazel` workflow. The key needs a job-level
namespace as well.
## What Changed
- Added a required `cache-scope` input to
`.github/actions/prepare-bazel-ci/action.yml`.
- Moved Bazel repository cache key construction into the shared action
and exposed the computed key as `repository-cache-key`.
- Exposed the exact restore result as `repository-cache-hit` so save
steps can skip exact cache hits.
- Updated `.github/workflows/bazel.yml` to pass `cache-scope: bazel-${{
github.job }}` for the `test`, `clippy`, and `verify-release-build`
jobs.
- The scoped restore key is now the only fallback. This avoids carrying
a temporary restore path for the old unscoped cache namespace.
## Verification
- Parsed `.github/actions/prepare-bazel-ci/action.yml` and
`.github/workflows/bazel.yml` with Ruby's YAML parser.
- `actionlint` is not installed in this workspace, so I could not run a
GitHub Actions semantic lint locally.
293 lines
11 KiB
YAML
293 lines
11 KiB
YAML
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: 30
|
|
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: Check rusty_v8 MODULE.bazel checksums
|
|
if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu'
|
|
shell: bash
|
|
run: |
|
|
python3 .github/scripts/rusty_v8_bazel.py check-module-bazel
|
|
python3 -m unittest discover -s .github/scripts -p test_rusty_v8_bazel.py
|
|
|
|
- name: Prepare Bazel CI
|
|
id: prepare_bazel
|
|
uses: ./.github/actions/prepare-bazel-ci
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
cache-scope: bazel-${{ github.job }}
|
|
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
|
|
)
|
|
|
|
bazel_wrapper_args=(
|
|
--print-failed-test-logs
|
|
--use-node-test-env
|
|
)
|
|
bazel_test_args=(
|
|
test
|
|
--test_tag_filters=-argument-comment-lint
|
|
--test_verbose_timeout_warnings
|
|
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
|
)
|
|
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
|
bazel_wrapper_args+=(--windows-msvc-host-platform)
|
|
bazel_test_args+=(--jobs=8)
|
|
fi
|
|
|
|
./.github/scripts/run-bazel-ci.sh \
|
|
"${bazel_wrapper_args[@]}" \
|
|
-- \
|
|
"${bazel_test_args[@]}" \
|
|
-- \
|
|
"${bazel_targets[@]}"
|
|
|
|
- name: Upload Bazel execution logs
|
|
if: always() && !cancelled()
|
|
continue-on-error: true
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
|
with:
|
|
name: bazel-execution-logs-test-${{ matrix.target }}
|
|
path: ${{ runner.temp }}/bazel-execution-logs
|
|
if-no-files-found: ignore
|
|
|
|
# Save the job-scoped Bazel repository cache after cache misses. Keep the
|
|
# upload non-fatal so cache service issues never fail the job itself.
|
|
- name: Save bazel repository cache
|
|
if: always() && !cancelled() && steps.prepare_bazel.outputs.repository-cache-hit != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
|
key: ${{ steps.prepare_bazel.outputs.repository-cache-key }}
|
|
|
|
clippy:
|
|
timeout-minutes: 30
|
|
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: Prepare Bazel CI
|
|
id: prepare_bazel
|
|
uses: ./.github/actions/prepare-bazel-ci
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
cache-scope: bazel-${{ github.job }}
|
|
|
|
- name: bazel build --config=clippy lint targets
|
|
env:
|
|
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
|
shell: bash
|
|
run: |
|
|
bazel_clippy_args=(
|
|
--config=clippy
|
|
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
|
--build_metadata=TAG_job=clippy
|
|
)
|
|
bazel_wrapper_args=()
|
|
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
|
# Keep this aligned with the Windows Bazel test job. With the
|
|
# default `//:local_windows` host platform, Windows `rust_test`
|
|
# targets such as `//codex-rs/core:core-all-test` can be skipped
|
|
# by `--skip_incompatible_explicit_targets`, which hides clippy
|
|
# diagnostics from integration-test modules.
|
|
bazel_wrapper_args+=(--windows-msvc-host-platform)
|
|
bazel_clippy_args+=(--skip_incompatible_explicit_targets)
|
|
fi
|
|
|
|
bazel_target_lines="$(./scripts/list-bazel-clippy-targets.sh)"
|
|
bazel_targets=()
|
|
while IFS= read -r target; do
|
|
bazel_targets+=("${target}")
|
|
done <<< "${bazel_target_lines}"
|
|
|
|
./.github/scripts/run-bazel-ci.sh \
|
|
--print-failed-action-summary \
|
|
"${bazel_wrapper_args[@]}" \
|
|
-- \
|
|
build \
|
|
"${bazel_clippy_args[@]}" \
|
|
-- \
|
|
"${bazel_targets[@]}"
|
|
|
|
- name: Upload Bazel execution logs
|
|
if: always() && !cancelled()
|
|
continue-on-error: true
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
|
with:
|
|
name: bazel-execution-logs-clippy-${{ matrix.target }}
|
|
path: ${{ runner.temp }}/bazel-execution-logs
|
|
if-no-files-found: ignore
|
|
|
|
# Save the job-scoped Bazel repository cache after cache misses. Keep the
|
|
# upload non-fatal so cache service issues never fail the job itself.
|
|
- name: Save bazel repository cache
|
|
if: always() && !cancelled() && steps.prepare_bazel.outputs.repository-cache-hit != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
|
key: ${{ steps.prepare_bazel.outputs.repository-cache-key }}
|
|
|
|
verify-release-build:
|
|
timeout-minutes: 30
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- 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: Verify release build on ${{ matrix.os }} for ${{ matrix.target }}
|
|
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
|
|
- name: Prepare Bazel CI
|
|
id: prepare_bazel
|
|
uses: ./.github/actions/prepare-bazel-ci
|
|
with:
|
|
target: ${{ matrix.target }}
|
|
cache-scope: bazel-${{ github.job }}
|
|
|
|
- name: bazel build verify-release-build targets
|
|
env:
|
|
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
|
|
shell: bash
|
|
run: |
|
|
# This job exists to compile Rust code behind
|
|
# `cfg(not(debug_assertions))` so PR CI catches failures that would
|
|
# otherwise show up only in a release build. We do not need the full
|
|
# optimizer and debug-info work that normally comes with a release
|
|
# build to get that signal, so keep Bazel in `fastbuild` and disable
|
|
# Rust debug assertions explicitly.
|
|
bazel_wrapper_args=()
|
|
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
|
bazel_wrapper_args+=(--windows-msvc-host-platform)
|
|
fi
|
|
|
|
bazel_build_args=(
|
|
--compilation_mode=fastbuild
|
|
--@rules_rust//rust/settings:extra_rustc_flag=-Cdebug-assertions=no
|
|
--@rules_rust//rust/settings:extra_exec_rustc_flag=-Cdebug-assertions=no
|
|
--build_metadata=COMMIT_SHA=${GITHUB_SHA}
|
|
--build_metadata=TAG_job=verify-release-build
|
|
--build_metadata=TAG_rust_debug_assertions=off
|
|
)
|
|
|
|
bazel_target_lines="$(bash ./scripts/list-bazel-release-targets.sh)"
|
|
bazel_targets=()
|
|
while IFS= read -r target; do
|
|
bazel_targets+=("${target}")
|
|
done <<< "${bazel_target_lines}"
|
|
|
|
./.github/scripts/run-bazel-ci.sh \
|
|
"${bazel_wrapper_args[@]}" \
|
|
-- \
|
|
build \
|
|
"${bazel_build_args[@]}" \
|
|
-- \
|
|
"${bazel_targets[@]}"
|
|
|
|
- name: Upload Bazel execution logs
|
|
if: always() && !cancelled()
|
|
continue-on-error: true
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
|
with:
|
|
name: bazel-execution-logs-verify-release-build-${{ matrix.target }}
|
|
path: ${{ runner.temp }}/bazel-execution-logs
|
|
if-no-files-found: ignore
|
|
|
|
# Save the job-scoped Bazel repository cache after cache misses. Keep the
|
|
# upload non-fatal so cache service issues never fail the job itself.
|
|
- name: Save bazel repository cache
|
|
if: always() && !cancelled() && steps.prepare_bazel.outputs.repository-cache-hit != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: ${{ steps.prepare_bazel.outputs.repository-cache-path }}
|
|
key: ${{ steps.prepare_bazel.outputs.repository-cache-key }}
|