Skip to content

chore: cleanup Config instantiation codepaths#8226

Merged
bolinfest merged 1 commit intomainfrom
pr8225
Dec 18, 2025
Merged

chore: cleanup Config instantiation codepaths#8226
bolinfest merged 1 commit intomainfrom
pr8225

Conversation

@bolinfest
Copy link
Copy Markdown
Collaborator

@bolinfest bolinfest commented Dec 18, 2025

This PR does various types of cleanup before I can proceed with more ambitious changes to config loading.

First, I noticed duplicated code across these two methods:

let root_value = load_resolved_config(
&codex_home,
cli_overrides,
crate::config_loader::LoaderOverrides::default(),
)
.await?;
let cfg = deserialize_config_toml_with_base(root_value, &codex_home).map_err(|e| {
tracing::error!("Failed to deserialize overridden config: {e}");
e
})?;

let root_value = load_resolved_config(
codex_home,
cli_overrides,
crate::config_loader::LoaderOverrides::default(),
)
.await?;
let cfg = deserialize_config_toml_with_base(root_value, codex_home).map_err(|e| {
tracing::error!("Failed to deserialize overridden config: {e}");
e
})?;

This has now been consolidated in load_config_as_toml_with_cli_overrides().

Further, I noticed that Config::load_with_cli_overrides() took two similar arguments:

pub async fn load_with_cli_overrides(
cli_overrides: Vec<(String, TomlValue)>,
overrides: ConfigOverrides,
) -> std::io::Result<Self> {

The difference between cli_overrides and overrides was not immediately obvious to me. At first glance, it appears that one should be able to be expressed in terms of the other, but it turns out that some fields of ConfigOverrides (such as cwd and codex_linux_sandbox_exe) are, by design, not configurable via a .toml file or a command-line --config flag.

That said, I discovered that many callers of Config::load_with_cli_overrides() were passing ConfigOverrides::default() for overrides, so I created two separate methods:

  • Config::load_with_cli_overrides(cli_overrides: Vec<(String, TomlValue)>)
  • Config::load_with_cli_overrides_and_harness_overrides(cli_overrides: Vec<(String, TomlValue)>, harness_overrides: ConfigOverrides)

The latter has a long name, as it is not what should be used in the common case, so the extra typing is designed to draw attention to this fact. I tried to update the existing callsites to use the shorter name, where possible.

Further, in the cases where ConfigOverrides is used, usually only a limited subset of fields are actually set, so I updated the declarations to leverage ..Default::default() where possible.


/// DEPRECATED: Use [Config::load_with_cli_overrides()] instead because this
/// codepath is not guaranteed to honor [ConfigRequirements].
pub async fn load_config_as_toml_with_cli_overrides(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load_config_as_toml_with_cli_overrides is returning ConfigToml while load_with_cli_overrides returns Config. How are they substituting each other?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also what is [ConfigRequirements]

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, some of this came from my in-flight PR that I have stacked on top and then I split it out to create a smaller PR.

ConfigRequirements is a new abstraction we are introducing to ensure enterprise-level restrictions are enforced when creating a Config.

Admittedly, one is not a substitute for the other, but the higher-level goal is that callers should generally never work with ConfigToml directly, only a fully-instantiated Config, because using a raw ConfigToml runs the risk that you are using a value where ConfigRequirements have not been enforced.

impl Config {
/// Meant to be used exclusively for tests: `load_with_overrides()` should
/// be used in all other cases.
/// Meant to be used exclusively for tests:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment always confused me. It's saying exclusive for tests but it's used in normal code and doesn't have cfg test around it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know...the problem is that it needs to access things that are private to this file, but we also need to make it available to integration tests. Adding #[cfg(test)] would make it so it is not available to integration tests, so we're kinda stuck.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some places in the code is using #[cfg(any(test, feature = "test-support"))] not sure if this is possible here. we probably have core tests that are using it. It's still being used in non tests load_with_cli_overrides and load_with_cli_overrides_and_harness_overrides. Is this expected?

@bolinfest bolinfest merged commit a879701 into main Dec 18, 2025
69 of 73 checks passed
@bolinfest bolinfest deleted the pr8225 branch December 18, 2025 02:01
@github-actions github-actions bot locked and limited conversation to collaborators Dec 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants