Skip to content

Commit c68c0c8

Browse files
sinelawclaude
andcommitted
Use BTreeMap for stable config schema generation
HashMap iteration order is non-deterministic, causing config-schema.json to change between builds even when the source hasn't changed. Switch to BTreeMap for definitions and properties, and sort the required array, to ensure consistent output. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 2b1c7f0 commit c68c0c8

File tree

2 files changed

+265
-264
lines changed

2 files changed

+265
-264
lines changed

build.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! Generates TypeScript type definitions from Rust op definitions
44
//! and JSON Schema for configuration.
55
6-
use std::collections::HashMap;
6+
use std::collections::{BTreeMap, HashMap};
77
use std::fs;
88
use std::path::Path;
99

@@ -1532,7 +1532,7 @@ fn apply_rename_style(name: &str, style: &str) -> String {
15321532
/// Convert Rust type to JSON Schema type
15331533
fn rust_type_to_json_schema(
15341534
rust_type: &str,
1535-
definitions: &HashMap<String, serde_json::Value>,
1535+
definitions: &BTreeMap<String, serde_json::Value>,
15361536
) -> serde_json::Value {
15371537
let rust_type = rust_type.trim();
15381538

@@ -1618,7 +1618,7 @@ fn rust_type_to_json_schema(
16181618

16191619
/// Generate full JSON Schema from extracted structs
16201620
fn generate_json_schema(structs: &[ConfigStructInfo]) -> serde_json::Value {
1621-
let mut definitions: HashMap<String, serde_json::Value> = HashMap::new();
1621+
let mut definitions: BTreeMap<String, serde_json::Value> = BTreeMap::new();
16221622

16231623
// First pass: collect all definition names
16241624
let def_names: std::collections::HashSet<String> =
@@ -1648,12 +1648,12 @@ fn generate_struct_schema(
16481648
struct_info: &ConfigStructInfo,
16491649
def_names: &std::collections::HashSet<String>,
16501650
) -> serde_json::Value {
1651-
let definitions: HashMap<String, serde_json::Value> = def_names
1651+
let definitions: BTreeMap<String, serde_json::Value> = def_names
16521652
.iter()
16531653
.map(|name| (name.clone(), serde_json::json!({})))
16541654
.collect();
16551655

1656-
let mut properties: HashMap<String, serde_json::Value> = HashMap::new();
1656+
let mut properties: BTreeMap<String, serde_json::Value> = BTreeMap::new();
16571657
let mut required: Vec<String> = Vec::new();
16581658

16591659
for field in &struct_info.fields {
@@ -1687,6 +1687,7 @@ fn generate_struct_schema(
16871687
});
16881688

16891689
if !required.is_empty() {
1690+
required.sort();
16901691
schema["required"] = serde_json::json!(required);
16911692
}
16921693

0 commit comments

Comments
 (0)