Remove deterministic_process_ids feature to avoid duplicate codex-core builds (#11393)
## Why `codex-core` enabled `deterministic_process_ids` through a self dev-dependency. That forced a second feature-resolved build of the same crate, which increased compile time and test latency. ## What Changed - Removed the `deterministic_process_ids` feature from `codex-rs/core/Cargo.toml`. - Removed the self dev-dependency on `codex-core` that enabled that feature. - Removed the Bazel `deterministic_process_ids` crate feature for `codex-core`. - Added a test-only `AtomicBool` override in unified exec process-id allocation. - Added a test-support setter for that override and re-exported it from `codex-core`. - Enabled deterministic process IDs in integration tests via `core_test_support` ctor. ## Behavior - Production behavior remains random process IDs. - Unit tests remain deterministic via `cfg(test)`. - Integration tests remain deterministic via explicit test-support initialization. ## Validation - `just fmt` - `cargo test -p codex-core unified_exec::` - `cargo test -p codex-core --test all unified_exec -- --test-threads=1` - `cargo tree -p codex-core -e features` (verified the removed feature path)
This commit is contained in:
parent
8b46c0ce00
commit
b68a84ee8e
8 changed files with 47 additions and 10 deletions
2
codex-rs/Cargo.lock
generated
2
codex-rs/Cargo.lock
generated
|
|
@ -1660,7 +1660,6 @@ dependencies = [
|
|||
"codex-arg0",
|
||||
"codex-async-utils",
|
||||
"codex-client",
|
||||
"codex-core",
|
||||
"codex-execpolicy",
|
||||
"codex-file-search",
|
||||
"codex-git",
|
||||
|
|
@ -2639,6 +2638,7 @@ dependencies = [
|
|||
"codex-protocol",
|
||||
"codex-utils-absolute-path",
|
||||
"codex-utils-cargo-bin",
|
||||
"ctor 0.6.3",
|
||||
"futures",
|
||||
"notify",
|
||||
"pretty_assertions",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ codex_rust_crate(
|
|||
# TODO(mbolin): Eliminate the use of features in the version of the
|
||||
# rust_library() that is used by rust_binary() rules for release artifacts
|
||||
# such as the Codex CLI.
|
||||
crate_features = ["deterministic_process_ids", "test-support"],
|
||||
crate_features = ["test-support"],
|
||||
compile_data = glob(
|
||||
include = ["**"],
|
||||
exclude = [
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ wildmatch = { workspace = true }
|
|||
zip = { workspace = true }
|
||||
|
||||
[features]
|
||||
deterministic_process_ids = []
|
||||
test-support = []
|
||||
|
||||
|
||||
|
|
@ -150,9 +149,6 @@ keyring = { workspace = true, features = ["sync-secret-service"] }
|
|||
assert_cmd = { workspace = true }
|
||||
assert_matches = { workspace = true }
|
||||
codex-arg0 = { workspace = true }
|
||||
codex-core = { path = ".", default-features = false, features = [
|
||||
"deterministic_process_ids",
|
||||
] }
|
||||
codex-otel = { workspace = true, features = [
|
||||
"disable-default-metrics-exporter",
|
||||
] }
|
||||
|
|
|
|||
|
|
@ -145,6 +145,8 @@ pub use file_watcher::FileWatcherEvent;
|
|||
pub use safety::get_platform_sandbox;
|
||||
pub use tools::spec::parse_tool_input_schema;
|
||||
pub use turn_metadata::build_turn_metadata_header;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub use unified_exec::set_deterministic_process_ids_for_tests;
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ mod head_tail_buffer;
|
|||
mod process;
|
||||
mod process_manager;
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn set_deterministic_process_ids_for_tests(enabled: bool) {
|
||||
process_manager::set_deterministic_process_ids_for_tests(enabled);
|
||||
}
|
||||
|
||||
pub(crate) use errors::UnifiedExecError;
|
||||
pub(crate) use process::UnifiedExecProcess;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use std::collections::HashSet;
|
|||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use tokio::sync::Notify;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::time::Duration;
|
||||
|
|
@ -61,6 +62,32 @@ const UNIFIED_EXEC_ENV: [(&str, &str); 10] = [
|
|||
("CODEX_CI", "1"),
|
||||
];
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
/// Test-only override for deterministic unified exec process IDs.
|
||||
///
|
||||
/// In production builds this value should remain at its default (`false`) and
|
||||
/// must not be toggled.
|
||||
static FORCE_DETERMINISTIC_PROCESS_IDS: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub(super) fn set_deterministic_process_ids_for_tests(enabled: bool) {
|
||||
FORCE_DETERMINISTIC_PROCESS_IDS.store(enabled, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
fn deterministic_process_ids_forced_for_tests() -> bool {
|
||||
FORCE_DETERMINISTIC_PROCESS_IDS.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
#[cfg(not(any(test, feature = "test-support")))]
|
||||
fn deterministic_process_ids_forced_for_tests() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn should_use_deterministic_process_ids() -> bool {
|
||||
cfg!(test) || deterministic_process_ids_forced_for_tests()
|
||||
}
|
||||
|
||||
fn apply_unified_exec_env(mut env: HashMap<String, String>) -> HashMap<String, String> {
|
||||
for (key, value) in UNIFIED_EXEC_ENV {
|
||||
env.insert(key.to_string(), value.to_string());
|
||||
|
|
@ -85,10 +112,7 @@ impl UnifiedExecProcessManager {
|
|||
loop {
|
||||
let mut store = self.process_store.lock().await;
|
||||
|
||||
let process_id = if !cfg!(test) && !cfg!(feature = "deterministic_process_ids") {
|
||||
// production mode → random
|
||||
rand::rng().random_range(1_000..100_000).to_string()
|
||||
} else {
|
||||
let process_id = if should_use_deterministic_process_ids() {
|
||||
// test or deterministic mode
|
||||
let next = store
|
||||
.reserved_process_ids
|
||||
|
|
@ -99,6 +123,9 @@ impl UnifiedExecProcessManager {
|
|||
.unwrap_or(1000);
|
||||
|
||||
next.to_string()
|
||||
} else {
|
||||
// production mode → random
|
||||
rand::rng().random_range(1_000..100_000).to_string()
|
||||
};
|
||||
|
||||
if store.reserved_process_ids.contains(&process_id) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ codex-core = { workspace = true, features = ["test-support"] }
|
|||
codex-protocol = { workspace = true }
|
||||
codex-utils-absolute-path = { workspace = true }
|
||||
codex-utils-cargo-bin = { workspace = true }
|
||||
ctor = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
notify = { workspace = true }
|
||||
regex-lite = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#![expect(clippy::expect_used)]
|
||||
|
||||
use codex_utils_cargo_bin::CargoBinError;
|
||||
use ctor::ctor;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use codex_core::CodexThread;
|
||||
|
|
@ -17,6 +18,11 @@ pub mod streaming_sse;
|
|||
pub mod test_codex;
|
||||
pub mod test_codex_exec;
|
||||
|
||||
#[ctor]
|
||||
fn enable_deterministic_unified_exec_process_ids_for_tests() {
|
||||
codex_core::set_deterministic_process_ids_for_tests(true);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn assert_regex_match<'s>(pattern: &str, actual: &'s str) -> regex_lite::Captures<'s> {
|
||||
let regex = Regex::new(pattern).unwrap_or_else(|err| {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue