Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The workflows in this directory are split so that pull requests get fast, review
- `rust-ci.yml` keeps the Cargo-native PR checks intentionally small:
- `cargo fmt --check`
- `cargo shear`
- Linux `codex-core` remote-env smoke tests in Docker
- `argument-comment-lint` on Linux, macOS, and Windows
- `tools/argument-comment-lint` package tests when the lint or its workflow wiring changes

Expand Down
145 changes: 145 additions & 0 deletions .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,148 @@ jobs:
- name: cargo shear
run: cargo shear

remote_tests_linux:
name: Remote tests - Linux
runs-on:
group: codex-runners
labels: codex-linux-x64
timeout-minutes: 45
needs: changed
if: ${{ needs.changed.outputs.codex == 'true' || needs.changed.outputs.workflows == 'true' }}
defaults:
run:
working-directory: codex-rs
env:
USE_SCCACHE: "true"
CARGO_INCREMENTAL: "0"
SCCACHE_CACHE_SIZE: 10G
CODEX_TEST_REMOTE_ENV_TARGET: x86_64-unknown-linux-gnu
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
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
- name: Install DotSlash
uses: facebook/install-dotslash@1e4e7b3e07eaca387acb98f1d4720e0bee8dbb6a # v2
- uses: dtolnay/rust-toolchain@a0b273b48ed29de4470960879e8381ff45632f26 # 1.93.0
with:
targets: ${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}
- name: Compute lockfile hash
id: lockhash
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@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: cargo-home-${{ runner.os }}-${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}-remote-tests-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
restore-keys: |
cargo-home-${{ runner.os }}-${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}-remote-tests-
- name: Install sccache
uses: taiki-e/install-action@44c6d64aa62cd779e873306675c7a58e86d6d532 # v2
with:
tool: sccache
version: 0.7.5
- name: Configure sccache backend
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
shell: bash
run: echo "RUSTC_WRAPPER=sccache" >> "$GITHUB_ENV"
- name: Restore sccache cache (fallback)
if: ${{ env.SCCACHE_GHA_ENABLED != 'true' }}
id: cache_sccache_restore
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: ${{ github.workspace }}/.sccache/
key: sccache-${{ runner.os }}-${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}-remote-tests-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
restore-keys: |
sccache-${{ runner.os }}-${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}-remote-tests-${{ steps.lockhash.outputs.hash }}-
sccache-${{ runner.os }}-${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}-remote-tests-
- name: Enable unprivileged user namespaces
run: |
sudo sysctl -w kernel.unprivileged_userns_clone=1
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)
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: Build remote exec-server binary
shell: bash
run: |
set -euo pipefail
cargo build -p codex-exec-server --bin codex-exec-server --target ${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}
binary_path="${GITHUB_WORKSPACE}/codex-rs/target/${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}/debug/codex-exec-server"
echo "CARGO_BIN_EXE_codex_exec_server=${binary_path}" >> "$GITHUB_ENV"
- name: Remote tests
id: remote_tests
shell: bash
run: |
set -euo pipefail
cargo test -p codex-core --target ${{ env.CODEX_TEST_REMOTE_ENV_TARGET }} --lib unified_exec::tests::unified_exec_uses_remote_exec_server_when_configured -- --exact
cargo test -p codex-core --target ${{ env.CODEX_TEST_REMOTE_ENV_TARGET }} --lib unified_exec::tests::remote_exec_server_rejects_inherited_fd_launches -- --exact
cargo test -p codex-core --target ${{ env.CODEX_TEST_REMOTE_ENV_TARGET }} --test all suite::remote_env::remote_test_env_can_connect_and_use_filesystem -- --exact
env:
RUST_BACKTRACE: 1
- 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-${{ runner.os }}-${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}-remote-tests-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }}
- name: Save sccache cache (fallback)
if: always() && !cancelled() && env.SCCACHE_GHA_ENABLED != 'true'
continue-on-error: true
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
with:
path: ${{ github.workspace }}/.sccache/
key: sccache-${{ runner.os }}-${{ env.CODEX_TEST_REMOTE_ENV_TARGET }}-remote-tests-${{ steps.lockhash.outputs.hash }}-${{ github.run_id }}
- name: Tear down remote test env
if: always()
shell: bash
run: |
set +e
if [[ "${{ steps.remote_tests.outcome }}" != "success" ]]; then
docker logs codex-remote-test-env || true
fi
docker rm -f codex-remote-test-env >/dev/null 2>&1 || true

