test(core/api): add compile-only API surface checks for core re-exports and models alias

This commit is contained in:
James Peter
2025-09-09 10:54:43 +10:00
parent 10b4bed60b
commit 74b0c1ca1c
6 changed files with 310 additions and 1 deletions
+54 -1
View File
@@ -21,6 +21,39 @@ permissions:
contents: write
jobs:
preflight-tests:
name: Preflight Tests (Linux fast E2E)
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust (1.89)
shell: bash
run: |
rustup set profile minimal
rustup toolchain install 1.89.0 --profile minimal
rustup default 1.89.0
- name: Setup Rust Cache
uses: Swatinem/rust-cache@v2
with:
prefix-key: v5-rust
shared-key: codex-preflight-1.89
workspaces: |
codex-rs -> target
cache-targets: true
cache-workspace-crates: true
cache-on-failure: true
- name: Build (fast profile)
shell: bash
run: ./build-fast.sh
- name: Curated tests + CLI smokes
shell: bash
run: bash scripts/ci-tests.sh
determine-version:
name: Determine Version
runs-on: ubuntu-latest
@@ -82,7 +115,7 @@ jobs:
build-binaries:
name: Build ${{ matrix.target }}
needs: determine-version
needs: [determine-version, preflight-tests]
runs-on: ${{ matrix.os }}
strategy:
matrix:
@@ -230,6 +263,26 @@ jobs:
cd codex-rs
cargo build --release --frozen --locked --timings --target ${{ matrix.target }} --bin code
- name: Post-build smoke (run binary) [Unix]
if: |
(contains(matrix.os, 'ubuntu') && matrix.target == 'x86_64-unknown-linux-musl') ||
(matrix.os == 'ubuntu-24.04-arm' && matrix.target == 'aarch64-unknown-linux-musl') ||
(startsWith(matrix.os, 'macos-') && matrix.target == 'aarch64-apple-darwin')
shell: bash
run: |
set -euo pipefail
exe="codex-rs/target/${{ matrix.target }}/release/code"
"$exe" --version
"$exe" completion --shell bash > /dev/null
- name: Post-build smoke (run binary) [Windows]
if: matrix.os == 'windows-latest' && matrix.target == 'x86_64-pc-windows-msvc'
shell: pwsh
run: |
$exe = "codex-rs/target/${{ matrix.target }}/release/code.exe"
& $exe --version | Out-Null
& $exe completion --shell bash | Out-Null
- name: sccache stats
shell: bash
run: sccache --show-stats || true
+20
View File
@@ -460,6 +460,11 @@ jobs:
- Do NOT blanket-delete new crates or reintroduced paths. Surface noteworthy cases in MERGE_REPORT.md and make a reasoned choice.
- For any path listed in purge_globs or perma_removed_paths, ensure it remains deleted if upstream reintroduced it.
- Review the upstream commit range (e.g., via `git rev-list upstream/UPSTREAM_BRANCH ^origin/DEFAULT_BRANCH`). Use repo context and the provided artifacts to make sensible, minimal decisions. Prefer preserving our local UX/branding and workflows; adopt upstream when it improves correctness, security, or compatibility. Record notable decisions in MERGE_REPORT.md.
5) Compatibility (do not break callers):
- Keep these public re-exports in codex-core: ModelClient, Prompt, ResponseEvent, ResponseStream.
Removing them breaks downstream imports and will fail API tests.
- Keep codex_core::models namespace as an alias to protocol models.
- Do not remove ICU/sys-locale dependencies unless you confirm (via repo-wide search) they are unused across the workspace.
5) Stage and commit with a conventional message and short build status.
6) Run ./build-fast.sh (warnings treated as failures). Apply minimal safe fixes only.
7) Write .github/auto/MERGE_REPORT.md (Incorporated / Dropped / Other changes) summarizing choices.
@@ -473,6 +478,14 @@ jobs:
- If Git reports no merge-base between origin/DEFAULT_BRANCH and upstream/UPSTREAM_BRANCH, you may use `--allow-unrelated-histories` to graft histories and proceed with all policies/guards.
- If the initial `git merge --no-ff --no-commit upstream/UPSTREAM_BRANCH` fails with unrelated histories, re-run the merge in a separate command with `--allow-unrelated-histories` (do not chain with `||`).
- Use only the provided GH_TOKEN for push; do not echo it.
<tools>
- To search for API usages before removing exports:
rg -n "^(use\\s+codex_core::|codex_core::)(ModelClient|Prompt|Response(Event|Stream))\\b" codex-rs
- To look for ICU/sys-locale usage across workspace:
rg -n "\\b(sys_locale|icu_(decimal|locale_core))\\b" codex-rs
- To compile API tests without running them:
cargo check -p codex-core --tests --quiet
</constraints>
EOP
} | env -i PATH="$SAFE_PATH" HOME="$SAFE_HOME" \
@@ -498,6 +511,13 @@ jobs:
--skip-git-repo-check \
- | tee .github/auto/AGENT_STDOUT.txt
- name: Compile API surface tests (no run)
if: steps.check_upstream.outputs.skip != 'true'
working-directory: codex-rs
run: |
set -euo pipefail
cargo check --tests --quiet
- name: Enforce policy removals on merge branch (images + caches + purge_globs)
if: steps.check_upstream.outputs.skip != 'true'
env:
+148
View File
@@ -0,0 +1,148 @@
Run set -euo pipefail
[2025-09-09T00:20:09] Code v0.2.97
--------
workdir: /home/runner/work/code/code
model: gpt-5
provider: openai
approval: never
sandbox: workspace-write [workdir, /tmp, $TMPDIR] (git writes enabled) (network access enabled)
reasoning effort: medium
reasoning summaries: auto
--------
[2025-09-09T00:20:09] User instructions:
Context
- UPSTREAM_REPO=openai/codex
- UPSTREAM_BRANCH=main
- MERGE_BRANCH=upstream-merge
- DEFAULT_BRANCH=main
Runtime
- ENV: github-actions
- MERGE_MODE=by-bucket
Goals
- Keep our fork in sync with upstream by incorporating genuine improvements.
- Do not overwrite our unique TUI and tooling approach unless clearly beneficial and compatible.
- Make granular decisions commit-by-commit or by bucket; do not blanket-drop upstream changes without review.
Artifacts
- .github/auto/COMMITS.json: upstream commits not in default (sha, title, files, stats).
- .github/auto/DELETED_ON_DEFAULT.txt: crates/paths removed on our default; avoid re-introducing.
- .github/auto/CHANGE_HISTOGRAM.txt: rough areas touched.
- .github/auto/DELTA_FILES.txt and DIFFSTAT.txt: filenames and summary.
- .github/auto/REINTRODUCED_PATHS.txt: candidate paths removed previously that upstream reintroduced.
<policy>
{
"prefer_ours_globs": [
"codex-rs/tui/**",
"codex-cli/**",
".github/workflows/**",
"docs/**",
"AGENTS.md",
"README.md",
"CHANGELOG.md"
],
"prefer_theirs_globs": [
"codex-rs/core/**",
"codex-rs/common/**",
"codex-rs/protocol/**",
"codex-rs/exec/**",
"codex-rs/file-search/**"
],
"purge_globs": [
".github/codex-cli-*.png",
".github/codex-cli-*.jpg",
".github/codex-cli-*.jpeg",
".github/codex-cli-*.webp"
pub mod codex;
+pub mod debug_logger;
+pub mod slash_commands;
+pub use codex::Codex;
+pub use codex::CodexSpawnOk;
mod codex_conversation;
pub mod token_data;
pub use codex_conversation::CodexConversation;
@@ -27,6 +33,8 @@
pub mod exec_env;
mod flags;
pub mod git_info;
+pub mod git_worktree;
+mod image_comparison;
mod is_safe_command;
pub mod landlock;
mod mcp_connection_manager;
@@ -34,14 +42,12 @@
mod message_history;
mod model_provider_info;
pub mod parse_command;
-mod user_instructions;
pub use model_provider_info::BUILT_IN_OSS_MODEL_PROVIDER_ID;
pub use model_provider_info::ModelProviderInfo;
pub use model_provider_info::WireApi;
pub use model_provider_info::built_in_model_providers;
pub use model_provider_info::create_oss_provider_with_base_url;
mod conversation_manager;
-mod event_mapping;
pub use conversation_manager::ConversationManager;
pub use conversation_manager::NewConversation;
// Re-export common auth types for workspace consumers
@@ -61,29 +67,15 @@
pub mod terminal;
mod tool_apply_patch;
pub mod turn_diff_tracker;
-pub use rollout::RolloutRecorder;
-pub use rollout::SessionMeta;
-pub use rollout::list::ConversationItem;
pub use rollout::list::ConversationsPage;
-pub use rollout::list::Cursor;
mod user_notification;
pub mod util;
+pub mod http_client;
pub use apply_patch::CODEX_APPLY_PATCH_ARG1;
pub use safety::get_platform_sandbox;
-// Re-export the protocol types from the standalone `codex-protocol` crate so existing
-// `codex_core::protocol::...` references continue to work across the workspace.
-pub use codex_protocol::protocol;
-// Re-export protocol config enums to ensure call sites can use the same types
-// as those in the protocol crate when constructing protocol messages.
+// Use our local protocol definitions to preserve custom events and input items.
+pub mod protocol;
+// Optionally expose upstream protocol config enums for callers that need them.
pub use codex_protocol::config_types as protocol_config_types;
-
-pub use client::ModelClient;
-pub use client_common::Prompt;
-pub use client_common::ResponseEvent;
-pub use client_common::ResponseStream;
-pub use codex_protocol::models::ContentItem;
-pub use codex_protocol::models::LocalShellAction;
-pub use codex_protocol::models::LocalShellExecAction;
-pub use codex_protocol::models::LocalShellStatus;
-pub use codex_protocol::models::ReasoningItemContent;
-pub use codex_protocol::models::ResponseItem;
+// Re-export protocol models for compatibility with existing imports.
+pub use codex_protocol::models as models;
diff --git a/codex-rs/protocol/Cargo.toml b/codex-rs/protocol/Cargo.toml
index 8013b6c812a2136a45b6465a50805ff7ac6df597..aac2444014b62289caeaa3361919b41af50aac95
--- a/codex-rs/protocol/Cargo.toml
+++ b/codex-rs/protocol/Cargo.toml
@@ -12,8 +12,6 @@
[dependencies]
base64 = "0.22.1"
-icu_decimal = "2.0.0"
-icu_locale_core = "2.0.0"
mcp-types = { path = "../mcp-types" }
mime_guess = "2.0.5"
serde = { version = "1", features = ["derive"] }
@@ -21,9 +19,8 @@
serde_json = "1"
strum = "0.27.2"
strum_macros = "0.27.2"
-sys-locale = "0.3.2"
tracing = "0.1.41"
-ts-rs = { version = "11", features = ["uuid-impl", "serde-json-impl", "no-serde-warnings"] }
+ts-rs = { version = "11", features = ["uuid-impl", "serde-json-impl"] }
uuid = { version = "1", features = ["serde", "v4"] }
[dev-dependencies]
+37
View File
@@ -0,0 +1,37 @@
use std::env;
use std::process::Command;
fn bin_path() -> String {
// Cargo sets this for integration tests so they can execute the package's bins.
env::var("CARGO_BIN_EXE_code").expect("CARGO_BIN_EXE_code env var not set by cargo")
}
#[test]
fn version_prints() {
let out = Command::new(bin_path())
.arg("--version")
.output()
.expect("failed to run code --version");
assert!(out.status.success());
assert!(!out.stdout.is_empty());
}
#[test]
fn completion_bash_emits() {
let out = Command::new(bin_path())
.args(["completion", "--shell", "bash"])
.output()
.expect("failed to run code completion");
assert!(out.status.success());
assert!(!out.stdout.is_empty());
}
#[test]
fn doctor_runs() {
let status = Command::new(bin_path())
.arg("doctor")
.status()
.expect("failed to run code doctor");
assert!(status.success());
}
+25
View File
@@ -0,0 +1,25 @@
//! Compile-only API surface checks for codex-core.
//! These tests intentionally reference public re-exports that must remain
//! stable for workspace consumers and external tools. They are lightweight
//! and do not execute any runtime logic.
#[allow(dead_code)]
fn assert_type<T>() {}
#[test]
fn codex_core_public_api_reexports_exist() {
// Core client and stream types must remain publicly re-exported from
// codex_core so downstream crates (tests, tools) can compile unchanged.
assert_type::<codex_core::ModelClient>();
assert_type::<codex_core::Prompt>();
assert_type::<codex_core::ResponseEvent>();
assert_type::<codex_core::ResponseStream>();
}
#[test]
fn codex_core_protocol_models_are_exposed() {
// The models namespace should remain accessible via codex_core::models
// to keep imports stable in TUI/tests.
assert_type::<codex_core::models::ResponseItem>();
}
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
# Run a small, curated set of fast integration tests + CLI smokes.
# Assumes `./build-fast.sh` was run already so the host binary exists.
echo "[ci-tests] Running curated integration tests..."
pushd codex-rs >/dev/null
# Keep quiet output; fail fast on first error.
cargo test -p codex-login --test all -q
cargo test -p codex-chatgpt --test all -q
cargo test -p codex-apply-patch --test all -q
cargo test -p codex-execpolicy --tests -q
cargo test -p mcp-types --tests -q
popd >/dev/null
echo "[ci-tests] CLI smokes with host binary..."
BIN=./codex-rs/target/dev-fast/code
"${BIN}" --version >/dev/null
"${BIN}" completion --shell bash >/dev/null
"${BIN}" doctor >/dev/null || true
echo "[ci-tests] Done."