Skip to content

Commit 31125c4

Browse files
committed
mv regen to bin, add seperate ci step, compare actual json, docs
1 parent 15d1235 commit 31125c4

File tree

10 files changed

+77
-50
lines changed

10 files changed

+77
-50
lines changed

.github/workflows/rust-ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ jobs:
6666
run: cargo fmt -- --config imports_granularity=Item --check
6767
- name: Verify codegen for mcp-types
6868
run: ./mcp-types/check_lib_rs.py
69+
- name: Verify config schema fixture
70+
run: |
71+
cargo run -p codex-core --bin codex-write-config-schema
72+
git diff --exit-code core/config.schema.json
6973
7074
cargo_shear:
7175
name: cargo shear

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ In the codex-rs folder where the rust code lives:
1313
- Use method references over closures when possible per https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
1414
- When writing tests, prefer comparing the equality of entire objects over fields one by one.
1515
- When making a change that adds or changes an API, ensure that the documentation in the `docs/` folder is up to date if applicable.
16+
- If you change `ConfigToml` or nested config types, run `just write-config-schema` to update `codex-rs/core/config.schema.json`.
1617

1718
Run `just fmt` (in `codex-rs` directory) automatically after making Rust code changes; do not ask for approval to run it. Before finalizing a change to `codex-rs`, run `just fix -p <project>` (in `codex-rs` directory) to fix any linter issues in the code. Prefer scoping with `-p` to avoid slow workspace‑wide Clippy builds; only run `just fix` without `-p` if you changed shared crates. Additionally, run the tests:
1819

codex-rs/core/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ doctest = false
99
name = "codex_core"
1010
path = "src/lib.rs"
1111

12+
[[bin]]
13+
name = "codex-write-config-schema"
14+
path = "src/bin/config_schema.rs"
15+
1216
[lints]
1317
workspace = true
1418

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use anyhow::Context;
2+
use anyhow::Result;
3+
use std::env;
4+
use std::path::PathBuf;
5+
6+
/// Generate the JSON Schema for `config.toml` and write it to `config.schema.json`.
7+
fn main() -> Result<()> {
8+
let mut args = env::args().skip(1);
9+
let mut out_path = None;
10+
11+
while let Some(arg) = args.next() {
12+
match arg.as_str() {
13+
"--out" | "-o" => {
14+
let value = args.next().context("expected a path after --out/-o")?;
15+
out_path = Some(PathBuf::from(value));
16+
}
17+
_ => anyhow::bail!("unknown argument: {arg}"),
18+
}
19+
}
20+
21+
let out_path = out_path
22+
.unwrap_or_else(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("config.schema.json"));
23+
codex_core::config::schema::write_config_schema(&out_path)?;
24+
Ok(())
25+
}

codex-rs/core/src/config/SCHEMA.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
# Config JSON Schema
22

33
We generate a JSON Schema for `~/.codex/config.toml` from the `ConfigToml` type
4-
and commit it at `docs/config.schema.json` for editor integration.
4+
and commit it at `codex-rs/core/config.schema.json` for editor integration.
55

66
When you change any fields included in `ConfigToml` (or nested config types),
7-
regenerate the schema and update the fixture:
7+
regenerate the schema:
88

99
```
1010
just write-config-schema
11-
cargo test -p codex-core config_schema_matches_fixture
1211
```

codex-rs/core/src/config/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ pub fn set_default_oss_provider(codex_home: &Path, provider: &str) -> std::io::R
684684
}
685685

686686
/// Base config deserialized from ~/.codex/config.toml.
687-
// The JSON Schema in `docs/config.schema.json` is generated from this struct.
687+
// The JSON Schema in `codex-rs/core/config.schema.json` is generated from this struct.
688688
// If you add, remove, or rename fields, regenerate the schema via
689689
// `just write-config-schema` and update the fixture test.
690690
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, JsonSchema)]

codex-rs/core/src/config/schema.rs

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,15 @@
1-
#[cfg(test)]
21
use crate::config::ConfigToml;
32
use crate::config::types::RawMcpServerConfig;
43
use crate::features::FEATURES;
54
use schemars::r#gen::SchemaGenerator;
6-
#[cfg(test)]
75
use schemars::r#gen::SchemaSettings;
86
use schemars::schema::InstanceType;
97
use schemars::schema::ObjectValidation;
10-
#[cfg(test)]
118
use schemars::schema::RootSchema;
129
use schemars::schema::Schema;
1310
use schemars::schema::SchemaObject;
14-
#[cfg(test)]
1511
use std::path::Path;
1612

