fix: validate configured model reasoning effort #1721
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: | |
| # PRs use the sharded Windows cross-compiled test jobs below. Post-merge | |
| # pushes to main also run the native Windows test job for broader Windows | |
| # signal without putting PR latency back on the critical path. Cargo CI | |
| # owns V8/code-mode test coverage for now. | |
| # Above the heavy Bazel step's 170-min step timeout: an overrun fails the | |
| # STEP, not the JOB, so !cancelled() stays true and Save banks the cache. | |
| timeout-minutes: 185 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # macOS Bazel legs are disabled in keyless Codewith CI because the | |
| # hermetic Apple CLTools SDK archive currently returns HTTP 403 from | |
| # GitHub-hosted macOS runners. Rust CI and release workflows still | |
| # cover macOS builds outside Bazel. | |
| # 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 | |
| runs-on: ${{ matrix.os }} | |
| # Configure a human readable name for each job | |
| name: Bazel test on ${{ matrix.os }} for ${{ matrix.target }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} | |
| persist-credentials: false | |
| - name: Free Linux runner disk for Bazel tests | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| df -h | |
| sudo rm -rf \ | |
| /opt/ghc \ | |
| /opt/hostedtoolcache \ | |
| /usr/local/lib/android \ | |
| /usr/local/share/boost \ | |
| /usr/share/dotnet | |
| docker system prune -af --volumes || true | |
| sudo apt-get clean || true | |
| df -h | |
| - 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: Enable unprivileged user namespaces (Linux) | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| run: | | |
| sudo sysctl -w kernel.unprivileged_userns_clone=1 | |
| if [[ -e /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]]; then | |
| sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 | |
| fi | |
| - name: Verify Windows-cross host tool resolution | |
| if: matrix.os == 'ubuntu-24.04' && matrix.target == 'x86_64-unknown-linux-gnu' | |
| shell: bash | |
| run: python3 .github/scripts/check_windows_bazel_host_tools.py | |
| - 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: Configure keyless Bazel disk cache | |
| id: disk_cache_cfg | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| env: | |
| BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} | |
| run: | | |
| # Keyless (no BuildBuddy) Linux runs use a persisted local disk cache; | |
| # keyed RBE runs do not. Never print the key, only test its presence. | |
| if [[ -z "${BUILDBUDDY_API_KEY:-}" ]]; then | |
| echo "keyless=true" >> "${GITHUB_OUTPUT}" | |
| else | |
| echo "keyless=false" >> "${GITHUB_OUTPUT}" | |
| fi | |
| echo "path=${HOME}/.cache/bazel-disk-cache" >> "${GITHUB_OUTPUT}" | |
| - name: Restore Bazel disk cache (keyless) | |
| id: disk_cache_restore | |
| if: runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' | |
| continue-on-error: true | |
| uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.disk_cache_cfg.outputs.path }} | |
| key: bazel-disk-${{ github.job }}-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }} | |
| restore-keys: | | |
| bazel-disk-${{ github.job }}-${{ matrix.target }}- | |
| - name: bazel test //... | |
| # Bounded below the job timeout-minutes so a cold keyless build that | |
| # overruns fails THIS STEP (a failure) instead of the JOB (a | |
| # cancellation). !cancelled() then stays true and the Prune/Save steps | |
| # below bank the partial disk cache; the job still fails until the | |
| # build finishes within the window (no fake-green). | |
| timeout-minutes: 170 | |
| 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 | |
| # V8-backed code-mode tests are covered by Cargo CI. Bazel CI | |
| # cross-compiles in several legs, and those tests are not stable in | |
| # that setup yet. | |
| -//codex-rs/code-mode:code-mode-unit-tests | |
| -//codex-rs/v8-poc:v8-poc-unit-tests | |
| ) | |
| bazel_wrapper_args=( | |
| --print-failed-action-summary | |
| --print-failed-test-logs | |
| ) | |
| bazel_test_args=( | |
| test | |
| --test_tag_filters=-argument-comment-lint | |
| --test_verbose_timeout_warnings | |
| --build_metadata=COMMIT_SHA=${GITHUB_SHA} | |
| ) | |
| ./.github/scripts/run-bazel-ci.sh \ | |
| "${bazel_wrapper_args[@]}" \ | |
| -- \ | |
| "${bazel_test_args[@]}" \ | |
| -- \ | |
| "${bazel_targets[@]}" | |
| - name: Prune Bazel disk cache (keyless) | |
| if: always() && !cancelled() && runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' && steps.disk_cache_restore.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| # Bound to 8 GiB before saving (GitHub actions/cache entry limit is 10 GB). | |
| bash .github/scripts/prune-bazel-disk-cache.sh "${{ steps.disk_cache_cfg.outputs.path }}" $((8 * 1024 * 1024 * 1024)) | |
| - name: Save Bazel disk cache (keyless) | |
| if: always() && !cancelled() && runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' && steps.disk_cache_restore.outputs.cache-hit != 'true' | |
| continue-on-error: true | |
| uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.disk_cache_cfg.outputs.path }} | |
| key: bazel-disk-${{ github.job }}-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }} | |
| - name: Upload Bazel execution logs | |
| if: always() && !cancelled() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| 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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.prepare_bazel.outputs.repository-cache-path }} | |
| key: ${{ steps.prepare_bazel.outputs.repository-cache-key }} | |
| test-windows-shard: | |
| # Split the Windows Bazel test leg across separate Windows | |
| # hosts. Each shard cross-compiles the gnullvm target with Windows-hosted | |
| # tools and executes the tests on its own Windows runner. | |
| timeout-minutes: 180 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: | |
| - 1 | |
| - 2 | |
| - 3 | |
| - 4 | |
| runs-on: windows-latest | |
| name: Bazel test on windows-latest for x86_64-pc-windows-gnullvm shard ${{ matrix.shard }}/4 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} | |
| persist-credentials: false | |
| - name: Prepare Bazel CI | |
| id: prepare_bazel | |
| uses: ./.github/actions/prepare-bazel-ci | |
| with: | |
| target: x86_64-pc-windows-gnullvm | |
| # Reuse the former monolithic Windows test cache for restores. Do | |
| # not save it from every shard below; duplicate uploads would sit on | |
| # the PR-blocking critical path after the useful test work is done. | |
| cache-scope: bazel-test | |
| install-test-prereqs: "true" | |
| - name: bazel test shard | |
| env: | |
| BAZEL_TEST_SHARD: ${{ matrix.shard }} | |
| BAZEL_TEST_SHARD_COUNT: 4 | |
| BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| bazel_test_query='tests(//...) except tests(//third_party/v8:all) except //codex-rs/code-mode:code-mode-unit-tests except //codex-rs/v8-poc:v8-poc-unit-tests except attr(tags, "manual", tests(//...))' | |
| mapfile -t bazel_targets < <( | |
| MSYS2_ARG_CONV_EXCL='*' bazel query --output=label "${bazel_test_query}" \ | |
| | LC_ALL=C sort | |
| ) | |
| selected_targets=() | |
| for bazel_target in "${bazel_targets[@]}"; do | |
| target_bucket="$( | |
| printf '%s\n' "${bazel_target}" \ | |
| | cksum \ | |
| | awk -v shard_count="${BAZEL_TEST_SHARD_COUNT}" '{ print ($1 % shard_count) + 1 }' | |
| )" | |
| if [[ "${target_bucket}" == "${BAZEL_TEST_SHARD}" ]]; then | |
| selected_targets+=("${bazel_target}") | |
| fi | |
| done | |
| if [[ ${#selected_targets[@]} -eq 0 ]]; then | |
| echo "No Bazel test targets selected for Windows shard ${BAZEL_TEST_SHARD}/${BAZEL_TEST_SHARD_COUNT}." >&2 | |
| exit 1 | |
| fi | |
| echo "Selected ${#selected_targets[@]} of ${#bazel_targets[@]} Bazel test targets for Windows shard ${BAZEL_TEST_SHARD}/${BAZEL_TEST_SHARD_COUNT}." | |
| bazel_test_args=( | |
| test | |
| --skip_incompatible_explicit_targets | |
| --test_tag_filters=-argument-comment-lint | |
| --test_verbose_timeout_warnings | |
| --build_metadata=COMMIT_SHA=${GITHUB_SHA} | |
| --build_metadata=TAG_windows_test_shard=${BAZEL_TEST_SHARD} | |
| ) | |
| ./.github/scripts/run-bazel-ci.sh \ | |
| --print-failed-action-summary \ | |
| --print-failed-test-logs \ | |
| --windows-cross-compile \ | |
| --remote-download-toplevel \ | |
| -- \ | |
| "${bazel_test_args[@]}" \ | |
| -- \ | |
| "${selected_targets[@]}" | |
| - name: Upload Bazel execution logs | |
| if: always() && !cancelled() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: bazel-execution-logs-test-x86_64-pc-windows-gnullvm-shard-${{ matrix.shard }} | |
| path: ${{ runner.temp }}/bazel-execution-logs | |
| if-no-files-found: ignore | |
| test-windows: | |
| # Preserve the existing required-check surface while the real work happens | |
| # in the sharded Windows jobs above. | |
| if: always() | |
| needs: test-windows-shard | |
| runs-on: ubuntu-24.04 | |
| name: Bazel test on windows-latest for x86_64-pc-windows-gnullvm | |
| steps: | |
| - name: Confirm Windows Bazel test shards passed | |
| shell: bash | |
| run: | | |
| if [[ "${{ needs.test-windows-shard.result }}" != "success" ]]; then | |
| echo "Windows Bazel test shards finished with result: ${{ needs.test-windows-shard.result }}" >&2 | |
| exit 1 | |
| fi | |
| test-windows-native-main: | |
| # Native Windows Bazel tests are slower and frequently approach the | |
| # 30-minute PR budget. Run this only for post-merge commits to main and give | |
| # it a larger timeout. | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| timeout-minutes: 180 | |
| runs-on: windows-latest | |
| name: Bazel test on windows-latest for x86_64-pc-windows-gnullvm (native main) | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} | |
| persist-credentials: false | |
| - name: Prepare Bazel CI | |
| id: prepare_bazel | |
| uses: ./.github/actions/prepare-bazel-ci | |
| with: | |
| target: x86_64-pc-windows-gnullvm | |
| cache-scope: bazel-${{ github.job }} | |
| install-test-prereqs: "true" | |
| - 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 | |
| # Keep this aligned with the main Bazel job. The native Windows | |
| # job preserves broad post-merge coverage, but code-mode/V8 tests | |
| # are covered by Cargo CI rather than Bazel for now. | |
| -//codex-rs/code-mode:code-mode-unit-tests | |
| -//codex-rs/v8-poc:v8-poc-unit-tests | |
| ) | |
| bazel_test_args=( | |
| test | |
| --test_tag_filters=-argument-comment-lint | |
| --test_verbose_timeout_warnings | |
| --build_metadata=COMMIT_SHA=${GITHUB_SHA} | |
| --build_metadata=TAG_windows_native_main=true | |
| ) | |
| ./.github/scripts/run-bazel-ci.sh \ | |
| --print-failed-action-summary \ | |
| --print-failed-test-logs \ | |
| -- \ | |
| "${bazel_test_args[@]}" \ | |
| -- \ | |
| "${bazel_targets[@]}" | |
| - name: Upload Bazel execution logs | |
| if: always() && !cancelled() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: bazel-execution-logs-test-windows-native-x86_64-pc-windows-gnullvm | |
| 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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.prepare_bazel.outputs.repository-cache-path }} | |
| key: ${{ steps.prepare_bazel.outputs.repository-cache-key }} | |
| clippy: | |
| # Above the heavy Bazel step's 170-min step timeout: an overrun fails the | |
| # STEP, not the JOB, so !cancelled() stays true and Save banks the cache. | |
| timeout-minutes: 185 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Keep Linux lint coverage on x64 and add Windows gnullvm 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: windows-latest | |
| target: x86_64-pc-windows-gnullvm | |
| runs_on: windows-latest | |
| runs-on: ${{ matrix.os }} | |
| name: Bazel clippy on ${{ matrix.os }} for ${{ matrix.target }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} | |
| persist-credentials: false | |
| - name: Prepare Bazel CI | |
| id: prepare_bazel | |
| uses: ./.github/actions/prepare-bazel-ci | |
| with: | |
| target: ${{ matrix.target }} | |
| cache-scope: bazel-${{ github.job }} | |
| - name: Configure keyless Bazel disk cache | |
| id: disk_cache_cfg | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| env: | |
| BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} | |
| run: | | |
| # Keyless (no BuildBuddy) Linux runs use a persisted local disk cache; | |
| # keyed RBE runs do not. Never print the key, only test its presence. | |
| if [[ -z "${BUILDBUDDY_API_KEY:-}" ]]; then | |
| echo "keyless=true" >> "${GITHUB_OUTPUT}" | |
| else | |
| echo "keyless=false" >> "${GITHUB_OUTPUT}" | |
| fi | |
| echo "path=${HOME}/.cache/bazel-disk-cache" >> "${GITHUB_OUTPUT}" | |
| - name: Restore Bazel disk cache (keyless) | |
| id: disk_cache_restore | |
| if: runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' | |
| continue-on-error: true | |
| uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.disk_cache_cfg.outputs.path }} | |
| key: bazel-disk-${{ github.job }}-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }} | |
| restore-keys: | | |
| bazel-disk-${{ github.job }}-${{ matrix.target }}- | |
| - name: Free Linux runner disk for Bazel clippy | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| run: | | |
| df -h | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL | |
| sudo apt-get clean | |
| df -h | |
| - name: bazel build --config=clippy lint targets | |
| # Bounded below the job timeout-minutes so a cold keyless build that | |
| # overruns fails THIS STEP (a failure) instead of the JOB (a | |
| # cancellation). !cancelled() then stays true and the Prune/Save steps | |
| # below bank the partial disk cache; the job still fails until the | |
| # build finishes within the window (no fake-green). | |
| timeout-minutes: 170 | |
| 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=() | |
| bazel_target_list_args=() | |
| if [[ "${RUNNER_OS}" == "Windows" ]]; then | |
| # Keep this aligned with the fast Windows Bazel test job: use a | |
| # Windows exec host while targeting Windows gnullvm. The generated | |
| # clippy list can include explicit targets that are incompatible | |
| # with the Windows host platform, so keep Bazel from failing after | |
| # successfully building the compatible subset. | |
| bazel_wrapper_args+=(--windows-cross-compile) | |
| bazel_target_list_args+=(--windows-cross-compile) | |
| bazel_clippy_args+=(--skip_incompatible_explicit_targets) | |
| fi | |
| bazel_target_lines="$(./scripts/list-bazel-clippy-targets.sh "${bazel_target_list_args[@]}")" | |
| 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: Prune Bazel disk cache (keyless) | |
| if: always() && !cancelled() && runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' && steps.disk_cache_restore.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| # Bound to 8 GiB before saving (GitHub actions/cache entry limit is 10 GB). | |
| bash .github/scripts/prune-bazel-disk-cache.sh "${{ steps.disk_cache_cfg.outputs.path }}" $((8 * 1024 * 1024 * 1024)) | |
| - name: Save Bazel disk cache (keyless) | |
| if: always() && !cancelled() && runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' && steps.disk_cache_restore.outputs.cache-hit != 'true' | |
| continue-on-error: true | |
| uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.disk_cache_cfg.outputs.path }} | |
| key: bazel-disk-${{ github.job }}-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }} | |
| - name: Upload Bazel execution logs | |
| if: always() && !cancelled() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| 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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.prepare_bazel.outputs.repository-cache-path }} | |
| key: ${{ steps.prepare_bazel.outputs.repository-cache-key }} | |
| verify-release-build: | |
| # Above the heavy Bazel step's 170-min step timeout: an overrun fails the | |
| # STEP, not the JOB, so !cancelled() stays true and Save banks the cache. | |
| timeout-minutes: 185 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-24.04 | |
| target: x86_64-unknown-linux-gnu | |
| - os: windows-latest | |
| target: x86_64-pc-windows-gnullvm | |
| runs_on: windows-latest | |
| runs-on: ${{ matrix.os }} | |
| name: Verify release build on ${{ matrix.os }} for ${{ matrix.target }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} | |
| persist-credentials: false | |
| - name: Prepare Bazel CI | |
| id: prepare_bazel | |
| uses: ./.github/actions/prepare-bazel-ci | |
| with: | |
| target: ${{ matrix.target }} | |
| cache-scope: bazel-${{ github.job }} | |
| - name: Configure keyless Bazel disk cache | |
| id: disk_cache_cfg | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| env: | |
| BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} | |
| run: | | |
| # Keyless (no BuildBuddy) Linux runs use a persisted local disk cache; | |
| # keyed RBE runs do not. Never print the key, only test its presence. | |
| if [[ -z "${BUILDBUDDY_API_KEY:-}" ]]; then | |
| echo "keyless=true" >> "${GITHUB_OUTPUT}" | |
| else | |
| echo "keyless=false" >> "${GITHUB_OUTPUT}" | |
| fi | |
| echo "path=${HOME}/.cache/bazel-disk-cache" >> "${GITHUB_OUTPUT}" | |
| - name: Restore Bazel disk cache (keyless) | |
| id: disk_cache_restore | |
| if: runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' | |
| continue-on-error: true | |
| uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.disk_cache_cfg.outputs.path }} | |
| key: bazel-disk-${{ github.job }}-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }} | |
| restore-keys: | | |
| bazel-disk-${{ github.job }}-${{ matrix.target }}- | |
| - name: bazel build verify-release-build targets | |
| # Bounded below the job timeout-minutes so a cold keyless build that | |
| # overruns fails THIS STEP (a failure) instead of the JOB (a | |
| # cancellation). !cancelled() then stays true and the Prune/Save steps | |
| # below bank the partial disk cache; the job still fails until the | |
| # build finishes within the window (no fake-green). | |
| timeout-minutes: 170 | |
| 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 | |
| # Use the same Windows-hosted cross-compile path as the fast | |
| # Windows test and clippy jobs. | |
| bazel_wrapper_args+=(--windows-cross-compile) | |
| 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: Verify Bazel builds bwrap | |
| if: runner.os == 'Linux' | |
| env: | |
| BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }} | |
| shell: bash | |
| run: | | |
| ./.github/scripts/run-bazel-ci.sh \ | |
| --remote-download-toplevel \ | |
| --print-failed-action-summary \ | |
| -- \ | |
| build \ | |
| --build_metadata=COMMIT_SHA=${GITHUB_SHA} \ | |
| --build_metadata=TAG_job=verify-bwrap \ | |
| -- \ | |
| //codex-rs/bwrap:bwrap | |
| - name: Prune Bazel disk cache (keyless) | |
| if: always() && !cancelled() && runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' && steps.disk_cache_restore.outputs.cache-hit != 'true' | |
| shell: bash | |
| run: | | |
| # Bound to 8 GiB before saving (GitHub actions/cache entry limit is 10 GB). | |
| bash .github/scripts/prune-bazel-disk-cache.sh "${{ steps.disk_cache_cfg.outputs.path }}" $((8 * 1024 * 1024 * 1024)) | |
| - name: Save Bazel disk cache (keyless) | |
| if: always() && !cancelled() && runner.os == 'Linux' && steps.disk_cache_cfg.outputs.keyless == 'true' && steps.disk_cache_restore.outputs.cache-hit != 'true' | |
| continue-on-error: true | |
| uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.disk_cache_cfg.outputs.path }} | |
| key: bazel-disk-${{ github.job }}-${{ matrix.target }}-${{ hashFiles('MODULE.bazel', 'codex-rs/Cargo.lock', 'codex-rs/Cargo.toml') }} | |
| - name: Upload Bazel execution logs | |
| if: always() && !cancelled() | |
| continue-on-error: true | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| 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@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ${{ steps.prepare_bazel.outputs.repository-cache-path }} | |
| key: ${{ steps.prepare_bazel.outputs.repository-cache-key }} |