argument_comment_lint_package:
name: Argument comment lint package
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -194,6 +336,7 @@ jobs:
changed,
general,
cargo_shear,
remote_tests_linux,
argument_comment_lint_package,
argument_comment_lint_prebuilt,
]
Expand All @@ -206,6 +349,7 @@ jobs:
echo "argpkg : ${{ needs.argument_comment_lint_package.result }}"
echo "arglint: ${{ needs.argument_comment_lint_prebuilt.result }}"
echo "general: ${{ needs.general.result }}"
echo "remote : ${{ needs.remote_tests_linux.result }}"
echo "shear : ${{ needs.cargo_shear.result }}"

# If nothing relevant changed (PR touching only root README, etc.),
Expand All @@ -226,4 +370,5 @@ jobs:
if [[ '${{ needs.changed.outputs.codex }}' == 'true' || '${{ needs.changed.outputs.workflows }}' == 'true' ]]; then
[[ '${{ needs.general.result }}' == 'success' ]] || { echo 'general failed'; exit 1; }
[[ '${{ needs.cargo_shear.result }}' == 'success' ]] || { echo 'cargo_shear failed'; exit 1; }
[[ '${{ needs.remote_tests_linux.result }}' == 'success' ]] || { echo 'remote_tests_linux failed'; exit 1; }
fi
20 changes: 10 additions & 10 deletions codex-rs/core/tests/suite/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,11 @@ impl ProviderAuthCommandFixture {
fn new(tokens: &[&str]) -> std::io::Result<Self> {
let tempdir = tempfile::tempdir()?;
let tokens_file = tempdir.path().join("tokens.txt");
let token_line_ending = if cfg!(windows) { "\r\n" } else { "\n" };
let mut token_file_contents = String::new();
for token in tokens {
token_file_contents.push_str(token);
token_file_contents.push('\n');
token_file_contents.push_str(token_line_ending);
}
std::fs::write(&tokens_file, token_file_contents)?;

Expand Down Expand Up @@ -200,22 +201,22 @@ mv tokens.next tokens.txt
&script_path,
r#"@echo off
setlocal EnableExtensions DisableDelayedExpansion

set "first_line="
<tokens.txt set /p first_line=
<tokens.txt set /p "first_line="
if not defined first_line exit /b 1

echo(%first_line%
setlocal EnableDelayedExpansion
echo(!first_line!
endlocal
more +1 tokens.txt > tokens.next
move /y tokens.next tokens.txt >nul
"#,
)?;
(
"cmd.exe".to_string(),
vec![
"/D".to_string(),
"/Q".to_string(),
"/C".to_string(),
"/d".to_string(),
"/s".to_string(),
"/c".to_string(),
".\\print-token.cmd".to_string(),
],
)
Expand All @@ -232,8 +233,7 @@ move /y tokens.next tokens.txt >nul
ModelProviderAuthInfo {
command: self.command.clone(),
args: self.args.clone(),
// Match the provider-auth default to avoid brittle shell-startup timing in CI.
timeout_ms: non_zero_u64(/*value*/ 5_000),
timeout_ms: non_zero_u64(/*value*/ 10_000),
refresh_interval_ms: 60_000,
cwd: match codex_utils_absolute_path::AbsolutePathBuf::try_from(self.tempdir.path()) {
Ok(cwd) => cwd,
Expand Down
17 changes: 13 additions & 4 deletions scripts/list-bazel-clippy-targets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${repo_root}"

# Resolve the dynamic targets before printing anything so callers do not
# continue with a partial list if `bazel query` fails.
manual_rust_test_targets="$(bazel query 'kind("rust_test rule", attr(tags, "manual", //codex-rs/... except //codex-rs/v8-poc/...))')"
manual_rust_test_targets=""
if [[ "${RUNNER_OS:-}" != "Windows" ]]; then
# Resolve the dynamic targets before printing anything so callers do not
# continue with a partial list if `bazel query` fails.
#
# The generated manual `*-unit-tests-bin` targets pull in Windows-incompatible
# V8/Python dependencies under gnullvm, so only include them on platforms
# where they currently analyze successfully.
manual_rust_test_targets="$(bazel query 'kind("rust_test rule", attr(tags, "manual", //codex-rs/... except //codex-rs/v8-poc/...))')"
fi

printf '%s\n' \
"//codex-rs/..." \
Expand All @@ -17,4 +24,6 @@ printf '%s\n' \
# underlying `rust_test` binaries. Add the internal manual `*-unit-tests-bin`
# targets explicitly so inline `#[cfg(test)]` code is linted like
# `cargo clippy --tests`.
printf '%s\n' "${manual_rust_test_targets}"
if [[ -n "${manual_rust_test_targets}" ]]; then
printf '%s\n' "${manual_rust_test_targets}"
fi
Loading