17-
/// Build the config schema used by the fixture test.
18-
#[cfg(test)]
19-
pub(crate) fn config_schema() -> RootSchema {
20-
SchemaSettings::draft07()
21-
.with(|settings| {
22-
settings.option_add_null_type = false;
23-
})
24-
.into_generator()
25-
.into_root_schema_for::<ConfigToml>()
26-
}
27-
28-
/// Write the config schema fixture to disk.
29-
#[cfg(test)]
30-
pub(crate) fn write_config_schema(out_path: &Path) -> anyhow::Result<()> {
31-
let schema = config_schema();
32-
let json = serde_json::to_vec_pretty(&schema)?;
33-
std::fs::write(out_path, json)?;
34-
Ok(())
35-
}
36-
3713
/// Schema for the `[features]` map with known + legacy keys only.
3814
pub(crate) fn features_schema(schema_gen: &mut SchemaGenerator) -> Schema {
3915
let mut object = SchemaObject {
@@ -74,32 +50,50 @@ pub(crate) fn mcp_servers_schema(schema_gen: &mut SchemaGenerator) -> Schema {
7450
Schema::Object(object)
7551
}
7652

53+
/// Build the config schema for `config.toml`.
54+
pub fn config_schema() -> RootSchema {
55+
SchemaSettings::draft07()
56+
.with(|settings| {
57+
settings.option_add_null_type = false;
58+
})
59+
.into_generator()
60+
.into_root_schema_for::<ConfigToml>()
61+
}
62+
63+
/// Render the config schema as pretty-printed JSON.
64+
pub fn config_schema_json() -> anyhow::Result<Vec<u8>> {
65+
let schema = config_schema();
66+
let json = serde_json::to_vec_pretty(&schema)?;
67+
Ok(json)
68+
}
69+
70+
/// Write the config schema fixture to disk.
71+
pub fn write_config_schema(out_path: &Path) -> anyhow::Result<()> {
72+
let json = config_schema_json()?;
73+
std::fs::write(out_path, json)?;
74+
Ok(())
75+
}
76+
7777
#[cfg(test)]
7878
mod tests {
79-
use super::*;
80-
use pretty_assertions::assert_eq;
79+
use super::config_schema_json;
80+
use similar::TextDiff;
8181

8282
#[test]
8383
fn config_schema_matches_fixture() {
84-
let schema = config_schema();
85-
let schema_value = serde_json::to_value(schema).expect("serialize config schema");
86-
let fixture_path = codex_utils_cargo_bin::find_resource!("../../docs/config.schema.json")
84+
let fixture_path = codex_utils_cargo_bin::find_resource!("config.schema.json")
8785
.expect("resolve config schema fixture path");
8886
let fixture = std::fs::read_to_string(fixture_path).expect("read config schema fixture");
89-
let fixture_value: serde_json::Value =
90-
serde_json::from_str(&fixture).expect("parse config schema fixture");
91-
assert_eq!(
92-
fixture_value, schema_value,
93-
"Current schema for `config.toml` doesn't match the fixture. Run `just write-config-schema` to overwrite with your changes."
94-
);
95-
}
96-
97-
/// Overwrite the config schema fixture with the current schema.
98-
#[test]
99-
#[ignore]
100-
fn write_config_schema_fixture() {
101-
let fixture_path = codex_utils_cargo_bin::find_resource!("../../docs/config.schema.json")
102-
.expect("resolve config schema fixture path");
103-
write_config_schema(&fixture_path).expect("write config schema fixture");
87+
let schema_json = config_schema_json().expect("serialize config schema");
88+
let schema_str = String::from_utf8(schema_json).expect("decode schema json");
89+
if fixture != schema_str {
90+
let diff = TextDiff::from_lines(&fixture, &schema_str)
91+
.unified_diff()
92+
.to_string();
93+
let short = diff.lines().take(50).collect::<Vec<_>>().join("\n");
94+
panic!(
95+
"Current schema for `config.toml` doesn't match the fixture. Run `just write-config-schema` to overwrite with your changes.\n\n{short}"
96+
);
97+
}
10498
}
10599
}

docs/config.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ Codex can run a notification hook when the agent finishes a turn. See the config
2020

2121
## JSON Schema
2222

23-
The generated JSON Schema for `config.toml` lives at `docs/config.schema.json`.
23+
The generated JSON Schema for `config.toml` lives at `codex-rs/core/config.schema.json`.

justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,4 @@ mcp-server-run *args:
5959

6060
# Regenerate the json schema for config.toml from the current config types.
6161
write-config-schema:
62-
cargo test -p codex-core write_config_schema_fixture -- --ignored
62+
cargo run -p codex-core --bin codex-write-config-schema

0 commit comments

Comments
 (0)