mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
## Why `argument-comment-lint` was green in CI even though the repo still had many uncommented literal arguments. The main gap was target coverage: the repo wrapper did not force Cargo to inspect test-only call sites, so examples like the `latest_session_lookup_params(true, ...)` tests in `codex-rs/tui_app_server/src/lib.rs` never entered the blocking CI path. This change cleans up the existing backlog, makes the default repo lint path cover all Cargo targets, and starts rolling that stricter CI enforcement out on the platform where it is currently validated. ## What changed - mechanically fixed existing `argument-comment-lint` violations across the `codex-rs` workspace, including tests, examples, and benches - updated `tools/argument-comment-lint/run-prebuilt-linter.sh` and `tools/argument-comment-lint/run.sh` so non-`--fix` runs default to `--all-targets` unless the caller explicitly narrows the target set - fixed both wrappers so forwarded cargo arguments after `--` are preserved with a single separator - documented the new default behavior in `tools/argument-comment-lint/README.md` - updated `rust-ci` so the macOS lint lane keeps the plain wrapper invocation and therefore enforces `--all-targets`, while Linux and Windows temporarily pass `-- --lib --bins` That temporary CI split keeps the stricter all-targets check where it is already cleaned up, while leaving room to finish the remaining Linux- and Windows-specific target-gated cleanup before enabling `--all-targets` on those runners. The Linux and Windows failures on the intermediate revision were caused by the wrapper forwarding bug, not by additional lint findings in those lanes. ## Validation - `bash -n tools/argument-comment-lint/run.sh` - `bash -n tools/argument-comment-lint/run-prebuilt-linter.sh` - shell-level wrapper forwarding check for `-- --lib --bins` - shell-level wrapper forwarding check for `-- --tests` - `just argument-comment-lint` - `cargo test` in `tools/argument-comment-lint` - `cargo test -p codex-terminal-detection` ## Follow-up - Clean up remaining Linux-only target-gated callsites, then switch the Linux lint lane back to the plain wrapper invocation. - Clean up remaining Windows-only target-gated callsites, then switch the Windows lint lane back to the plain wrapper invocation.
834 lines
35 KiB
YAML
834 lines
35 KiB
YAML
name: rust-ci
|
|
on:
|
|
pull_request: {}
|
|
push:
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
|
|
# CI builds in debug (dev) for faster signal.
|
|
|
|
jobs:
|
|
# --- Detect what changed to detect which tests to run (always runs) -------------------------------------
|
|
changed:
|
|
name: Detect changed areas
|
|
runs-on: ubuntu-24.04
|
|
outputs:
|
|
argument_comment_lint: ${{ steps.detect.outputs.argument_comment_lint }}
|
|
argument_comment_lint_package: ${{ steps.detect.outputs.argument_comment_lint_package }}
|
|
codex: ${{ steps.detect.outputs.codex }}
|
|
workflows: ${{ steps.detect.outputs.workflows }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Detect changed paths (no external action)
|
|
id: detect
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
|
BASE_SHA='${{ github.event.pull_request.base.sha }}'
|
|
HEAD_SHA='${{ github.event.pull_request.head.sha }}'
|
|
echo "Base SHA: $BASE_SHA"
|
|
echo "Head SHA: $HEAD_SHA"
|
|
# List files changed between base and PR head
|
|
mapfile -t files < <(git diff --name-only --no-renames "$BASE_SHA" "$HEAD_SHA")
|
|
else
|
|
# On push / manual runs, default to running everything
|
|
files=("codex-rs/force" ".github/force")
|
|
fi
|
|
|
|
codex=false
|
|
argument_comment_lint=false
|
|
argument_comment_lint_package=false
|
|
workflows=false
|
|
for f in "${files[@]}"; do
|
|
[[ $f == codex-rs/* ]] && codex=true
|
|
[[ $f == codex-rs/* || $f == tools/argument-comment-lint/* || $f == justfile ]] && argument_comment_lint=true
|
|
[[ $f == tools/argument-comment-lint/* || $f == .github/workflows/rust-ci.yml ]] && argument_comment_lint_package=true
|
|
[[ $f == .github/* ]] && workflows=true
|
|
done
|
|
|
|
echo "argument_comment_lint=$argument_comment_lint" >> "$GITHUB_OUTPUT"
|
|
echo "argument_comment_lint_package=$argument_comment_lint_package" >> "$GITHUB_OUTPUT"
|
|
echo "codex=$codex" >> "$GITHUB_OUTPUT"
|
|
echo "workflows=$workflows" >> "$GITHUB_OUTPUT"
|
|
|
|
# --- CI that doesn't need specific targets ---------------------------------
|
|
general:
|
|
name: Format / etc
|
|
runs-on: ubuntu-24.04
|
|
needs: changed
|
|
if: ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' || github.event_name == 'push' }}
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
|
with:
|
|
components: rustfmt
|
|
- name: cargo fmt
|
|
run: cargo fmt -- --config imports_granularity=Item --check
|
|
|
|
cargo_shear:
|
|
name: cargo shear
|
|
runs-on: ubuntu-24.04
|
|
needs: changed
|
|
if: ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' || github.event_name == 'push' }}
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
|
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
|
|
with:
|
|
tool: cargo-shear
|
|
version: 1.5.1
|
|
- name: cargo shear
|
|
run: cargo shear
|
|
|
|
argument_comment_lint_package:
|
|
name: Argument comment lint package
|
|
runs-on: ubuntu-24.04
|
|
needs: changed
|
|
if: ${{ needs.changed.outputs.argument_comment_lint_package == 'true' || github.event_name == 'push' }}
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
|
with:
|
|
toolchain: nightly-2025-09-18
|
|
components: llvm-tools-preview, rustc-dev, rust-src
|
|
- name: Cache cargo-dylint tooling
|
|
id: cargo_dylint_cache
|
|
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: |
|
|
~/.cargo/bin/cargo-dylint
|
|
~/.cargo/bin/dylint-link
|
|
~/.cargo/registry/index
|
|
~/.cargo/registry/cache
|
|
~/.cargo/git/db
|
|
key: argument-comment-lint-${{ runner.os }}-${{ hashFiles('tools/argument-comment-lint/Cargo.lock', 'tools/argument-comment-lint/rust-toolchain', '.github/workflows/rust-ci.yml') }}
|
|
- name: Install cargo-dylint tooling
|
|
if: ${{ steps.cargo_dylint_cache.outputs.cache-hit != 'true' }}
|
|
run: cargo install --locked cargo-dylint dylint-link
|
|
- name: Check source wrapper syntax
|
|
run: bash -n tools/argument-comment-lint/run.sh
|
|
- name: Test argument comment lint package
|
|
working-directory: tools/argument-comment-lint
|
|
run: cargo test
|
|
|
|
argument_comment_lint_prebuilt:
|
|
name: Argument comment lint - ${{ matrix.name }}
|
|
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
|
needs: changed
|
|
if: ${{ needs.changed.outputs.argument_comment_lint == 'true' || needs.changed.outputs.workflows == 'true' || github.event_name == 'push' }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- name: Linux
|
|
runner: ubuntu-24.04
|
|
- name: macOS
|
|
runner: macos-15-xlarge
|
|
- name: Windows
|
|
runner: windows-x64
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-windows-x64
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
- name: Install Linux sandbox build dependencies
|
|
if: ${{ runner.os == 'Linux' }}
|
|
shell: bash
|
|
run: |
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev
|
|
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
|
with:
|
|
toolchain: nightly-2025-09-18
|
|
components: llvm-tools-preview, rustc-dev, rust-src
|
|
- uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
|
- name: Run argument comment lint on codex-rs
|
|
if: ${{ runner.os == 'macOS' }}
|
|
shell: bash
|
|
run: ./tools/argument-comment-lint/run-prebuilt-linter.sh
|
|
- name: Run argument comment lint on codex-rs (default targets only)
|
|
if: ${{ runner.os != 'macOS' }}
|
|
shell: bash
|
|
run: ./tools/argument-comment-lint/run-prebuilt-linter.sh -- --lib --bins
|
|
|
|
# --- CI to validate on different os/targets --------------------------------
|
|
lint_build:
|
|
name: Lint/Build — ${{ matrix.runner }} - ${{ matrix.target }}${{ matrix.profile == 'release' && ' (release)' || '' }}
|
|
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
|
timeout-minutes: 30
|
|
needs: changed
|
|
# Keep job-level if to avoid spinning up runners when not needed
|
|
if: ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' || github.event_name == 'push' }}
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
env:
|
|
# Speed up repeated builds across CI runs by caching compiled objects, except on
|
|
# arm64 macOS runners cross-targeting x86_64 where ring/cc-rs can produce
|
|
# mixed-architecture archives under sccache.
|
|
USE_SCCACHE: ${{ (startsWith(matrix.runner, 'windows') || (matrix.runner == 'macos-15-xlarge' && matrix.target == 'x86_64-apple-darwin')) && 'false' || 'true' }}
|
|
CARGO_INCREMENTAL: "0"
|
|
SCCACHE_CACHE_SIZE: 10G
|
|
# In rust-ci, representative release-profile checks use thin LTO for faster feedback.
|
|
CARGO_PROFILE_RELEASE_LTO: ${{ matrix.profile == 'release' && 'thin' || 'fat' }}
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: macos-15-xlarge
|
|
target: aarch64-apple-darwin
|
|
profile: dev
|
|
- runner: macos-15-xlarge
|
|
target: x86_64-apple-darwin
|
|
profile: dev
|
|
- runner: ubuntu-24.04
|
|
target: x86_64-unknown-linux-musl
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-x64
|
|
- runner: ubuntu-24.04
|
|
target: x86_64-unknown-linux-gnu
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-x64
|
|
- runner: ubuntu-24.04-arm
|
|
target: aarch64-unknown-linux-musl
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-arm64
|
|
- runner: ubuntu-24.04-arm
|
|
target: aarch64-unknown-linux-gnu
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-arm64
|
|
- runner: windows-x64
|
|
target: x86_64-pc-windows-msvc
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-windows-x64
|
|
- runner: windows-arm64
|
|
target: aarch64-pc-windows-msvc
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-windows-arm64
|
|
|
|
# Also run representative release builds on Mac and Linux because
|
|
# there could be release-only build errors we want to catch.
|
|
# Hopefully this also pre-populates the build cache to speed up
|
|
# releases.
|
|
- runner: macos-15-xlarge
|
|
target: aarch64-apple-darwin
|
|
profile: release
|
|
- runner: ubuntu-24.04
|
|
target: x86_64-unknown-linux-musl
|
|
profile: release
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-x64
|
|
- runner: ubuntu-24.04-arm
|
|
target: aarch64-unknown-linux-musl
|
|
profile: release
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-arm64
|
|
- runner: windows-x64
|
|
target: x86_64-pc-windows-msvc
|
|
profile: release
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-windows-x64
|
|
- runner: windows-arm64
|
|
target: aarch64-pc-windows-msvc
|
|
profile: release
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-windows-arm64
|
|
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
- name: Install Linux build dependencies
|
|
if: ${{ runner.os == 'Linux' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
sudo apt-get update -y
|
|
packages=(pkg-config libcap-dev)
|
|
if [[ "${{ matrix.target }}" == 'x86_64-unknown-linux-musl' || "${{ matrix.target }}" == 'aarch64-unknown-linux-musl' ]]; then
|
|
packages+=(libubsan1)
|
|
fi
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "${packages[@]}"
|
|
fi
|
|
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
|
with:
|
|
targets: ${{ matrix.target }}
|
|
components: clippy
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Use hermetic Cargo home (musl)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
cargo_home="${GITHUB_WORKSPACE}/.cargo-home"
|
|
mkdir -p "${cargo_home}/bin"
|
|
echo "CARGO_HOME=${cargo_home}" >> "$GITHUB_ENV"
|
|
echo "${cargo_home}/bin" >> "$GITHUB_PATH"
|
|
: > "${cargo_home}/config.toml"
|
|
|
|
- name: Compute lockfile hash
|
|
id: lockhash
|
|
working-directory: codex-rs
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
echo "hash=$(sha256sum Cargo.lock | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
|
echo "toolchain_hash=$(sha256sum rust-toolchain.toml | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
|
|
|
# Explicit cache restore: split cargo home vs target, so we can
|
|
# avoid caching the large target dir on the gnu-dev job.
|
|
- name: Restore cargo home cache
|
|
id: cache_cargo_home_restore
|
|
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: |
|
|
~/.cargo/bin/
|
|
~/.cargo/registry/index/
|
|
~/.cargo/registry/cache/
|
|
~/.cargo/git/db/
|
|
${{ github.workspace }}/.cargo-home/bin/
|
|
${{ github.workspace }}/.cargo-home/registry/index/
|
|
${{ github.workspace }}/.cargo-home/registry/cache/
|
|
${{ github.workspace }}/.cargo-home/git/db/
|
|
key: cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
|
restore-keys: |
|
|
cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
|
|
|
|
# Install and restore sccache cache
|
|
- name: Install sccache
|
|
if: ${{ env.USE_SCCACHE == 'true' }}
|
|
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
|
|
with:
|
|
tool: sccache
|
|
version: 0.7.5
|
|
|
|
- name: Configure sccache backend
|
|
if: ${{ env.USE_SCCACHE == 'true' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -n "${ACTIONS_CACHE_URL:-}" && -n "${ACTIONS_RUNTIME_TOKEN:-}" ]]; then
|
|
echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
|
|
echo "Using sccache GitHub backend"
|
|
else
|
|
echo "SCCACHE_GHA_ENABLED=false" >> "$GITHUB_ENV"
|
|
echo "SCCACHE_DIR=${{ github.workspace }}/.sccache" >> "$GITHUB_ENV"
|
|
echo "Using sccache local disk + actions/cache fallback"
|
|
fi
|
|
|
|
- name: Enable sccache wrapper
|
|
if: ${{ env.USE_SCCACHE == 'true' }}
|
|
shell: bash
|
|
run: echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV"
|
|
|
|
- name: Restore sccache cache (fallback)
|
|
if: ${{ env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true' }}
|
|
id: cache_sccache_restore
|
|
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: ${{ github.workspace }}/.sccache/
|
|
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
|
restore-keys: |
|
|
sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-
|
|
sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Disable sccache wrapper (musl)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
echo "RUSTC_WRAPPER=" >> "$GITHUB_ENV"
|
|
echo "RUSTC_WORKSPACE_WRAPPER=" >> "$GITHUB_ENV"
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Prepare APT cache directories (musl)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
sudo mkdir -p /var/cache/apt/archives /var/lib/apt/lists
|
|
sudo chown -R "$USER:$USER" /var/cache/apt /var/lib/apt/lists
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Restore APT cache (musl)
|
|
id: cache_apt_restore
|
|
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: |
|
|
/var/cache/apt
|
|
key: apt-${{ matrix.runner }}-${{ matrix.target }}-v1
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Install Zig
|
|
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2
|
|
with:
|
|
version: 0.14.0
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Install musl build tools
|
|
env:
|
|
DEBIAN_FRONTEND: noninteractive
|
|
TARGET: ${{ matrix.target }}
|
|
APT_UPDATE_ARGS: -o Acquire::Retries=3
|
|
APT_INSTALL_ARGS: --no-install-recommends
|
|
shell: bash
|
|
run: bash "${GITHUB_WORKSPACE}/.github/scripts/install-musl-build-tools.sh"
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Configure rustc UBSan wrapper (musl host)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
ubsan=""
|
|
if command -v ldconfig >/dev/null 2>&1; then
|
|
ubsan="$(ldconfig -p | grep -m1 'libubsan\.so\.1' | sed -E 's/.*=> (.*)$/\1/')"
|
|
fi
|
|
wrapper_root="${RUNNER_TEMP:-/tmp}"
|
|
wrapper="${wrapper_root}/rustc-ubsan-wrapper"
|
|
cat > "${wrapper}" <<EOF
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
if [[ -n "${ubsan}" ]]; then
|
|
export LD_PRELOAD="${ubsan}\${LD_PRELOAD:+:\${LD_PRELOAD}}"
|
|
fi
|
|
exec "\$1" "\${@:2}"
|
|
EOF
|
|
chmod +x "${wrapper}"
|
|
echo "RUSTC_WRAPPER=${wrapper}" >> "$GITHUB_ENV"
|
|
echo "RUSTC_WORKSPACE_WRAPPER=" >> "$GITHUB_ENV"
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl'}}
|
|
name: Clear sanitizer flags (musl)
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
# Clear global Rust flags so host/proc-macro builds don't pull in UBSan.
|
|
echo "RUSTFLAGS=" >> "$GITHUB_ENV"
|
|
echo "CARGO_ENCODED_RUSTFLAGS=" >> "$GITHUB_ENV"
|
|
echo "RUSTDOCFLAGS=" >> "$GITHUB_ENV"
|
|
# Override any runner-level Cargo config rustflags as well.
|
|
echo "CARGO_BUILD_RUSTFLAGS=" >> "$GITHUB_ENV"
|
|
echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS=" >> "$GITHUB_ENV"
|
|
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS=" >> "$GITHUB_ENV"
|
|
echo "CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS=" >> "$GITHUB_ENV"
|
|
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS=" >> "$GITHUB_ENV"
|
|
|
|
sanitize_flags() {
|
|
local input="$1"
|
|
input="${input//-fsanitize=undefined/}"
|
|
input="${input//-fno-sanitize-recover=undefined/}"
|
|
input="${input//-fno-sanitize-trap=undefined/}"
|
|
echo "$input"
|
|
}
|
|
|
|
cflags="$(sanitize_flags "${CFLAGS-}")"
|
|
cxxflags="$(sanitize_flags "${CXXFLAGS-}")"
|
|
echo "CFLAGS=${cflags}" >> "$GITHUB_ENV"
|
|
echo "CXXFLAGS=${cxxflags}" >> "$GITHUB_ENV"
|
|
|
|
- if: ${{ matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl' }}
|
|
name: Configure musl rusty_v8 artifact overrides
|
|
env:
|
|
TARGET: ${{ matrix.target }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
version="$(python3 "${GITHUB_WORKSPACE}/.github/scripts/rusty_v8_bazel.py" resolved-v8-crate-version)"
|
|
release_tag="rusty-v8-v${version}"
|
|
base_url="https://github.com/openai/codex/releases/download/${release_tag}"
|
|
archive="https://github.com/openai/codex/releases/download/rusty-v8-v${version}/librusty_v8_release_${TARGET}.a.gz"
|
|
binding_dir="${RUNNER_TEMP}/rusty_v8"
|
|
binding_path="${binding_dir}/src_binding_release_${TARGET}.rs"
|
|
mkdir -p "${binding_dir}"
|
|
curl -fsSL "${base_url}/src_binding_release_${TARGET}.rs" -o "${binding_path}"
|
|
echo "RUSTY_V8_ARCHIVE=${archive}" >> "$GITHUB_ENV"
|
|
echo "RUSTY_V8_SRC_BINDING_PATH=${binding_path}" >> "$GITHUB_ENV"
|
|
|
|
- name: Install cargo-chef
|
|
if: ${{ matrix.profile == 'release' }}
|
|
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
|
|
with:
|
|
tool: cargo-chef
|
|
version: 0.1.71
|
|
|
|
- name: Pre-warm dependency cache (cargo-chef)
|
|
if: ${{ matrix.profile == 'release' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
RECIPE="${RUNNER_TEMP}/chef-recipe.json"
|
|
cargo chef prepare --recipe-path "$RECIPE"
|
|
cargo chef cook --recipe-path "$RECIPE" --target ${{ matrix.target }} --release --all-features
|
|
|
|
- name: cargo clippy
|
|
run: cargo clippy --target ${{ matrix.target }} --all-features --tests --profile ${{ matrix.profile }} --timings -- -D warnings
|
|
|
|
- name: Upload Cargo timings (clippy)
|
|
if: always()
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
|
with:
|
|
name: cargo-timings-rust-ci-clippy-${{ matrix.target }}-${{ matrix.profile }}
|
|
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
|
if-no-files-found: warn
|
|
|
|
# Save caches explicitly; make non-fatal so cache packaging
|
|
# never fails the overall job. Only save when key wasn't hit.
|
|
- name: Save cargo home cache
|
|
if: always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: |
|
|
~/.cargo/bin/
|
|
~/.cargo/registry/index/
|
|
~/.cargo/registry/cache/
|
|
~/.cargo/git/db/
|
|
${{ github.workspace }}/.cargo-home/bin/
|
|
${{ github.workspace }}/.cargo-home/registry/index/
|
|
${{ github.workspace }}/.cargo-home/registry/cache/
|
|
${{ github.workspace }}/.cargo-home/git/db/
|
|
key: cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
|
|
|
- name: Save sccache cache (fallback)
|
|
if: always() && !cancelled() && env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: ${{ github.workspace }}/.sccache/
|
|
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
|
|
|
- name: sccache stats
|
|
if: always() && env.USE_SCCACHE == 'true'
|
|
continue-on-error: true
|
|
run: sccache --show-stats || true
|
|
|
|
- name: sccache summary
|
|
if: always() && env.USE_SCCACHE == 'true'
|
|
shell: bash
|
|
run: |
|
|
{
|
|
echo "### sccache stats — ${{ matrix.target }} (${{ matrix.profile }})";
|
|
echo;
|
|
echo '```';
|
|
sccache --show-stats || true;
|
|
echo '```';
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
- name: Save APT cache (musl)
|
|
if: always() && !cancelled() && (matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl') && steps.cache_apt_restore.outputs.cache-hit != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: |
|
|
/var/cache/apt
|
|
key: apt-${{ matrix.runner }}-${{ matrix.target }}-v1
|
|
|
|
tests:
|
|
name: Tests — ${{ matrix.runner }} - ${{ matrix.target }}${{ matrix.remote_env == 'true' && ' (remote)' || '' }}
|
|
runs-on: ${{ matrix.runs_on || matrix.runner }}
|
|
# Perhaps we can bring this back down to 30m once we finish the cutover
|
|
# from tui_app_server/ to tui/. Incidentally, windows-arm64 was the main
|
|
# offender for exceeding the timeout.
|
|
timeout-minutes: 45
|
|
needs: changed
|
|
if: ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' || github.event_name == 'push' }}
|
|
defaults:
|
|
run:
|
|
working-directory: codex-rs
|
|
env:
|
|
# Speed up repeated builds across CI runs by caching compiled objects, except on
|
|
# arm64 macOS runners cross-targeting x86_64 where ring/cc-rs can produce
|
|
# mixed-architecture archives under sccache.
|
|
USE_SCCACHE: ${{ (startsWith(matrix.runner, 'windows') || (matrix.runner == 'macos-15-xlarge' && matrix.target == 'x86_64-apple-darwin')) && 'false' || 'true' }}
|
|
CARGO_INCREMENTAL: "0"
|
|
SCCACHE_CACHE_SIZE: 10G
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- runner: macos-15-xlarge
|
|
target: aarch64-apple-darwin
|
|
profile: dev
|
|
- runner: ubuntu-24.04
|
|
target: x86_64-unknown-linux-gnu
|
|
profile: dev
|
|
remote_env: "true"
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-x64
|
|
- runner: ubuntu-24.04-arm
|
|
target: aarch64-unknown-linux-gnu
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-linux-arm64
|
|
- runner: windows-x64
|
|
target: x86_64-pc-windows-msvc
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-windows-x64
|
|
- runner: windows-arm64
|
|
target: aarch64-pc-windows-msvc
|
|
profile: dev
|
|
runs_on:
|
|
group: codex-runners
|
|
labels: codex-windows-arm64
|
|
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
- name: Set up Node.js for js_repl tests
|
|
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
|
with:
|
|
node-version-file: codex-rs/node-version.txt
|
|
- name: Install Linux build dependencies
|
|
if: ${{ runner.os == 'Linux' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
sudo apt-get update -y
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends pkg-config libcap-dev
|
|
fi
|
|
|
|
# Some integration tests rely on DotSlash being installed.
|
|
# See https://github.com/openai/codex/pull/7617.
|
|
- name: Install DotSlash
|
|
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
|
|
|
|
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
|
|
with:
|
|
targets: ${{ matrix.target }}
|
|
|
|
- name: Compute lockfile hash
|
|
id: lockhash
|
|
working-directory: codex-rs
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
echo "hash=$(sha256sum Cargo.lock | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
|
echo "toolchain_hash=$(sha256sum rust-toolchain.toml | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Restore cargo home cache
|
|
id: cache_cargo_home_restore
|
|
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: |
|
|
~/.cargo/bin/
|
|
~/.cargo/registry/index/
|
|
~/.cargo/registry/cache/
|
|
~/.cargo/git/db/
|
|
key: cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
|
restore-keys: |
|
|
cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
|
|
|
|
- name: Install sccache
|
|
if: ${{ env.USE_SCCACHE == 'true' }}
|
|
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
|
|
with:
|
|
tool: sccache
|
|
version: 0.7.5
|
|
|
|
- name: Configure sccache backend
|
|
if: ${{ env.USE_SCCACHE == 'true' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -n "${ACTIONS_CACHE_URL:-}" && -n "${ACTIONS_RUNTIME_TOKEN:-}" ]]; then
|
|
echo "SCCACHE_GHA_ENABLED=true" >> "$GITHUB_ENV"
|
|
echo "Using sccache GitHub backend"
|
|
else
|
|
echo "SCCACHE_GHA_ENABLED=false" >> "$GITHUB_ENV"
|
|
echo "SCCACHE_DIR=${{ github.workspace }}/.sccache" >> "$GITHUB_ENV"
|
|
echo "Using sccache local disk + actions/cache fallback"
|
|
fi
|
|
|
|
- name: Enable sccache wrapper
|
|
if: ${{ env.USE_SCCACHE == 'true' }}
|
|
shell: bash
|
|
run: echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV"
|
|
|
|
- name: Restore sccache cache (fallback)
|
|
if: ${{ env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true' }}
|
|
id: cache_sccache_restore
|
|
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: ${{ github.workspace }}/.sccache/
|
|
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
|
restore-keys: |
|
|
sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-
|
|
sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-
|
|
|
|
- uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
|
|
with:
|
|
tool: nextest
|
|
version: 0.9.103
|
|
|
|
- name: Enable unprivileged user namespaces (Linux)
|
|
if: runner.os == 'Linux'
|
|
run: |
|
|
# Required for bubblewrap to work on Linux CI runners.
|
|
sudo sysctl -w kernel.unprivileged_userns_clone=1
|
|
# Ubuntu 24.04+ can additionally gate unprivileged user namespaces
|
|
# behind AppArmor.
|
|
if sudo sysctl -a 2>/dev/null | grep -q '^kernel.apparmor_restrict_unprivileged_userns'; then
|
|
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
|
fi
|
|
|
|
- name: Set up remote test env (Docker)
|
|
if: ${{ runner.os == 'Linux' && matrix.remote_env == 'true' }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
export CODEX_TEST_REMOTE_ENV_CONTAINER_NAME=codex-remote-test-env
|
|
source "${GITHUB_WORKSPACE}/scripts/test-remote-env.sh"
|
|
echo "CODEX_TEST_REMOTE_ENV=${CODEX_TEST_REMOTE_ENV}" >> "$GITHUB_ENV"
|
|
|
|
- name: tests
|
|
id: test
|
|
run: cargo nextest run --all-features --no-fail-fast --target ${{ matrix.target }} --cargo-profile ci-test --timings
|
|
env:
|
|
RUST_BACKTRACE: 1
|
|
NEXTEST_STATUS_LEVEL: leak
|
|
|
|
- name: Upload Cargo timings (nextest)
|
|
if: always()
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7
|
|
with:
|
|
name: cargo-timings-rust-ci-nextest-${{ matrix.target }}-${{ matrix.profile }}
|
|
path: codex-rs/target/**/cargo-timings/cargo-timing.html
|
|
if-no-files-found: warn
|
|
|
|
- name: Save cargo home cache
|
|
if: always() && !cancelled() && steps.cache_cargo_home_restore.outputs.cache-hit != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: |
|
|
~/.cargo/bin/
|
|
~/.cargo/registry/index/
|
|
~/.cargo/registry/cache/
|
|
~/.cargo/git/db/
|
|
key: cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
|
|
|
|
- name: Save sccache cache (fallback)
|
|
if: always() && !cancelled() && env.USE_SCCACHE == 'true' && env.SCCACHE_GHA_ENABLED != 'true'
|
|
continue-on-error: true
|
|
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
|
|
with:
|
|
path: ${{ github.workspace }}/.sccache/
|
|
key: sccache-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
|
|
|
|
- name: sccache stats
|
|
if: always() && env.USE_SCCACHE == 'true'
|
|
continue-on-error: true
|
|
run: sccache --show-stats || true
|
|
|
|
- name: sccache summary
|
|
if: always() && env.USE_SCCACHE == 'true'
|
|
shell: bash
|
|
run: |
|
|
{
|
|
echo "### sccache stats — ${{ matrix.target }} (tests)";
|
|
echo;
|
|
echo '```';
|
|
sccache --show-stats || true;
|
|
echo '```';
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
- name: Tear down remote test env
|
|
if: ${{ always() && runner.os == 'Linux' && matrix.remote_env == 'true' }}
|
|
shell: bash
|
|
run: |
|
|
set +e
|
|
if [[ "${{ steps.test.outcome }}" != "success" ]]; then
|
|
docker logs codex-remote-test-env || true
|
|
fi
|
|
docker rm -f codex-remote-test-env >/dev/null 2>&1 || true
|
|
|
|
- name: verify tests passed
|
|
if: steps.test.outcome == 'failure'
|
|
run: |
|
|
echo "Tests failed. See logs for details."
|
|
exit 1
|
|
|
|
# --- Gatherer job that you mark as the ONLY required status -----------------
|
|
results:
|
|
name: CI results (required)
|
|
needs:
|
|
[
|
|
changed,
|
|
general,
|
|
cargo_shear,
|
|
argument_comment_lint_package,
|
|
argument_comment_lint_prebuilt,
|
|
lint_build,
|
|
tests,
|
|
]
|
|
if: always()
|
|
runs-on: ubuntu-24.04
|
|
steps:
|
|
- name: Summarize
|
|
shell: bash
|
|
run: |
|
|
echo "argpkg : ${{ needs.argument_comment_lint_package.result }}"
|
|
echo "arglint: ${{ needs.argument_comment_lint_prebuilt.result }}"
|
|
echo "general: ${{ needs.general.result }}"
|
|
echo "shear : ${{ needs.cargo_shear.result }}"
|
|
echo "lint : ${{ needs.lint_build.result }}"
|
|
echo "tests : ${{ needs.tests.result }}"
|
|
|
|
# If nothing relevant changed (PR touching only root README, etc.),
|
|
# declare success regardless of other jobs.
|
|
if [[ '${{ needs.changed.outputs.argument_comment_lint }}' != 'true' && '${{ needs.changed.outputs.codex }}' != 'true' && '${{ needs.changed.outputs.workflows }}' != 'true' && '${{ github.event_name }}' != 'push' ]]; then
|
|
echo 'No relevant changes -> CI not required.'
|
|
exit 0
|
|
fi
|
|
|
|
if [[ '${{ needs.changed.outputs.argument_comment_lint_package }}' == 'true' || '${{ github.event_name }}' == 'push' ]]; then
|
|
[[ '${{ needs.argument_comment_lint_package.result }}' == 'success' ]] || { echo 'argument_comment_lint_package failed'; exit 1; }
|
|
fi
|
|
|
|
if [[ '${{ needs.changed.outputs.argument_comment_lint }}' == 'true' || '${{ needs.changed.outputs.workflows }}' == 'true' || '${{ github.event_name }}' == 'push' ]]; then
|
|
[[ '${{ needs.argument_comment_lint_prebuilt.result }}' == 'success' ]] || { echo 'argument_comment_lint_prebuilt failed'; exit 1; }
|
|
fi
|
|
|
|
if [[ '${{ needs.changed.outputs.codex }}' == 'true' || '${{ needs.changed.outputs.workflows }}' == 'true' || '${{ github.event_name }}' == 'push' ]]; then
|
|
[[ '${{ needs.general.result }}' == 'success' ]] || { echo 'general failed'; exit 1; }
|
|
[[ '${{ needs.cargo_shear.result }}' == 'success' ]] || { echo 'cargo_shear failed'; exit 1; }
|
|
[[ '${{ needs.lint_build.result }}' == 'success' ]] || { echo 'lint_build failed'; exit 1; }
|
|
[[ '${{ needs.tests.result }}' == 'success' ]] || { echo 'tests failed'; exit 1; }
|
|
fi
|
|
|
|
- name: sccache summary note
|
|
if: always()
|
|
run: |
|
|
echo "Per-job sccache stats are attached to each matrix job's Step Summary."
|