Skip to content

Commit d1f85bf

Browse files
authored
Merge pull request #7863 from Extra-Chill/refactor/consolidate-lab-dispatch-projection
Consolidate Lab dispatch projection
2 parents ef8a2c4 + a0fd4e0 commit d1f85bf

13 files changed

Lines changed: 116 additions & 199 deletions

File tree

src/command_contract/lab.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,8 @@ pub const RUNNER_ARTIFACT_MANIFEST_SCHEMA: &str = crate::core::artifacts::ARTIFA
4141
pub const RUNNER_ARTIFACT_MANIFEST_FILE: &str = crate::core::artifacts::ARTIFACT_MANIFEST_FILE;
4242
pub const RUNNER_ARTIFACT_ROOT_DIR_SUFFIX: &str = "-homeboy-artifacts";
4343

44-
/// Routing-policy flags shared by every Lab command representation
45-
/// (`LabCommandContract`, `LabRoutePlan`, `LabOffloadCommand`). These four
46-
/// booleans travel together as one cohesive policy as a command is resolved
47-
/// from its contract into a route plan and finally an offload command, so they
48-
/// live in a single embedded struct rather than being duplicated field-by-field
49-
/// across the three layers.
44+
/// Routing-policy flags owned by the Lab command contract and retained through
45+
/// route planning, offload, and runner dispatch.
5046
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
5147
pub struct LabRoutingPolicy {
5248
/// Whether the command offloads to a default Lab runner without an explicit
@@ -1075,6 +1071,10 @@ pub(super) fn apply_lab_contract_to_descriptor(
10751071
}
10761072

10771073
impl LabCommandContract {
1074+
pub const fn is_portable(self) -> bool {
1075+
matches!(self.portability, LabCommandPortability::Portable)
1076+
}
1077+
10781078
pub(crate) fn into_route_contract(
10791079
self,
10801080
required_extensions: Vec<String>,

src/commands/infra/route.rs

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ fn strip_component_target_args(
10861086
mod tests {
10871087
use super::*;
10881088
use clap::Parser;
1089-
use homeboy::command_contract::lab_runner_supports_contract_label;
1089+
use homeboy::command_contract::{lab_runner_supports_contract_label, LabCommandPortability};
10901090
use std::fs;
10911091
use std::path::Path;
10921092
use std::sync::{Mutex, MutexGuard, OnceLock};
@@ -1228,8 +1228,7 @@ mod tests {
12281228
let command = lab_offload_command(&cli.command).unwrap().unwrap();
12291229

12301230
assert_eq!(command.hot_label, "review lint");
1231-
assert!(command.portable);
1232-
assert!(command.unsupported_reason.is_none());
1231+
assert!(command.is_portable());
12331232
}
12341233

12351234
#[test]
@@ -1278,8 +1277,7 @@ mod tests {
12781277
let command = lab_offload_command(&cli.command).unwrap().unwrap();
12791278

12801279
assert_eq!(command.hot_label, "review lint");
1281-
assert!(command.portable);
1282-
assert!(command.unsupported_reason.is_none());
1280+
assert!(command.is_portable());
12831281
}
12841282

12851283
#[test]
@@ -1331,8 +1329,7 @@ mod tests {
13311329

13321330
assert_eq!(cli.runner.as_deref(), Some("homeboy-lab"));
13331331
assert_eq!(command.hot_label, "review test");
1334-
assert!(command.portable);
1335-
assert!(command.unsupported_reason.is_none());
1332+
assert!(command.is_portable());
13361333
}
13371334

13381335
#[test]
@@ -1977,7 +1974,7 @@ mod tests {
19771974
let command = lab_offload_command(&cli.command).unwrap().unwrap();
19781975

19791976
assert_eq!(command.hot_label, "rig check");
1980-
assert!(command.portable);
1977+
assert!(command.is_portable());
19811978
assert!(!command.routing_policy.default_lab_offload);
19821979
assert!(!command.routing_policy.infer_source_path_tools);
19831980
assert!(cli.command.supports_lab_runner());
@@ -2018,7 +2015,7 @@ mod tests {
20182015
let command = lab_offload_command(&cli.command).unwrap().unwrap();
20192016

20202017
assert_eq!(command.hot_label, "rig check");
2021-
assert!(command.portable);
2018+
assert!(command.is_portable());
20222019
assert!(command.routing_policy.default_lab_offload);
20232020
assert!(!command.routing_policy.infer_source_path_tools);
20242021
}
@@ -2030,8 +2027,7 @@ mod tests {
20302027
let command = lab_offload_command(&cli.command).unwrap().unwrap();
20312028

20322029
assert_eq!(command.hot_label, "review lint");
2033-
assert!(command.portable);
2034-
assert!(command.unsupported_reason.is_none());
2030+
assert!(command.is_portable());
20352031
assert!(command.routing_policy.requires_extension_parity);
20362032
}
20372033

@@ -2049,9 +2045,8 @@ mod tests {
20492045
let command = lab_offload_command(&cli.command).unwrap().unwrap();
20502046

20512047
assert_eq!(command.hot_label, "extension update");
2052-
assert!(command.portable);
2048+
assert!(command.is_portable());
20532049
assert!(!command.routing_policy.default_lab_offload);
2054-
assert!(command.unsupported_reason.is_none());
20552050
assert!(!command.routing_policy.requires_extension_parity);
20562051
assert!(command.required_extensions.is_empty());
20572052
assert!(!command.routing_policy.infer_source_path_tools);
@@ -2076,9 +2071,8 @@ mod tests {
20762071
let command = lab_offload_command(&cli.command).unwrap().unwrap();
20772072

20782073
assert_eq!(command.hot_label, "extension refresh");
2079-
assert!(command.portable);
2074+
assert!(command.is_portable());
20802075
assert!(!command.routing_policy.default_lab_offload);
2081-
assert!(command.unsupported_reason.is_none());
20822076
assert!(!command.routing_policy.requires_extension_parity);
20832077
assert!(command.required_extensions.is_empty());
20842078
assert!(!command.routing_policy.infer_source_path_tools);
@@ -2117,9 +2111,8 @@ mod tests {
21172111
let command = lab_offload_command(&cli.command).unwrap().unwrap();
21182112

21192113
assert_eq!(command.hot_label, "extension show");
2120-
assert!(command.portable);
2114+
assert!(command.is_portable());
21212115
assert!(!command.routing_policy.default_lab_offload);
2122-
assert!(command.unsupported_reason.is_none());
21232116
assert!(!command.routing_policy.requires_extension_parity);
21242117
assert!(command.required_extensions.is_empty());
21252118
assert!(!command.routing_policy.infer_source_path_tools);
@@ -2150,7 +2143,7 @@ mod tests {
21502143
assert!(local_policy.deny_local_execution());
21512144
assert_eq!(command.hot_label, "fuzz doctor");
21522145
assert!(lab_runner_supports_contract_label(command.hot_label));
2153-
assert!(command.portable);
2146+
assert!(command.is_portable());
21542147
assert!(!command.routing_policy.default_lab_offload);
21552148
assert!(command.routing_policy.requires_extension_parity);
21562149
assert!(command.routing_policy.read_only_polling);
@@ -2372,7 +2365,7 @@ mod tests {
23722365

23732366
assert_eq!(cli.runner.as_deref(), Some("homeboy-lab"));
23742367
assert!(lab_runner_supports_contract_label(command.hot_label));
2375-
assert!(command.portable);
2368+
assert!(command.is_portable());
23762369
assert!(command.routing_policy.default_lab_offload);
23772370
}
23782371
}
@@ -2391,7 +2384,7 @@ mod tests {
23912384
"cargo test --locked",
23922385
]);
23932386
let automatic_command = lab_offload_command(&automatic.command).unwrap().unwrap();
2394-
assert!(automatic_command.portable);
2387+
assert!(automatic_command.is_portable());
23952388
assert!(automatic_command.routing_policy.default_lab_offload);
23962389

23972390
let explicit = Cli::parse_from([
@@ -2409,7 +2402,7 @@ mod tests {
24092402
]);
24102403
let explicit_command = lab_offload_command(&explicit.command).unwrap().unwrap();
24112404
assert_eq!(explicit.runner.as_deref(), Some("homeboy-lab"));
2412-
assert!(explicit_command.portable);
2405+
assert!(explicit_command.is_portable());
24132406

24142407
let lab_only = Cli::parse_from([
24152408
"homeboy",
@@ -2428,12 +2421,10 @@ mod tests {
24282421
lab_only.allow_local_fallback,
24292422
lab_only.lab_only,
24302423
);
2431-
assert!(
2432-
lab_offload_command(&lab_only.command)
2433-
.unwrap()
2434-
.unwrap()
2435-
.portable
2436-
);
2424+
assert!(lab_offload_command(&lab_only.command)
2425+
.unwrap()
2426+
.unwrap()
2427+
.is_portable());
24372428
assert!(local_policy.deny_local_execution());
24382429
}
24392430

@@ -2451,7 +2442,7 @@ mod tests {
24512442

24522443
assert_eq!(cli.runner.as_deref(), Some("homeboy-lab"));
24532444
assert!(lab_runner_supports_contract_label(command.hot_label));
2454-
assert!(command.portable);
2445+
assert!(command.is_portable());
24552446
assert!(!command.routing_policy.default_lab_offload);
24562447
assert!(!command.routing_policy.requires_extension_parity);
24572448
assert!(command.required_extensions.is_empty());
@@ -2486,7 +2477,7 @@ mod tests {
24862477
command.hot_label,
24872478
"agent-task controller from-spec --resume/run-from-spec/materialize"
24882479
);
2489-
assert!(command.portable);
2480+
assert!(command.is_portable());
24902481
assert!(command.routing_policy.default_lab_offload);
24912482
assert!(!command.routing_policy.requires_extension_parity);
24922483
assert_eq!(
@@ -2536,7 +2527,7 @@ mod tests {
25362527
command.hot_label,
25372528
"agent-task controller from-spec --resume/run-from-spec/materialize"
25382529
);
2539-
assert!(command.portable);
2530+
assert!(command.is_portable());
25402531
assert!(command.routing_policy.default_lab_offload);
25412532
assert!(command.routing_policy.infer_source_path_tools);
25422533
assert!(!command.routing_policy.requires_extension_parity);
@@ -2604,7 +2595,7 @@ mod tests {
26042595
assert_eq!(cli.runner.as_deref(), Some("homeboy-lab"));
26052596
assert!(local_policy.deny_local_execution());
26062597
assert_eq!(command.hot_label, "agent-task fanout run-plan");
2607-
assert!(command.portable);
2598+
assert!(command.is_portable());
26082599
assert!(command.routing_policy.default_lab_offload);
26092600
assert!(command.routing_policy.requires_extension_parity);
26102601
}
@@ -2638,7 +2629,7 @@ mod tests {
26382629
assert_eq!(cli.runner.as_deref(), Some("homeboy-lab"));
26392630
assert!(local_policy.deny_local_execution());
26402631
assert_eq!(command.hot_label, "agent-task fanout cook-batch");
2641-
assert!(command.portable);
2632+
assert!(command.is_portable());
26422633
assert!(command.routing_policy.default_lab_offload);
26432634
assert!(command.routing_policy.requires_extension_parity);
26442635
}
@@ -2671,7 +2662,7 @@ mod tests {
26712662

26722663
assert_eq!(cli.runner.as_deref(), Some("homeboy-lab"));
26732664
assert_eq!(command.hot_label, "agent-task fanout status/artifacts");
2674-
assert!(command.portable);
2665+
assert!(command.is_portable());
26752666
assert!(!command.routing_policy.default_lab_offload);
26762667
assert_eq!(
26772668
command.source_path_mode,
@@ -2707,7 +2698,7 @@ mod tests {
27072698

27082699
assert_eq!(cli.runner.as_deref(), Some("homeboy-lab"));
27092700
assert_eq!(command.hot_label, "tunnel service start");
2710-
assert!(command.portable);
2701+
assert!(command.is_portable());
27112702
assert!(!command.routing_policy.default_lab_offload);
27122703
assert_eq!(
27132704
command.source_path_mode,
@@ -2740,7 +2731,7 @@ mod tests {
27402731
let command = lab_offload_command(&cli.command).unwrap().unwrap();
27412732

27422733
assert_eq!(command.hot_label, "tunnel preview-consumer run");
2743-
assert!(command.portable);
2734+
assert!(command.is_portable());
27442735
assert!(!command.routing_policy.default_lab_offload);
27452736
}
27462737

@@ -2751,8 +2742,7 @@ mod tests {
27512742
let command = lab_offload_command(&cli.command).unwrap().unwrap();
27522743

27532744
assert_eq!(command.hot_label, "review audit");
2754-
assert!(command.portable);
2755-
assert_eq!(command.unsupported_reason, None);
2745+
assert!(command.is_portable());
27562746
assert!(command.routing_policy.requires_extension_parity);
27572747
}
27582748

@@ -2763,8 +2753,7 @@ mod tests {
27632753
let command = lab_offload_command(&cli.command).unwrap().unwrap();
27642754

27652755
assert_eq!(command.hot_label, "review audit");
2766-
assert!(command.portable);
2767-
assert_eq!(command.unsupported_reason, None);
2756+
assert!(command.is_portable());
27682757
assert!(command.routing_policy.requires_extension_parity);
27692758
}
27702759

@@ -2775,8 +2764,10 @@ mod tests {
27752764
let command = lab_offload_command(&cli.command).unwrap().unwrap();
27762765

27772766
assert_eq!(command.hot_label, "rig up");
2778-
assert!(!command.portable);
2779-
assert!(command.unsupported_reason.is_some());
2767+
assert!(matches!(
2768+
command.portability,
2769+
LabCommandPortability::LocalOnly(_)
2770+
));
27802771
assert!(!command.routing_policy.requires_extension_parity);
27812772
}
27822773

src/core/api_jobs/mod.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -814,17 +814,15 @@ mod tests {
814814
)
815815
.build();
816816
let command_contract = crate::core::runner::LabOffloadCommand {
817-
hot_label: "tunnel preview-client start",
818-
portable: true,
819-
unsupported_reason: None,
820-
source_path_mode: crate::core::runner::LabOffloadSourcePathMode::CwdOrPathFlag,
821-
workspace_mode_policy:
822-
crate::core::runner::LabOffloadWorkspaceModePolicy::ChangedSinceGitElseSnapshot,
823-
secret_env_sources: Vec::new(),
817+
command: crate::command_contract::LabCommandContract::portable(
818+
"tunnel preview-client start",
819+
None,
820+
false,
821+
&[],
822+
),
824823
required_extensions: Vec::new(),
825824
required_capabilities: Vec::new(),
826825
workload: None,
827-
routing_policy: crate::command_contract::LabRoutingPolicy::default(),
828826
};
829827
request.runner_workload = Some(crate::core::runner::workload::build_runner_workload(
830828
crate::core::runner::workload::RunnerWorkloadBuildInput {

src/core/lab_routing.rs

Lines changed: 7 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ use crate::command_contract::{
99
LabWorkspaceModePolicy,
1010
};
1111
use crate::core::command_execution_plan::{
12-
CommandPortability, CommandSourceMaterialization, CommandSourcePolicy, CommandWorkspacePolicy,
13-
LabRoutePlan,
12+
CommandSourceMaterialization, CommandSourcePolicy, CommandWorkspacePolicy, LabRoutePlan,
1413
};
1514
use crate::core::observation::records::RunEvidenceCommands;
1615
use crate::core::observation::RunStatus;
@@ -448,47 +447,11 @@ pub fn lab_route_plan_from_contract(contract: LabCommandContract) -> LabRoutePla
448447
pub fn lab_offload_command_from_route_contract(
449448
route_contract: LabCommandRouteContract,
450449
) -> runners::LabOffloadCommand {
451-
let hot_label = route_contract.command.hot_label;
452-
let portability = route_contract.command.portability;
453-
let secret_env_sources = route_contract.command.secret_env_sources.to_vec();
454-
let workload = route_contract.workload.clone();
455-
let plan = lab_route_plan_from_route_contract(route_contract);
456450
runners::LabOffloadCommand {
457-
hot_label,
458-
portable: matches!(plan.portability, CommandPortability::Portable),
459-
unsupported_reason: match portability {
460-
LabCommandPortability::Portable => None,
461-
LabCommandPortability::LocalOnly(reason) => Some(reason),
462-
},
463-
source_path_mode: match plan.source_policy {
464-
CommandSourcePolicy::ControllerCwdOrExplicitPath
465-
| CommandSourcePolicy::MaterializeControllerPath => {
466-
runners::LabOffloadSourcePathMode::CwdOrPathFlag
467-
}
468-
CommandSourcePolicy::RunnerResident => {
469-
runners::LabOffloadSourcePathMode::RunnerResident
470-
}
471-
},
472-
workspace_mode_policy: match plan.workspace_policy {
473-
CommandWorkspacePolicy::ChangedSinceGitElseSnapshot => {
474-
runners::LabOffloadWorkspaceModePolicy::ChangedSinceGitElseSnapshot
475-
}
476-
CommandWorkspacePolicy::Git => runners::LabOffloadWorkspaceModePolicy::Git,
477-
CommandWorkspacePolicy::GitCheckoutRequired => {
478-
runners::LabOffloadWorkspaceModePolicy::GitCheckoutRequired
479-
}
480-
CommandWorkspacePolicy::RunnerResident => {
481-
runners::LabOffloadWorkspaceModePolicy::RunnerResident
482-
}
483-
CommandWorkspacePolicy::Snapshot => {
484-
runners::LabOffloadWorkspaceModePolicy::ChangedSinceGitElseSnapshot
485-
}
486-
},
487-
secret_env_sources,
488-
required_extensions: plan.required_extensions,
489-
required_capabilities: plan.required_capabilities,
490-
workload,
491-
routing_policy: plan.routing_policy,
451+
command: route_contract.command,
452+
required_extensions: route_contract.required_extensions,
453+
required_capabilities: route_contract.required_capabilities,
454+
workload: route_contract.workload,
492455
}
493456
}
494457

@@ -672,10 +635,10 @@ mod tests {
672635
vec!["wordpress".to_string(), "playwright".to_string()],
673636
);
674637

638+
assert_eq!(command.command, lab_contract());
675639
assert_eq!(command.hot_label, "trace");
676-
assert!(command.portable);
640+
assert!(command.is_portable());
677641
assert!(command.routing_policy.default_lab_offload);
678-
assert_eq!(command.unsupported_reason, None);
679642
assert_eq!(
680643
command.workspace_mode_policy,
681644
runners::LabOffloadWorkspaceModePolicy::GitCheckoutRequired

0 commit comments

Comments
 (0)