huskies: merge 563_story_build_agent_join_mechanism_agents_register_with_the_gateway_via_token
This commit is contained in:
+100
-1
@@ -56,6 +56,10 @@ struct CliArgs {
|
||||
rendezvous: Option<String>,
|
||||
/// Whether `--gateway` mode was requested (proxy MCP calls to per-project containers).
|
||||
gateway: bool,
|
||||
/// One-time join token for registering this build agent with a gateway (`--join-token`).
|
||||
join_token: Option<String>,
|
||||
/// HTTP URL of the gateway to register with when a join token is provided (`--gateway-url`).
|
||||
gateway_url: Option<String>,
|
||||
}
|
||||
|
||||
/// Parse CLI arguments into `CliArgs`, or exit early for `--help` / `--version`.
|
||||
@@ -66,6 +70,8 @@ fn parse_cli_args(args: &[String]) -> Result<CliArgs, String> {
|
||||
let mut agent = false;
|
||||
let mut gateway = false;
|
||||
let mut rendezvous: Option<String> = None;
|
||||
let mut join_token: Option<String> = None;
|
||||
let mut gateway_url: Option<String> = None;
|
||||
let mut i = 0;
|
||||
|
||||
while i < args.len() {
|
||||
@@ -106,6 +112,26 @@ fn parse_cli_args(args: &[String]) -> Result<CliArgs, String> {
|
||||
let val = &a["--rendezvous=".len()..];
|
||||
rendezvous = Some(val.to_string());
|
||||
}
|
||||
"--join-token" => {
|
||||
i += 1;
|
||||
if i >= args.len() {
|
||||
return Err("--join-token requires a value".to_string());
|
||||
}
|
||||
join_token = Some(args[i].clone());
|
||||
}
|
||||
a if a.starts_with("--join-token=") => {
|
||||
join_token = Some(a["--join-token=".len()..].to_string());
|
||||
}
|
||||
"--gateway-url" => {
|
||||
i += 1;
|
||||
if i >= args.len() {
|
||||
return Err("--gateway-url requires a value".to_string());
|
||||
}
|
||||
gateway_url = Some(args[i].clone());
|
||||
}
|
||||
a if a.starts_with("--gateway-url=") => {
|
||||
gateway_url = Some(a["--gateway-url=".len()..].to_string());
|
||||
}
|
||||
"--gateway" => {
|
||||
gateway = true;
|
||||
}
|
||||
@@ -139,6 +165,8 @@ fn parse_cli_args(args: &[String]) -> Result<CliArgs, String> {
|
||||
agent,
|
||||
rendezvous,
|
||||
gateway,
|
||||
join_token,
|
||||
gateway_url,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -172,6 +200,11 @@ fn print_help() {
|
||||
println!(
|
||||
" (or cwd) and proxies MCP calls to per-project containers."
|
||||
);
|
||||
println!(" --join-token <TOKEN> One-time token for registering this build agent with a");
|
||||
println!(" gateway. Also readable from HUSKIES_JOIN_TOKEN env var.");
|
||||
println!(" --gateway-url <URL> HTTP URL of the gateway to register with when");
|
||||
println!(" --join-token is provided (agent mode only).");
|
||||
println!(" Also readable from HUSKIES_GATEWAY_URL env var.");
|
||||
}
|
||||
|
||||
/// Resolve the optional positional path argument into an absolute `PathBuf`.
|
||||
@@ -411,7 +444,16 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
if is_agent {
|
||||
let agent_root = app_state.project_root.lock().unwrap().clone();
|
||||
let rendezvous = agent_rendezvous.expect("agent mode requires --rendezvous");
|
||||
return agent_mode::run(agent_root, rendezvous, port).await;
|
||||
// Join token / gateway URL can come from CLI flags or environment variables.
|
||||
let join_token = cli
|
||||
.join_token
|
||||
.clone()
|
||||
.or_else(|| std::env::var("HUSKIES_JOIN_TOKEN").ok());
|
||||
let agent_gateway_url = cli
|
||||
.gateway_url
|
||||
.clone()
|
||||
.or_else(|| std::env::var("HUSKIES_GATEWAY_URL").ok());
|
||||
return agent_mode::run(agent_root, rendezvous, port, join_token, agent_gateway_url).await;
|
||||
}
|
||||
|
||||
let workflow = Arc::new(std::sync::Mutex::new(WorkflowState::default()));
|
||||
@@ -1087,6 +1129,63 @@ name = "coder"
|
||||
assert_eq!(result.path, Some("/my/project".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_join_token_flag() {
|
||||
let args = vec![
|
||||
"agent".to_string(),
|
||||
"--rendezvous".to_string(),
|
||||
"ws://host:3001/crdt-sync".to_string(),
|
||||
"--join-token".to_string(),
|
||||
"my-secret-token".to_string(),
|
||||
];
|
||||
let result = parse_cli_args(&args).unwrap();
|
||||
assert_eq!(result.join_token, Some("my-secret-token".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_join_token_equals_syntax() {
|
||||
let args = vec![
|
||||
"agent".to_string(),
|
||||
"--rendezvous".to_string(),
|
||||
"ws://host:3001/crdt-sync".to_string(),
|
||||
"--join-token=abc123".to_string(),
|
||||
];
|
||||
let result = parse_cli_args(&args).unwrap();
|
||||
assert_eq!(result.join_token, Some("abc123".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_gateway_url_flag() {
|
||||
let args = vec![
|
||||
"agent".to_string(),
|
||||
"--rendezvous".to_string(),
|
||||
"ws://host:3001/crdt-sync".to_string(),
|
||||
"--gateway-url".to_string(),
|
||||
"http://gateway:3000".to_string(),
|
||||
];
|
||||
let result = parse_cli_args(&args).unwrap();
|
||||
assert_eq!(result.gateway_url, Some("http://gateway:3000".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_join_token_missing_value_is_error() {
|
||||
let args = vec!["--join-token".to_string()];
|
||||
assert!(parse_cli_args(&args).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_gateway_url_missing_value_is_error() {
|
||||
let args = vec!["--gateway-url".to_string()];
|
||||
assert!(parse_cli_args(&args).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_no_args_join_token_and_gateway_url_are_none() {
|
||||
let result = parse_cli_args(&[]).unwrap();
|
||||
assert_eq!(result.join_token, None);
|
||||
assert_eq!(result.gateway_url, None);
|
||||
}
|
||||
|
||||
// ── resolve_path_arg ────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user