11use crate :: test_file:: ProviderOverrides ;
2+ use indexmap:: IndexMap ;
23use serde:: Deserialize ;
3- use std:: collections:: BTreeMap ;
44use std:: path:: Path ;
55
66/// Top-level project configuration loaded from bugatti.config.toml.
@@ -10,7 +10,7 @@ pub struct Config {
1010 #[ serde( default ) ]
1111 pub provider : ProviderConfig ,
1212 #[ serde( default ) ]
13- pub commands : BTreeMap < String , CommandDef > ,
13+ pub commands : IndexMap < String , CommandDef > ,
1414 #[ serde( default ) ]
1515 pub checkpoint : Option < CheckpointConfig > ,
1616}
@@ -196,6 +196,7 @@ pub fn load_config(dir: &Path) -> Result<Config, ConfigError> {
196196mod tests {
197197 use super :: * ;
198198 use crate :: test_file:: { ProviderOverrides , Step , TestFile , TestOverrides } ;
199+ use indexmap:: IndexMap ;
199200 use std:: fs;
200201
201202 #[ test]
@@ -243,6 +244,28 @@ readiness_url = "http://localhost:3000/health"
243244 ) ;
244245 }
245246
247+ #[ test]
248+ fn config_preserves_toml_declaration_order ( ) {
249+ let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
250+ fs:: write (
251+ dir. path ( ) . join ( "bugatti.config.toml" ) ,
252+ r#"
253+ [commands.z_server]
254+ kind = "long_lived"
255+ cmd = "sleep 60"
256+
257+ [commands.a_migrate]
258+ kind = "short_lived"
259+ cmd = "echo migrate"
260+ "# ,
261+ )
262+ . unwrap ( ) ;
263+
264+ let config = load_config ( dir. path ( ) ) . unwrap ( ) ;
265+ let names: Vec < & String > = config. commands . keys ( ) . collect ( ) ;
266+ assert_eq ! ( names, vec![ "z_server" , "a_migrate" ] ) ;
267+ }
268+
246269 #[ test]
247270 fn missing_config_returns_defaults ( ) {
248271 let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
@@ -278,7 +301,7 @@ readiness_url = "http://localhost:3000/health"
278301 strict_warnings : None ,
279302 base_url : None ,
280303 } ,
281- commands : BTreeMap :: new ( ) ,
304+ commands : IndexMap :: new ( ) ,
282305 checkpoint : None ,
283306 } ;
284307 let test_file = TestFile {
@@ -321,7 +344,7 @@ readiness_url = "http://localhost:3000/health"
321344 strict_warnings : None ,
322345 base_url : None ,
323346 } ,
324- commands : BTreeMap :: new ( ) ,
347+ commands : IndexMap :: new ( ) ,
325348 checkpoint : None ,
326349 } ;
327350 let test_file = TestFile {
@@ -360,7 +383,7 @@ readiness_url = "http://localhost:3000/health"
360383 strict_warnings : None ,
361384 base_url : None ,
362385 } ,
363- commands : BTreeMap :: new ( ) ,
386+ commands : IndexMap :: new ( ) ,
364387 checkpoint : None ,
365388 } ;
366389 let test_file = TestFile {
@@ -419,7 +442,7 @@ step_timeout_secs = 600
419442 step_timeout_secs : Some ( 300 ) ,
420443 ..ProviderConfig :: default ( )
421444 } ,
422- commands : BTreeMap :: new ( ) ,
445+ commands : IndexMap :: new ( ) ,
423446 checkpoint : None ,
424447 } ;
425448 let test_file = TestFile {
@@ -445,7 +468,7 @@ step_timeout_secs = 600
445468 step_timeout_secs : Some ( 300 ) ,
446469 ..ProviderConfig :: default ( )
447470 } ,
448- commands : BTreeMap :: new ( ) ,
471+ commands : IndexMap :: new ( ) ,
449472 checkpoint : None ,
450473 } ;
451474 let test_file = TestFile {
@@ -487,7 +510,7 @@ strict_warnings = true
487510 strict_warnings : Some ( true ) ,
488511 ..ProviderConfig :: default ( )
489512 } ,
490- commands : BTreeMap :: new ( ) ,
513+ commands : IndexMap :: new ( ) ,
491514 checkpoint : None ,
492515 } ;
493516 let test_file = TestFile {
@@ -533,7 +556,7 @@ base_url = "http://localhost:3000"
533556 base_url : Some ( "http://localhost:3000" . to_string ( ) ) ,
534557 ..ProviderConfig :: default ( )
535558 } ,
536- commands : BTreeMap :: new ( ) ,
559+ commands : IndexMap :: new ( ) ,
537560 checkpoint : None ,
538561 } ;
539562 let test_file = TestFile {
@@ -562,7 +585,7 @@ base_url = "http://localhost:3000"
562585 base_url : Some ( "http://localhost:3000" . to_string ( ) ) ,
563586 ..ProviderConfig :: default ( )
564587 } ,
565- commands : BTreeMap :: new ( ) ,
588+ commands : IndexMap :: new ( ) ,
566589 checkpoint : None ,
567590 } ;
568591 let test_file = TestFile {
0 commit comments