1mod drift;
6
7use std::process::ExitCode;
8
9const EXIT_ERROR: u8 = 2;
11
12const HELP: &str = "\
13xtask — repo automation for ag-ui-rust
14
15USAGE
16 cargo run -p xtask -- <subcommand> [options]
17
18SUBCOMMANDS
19 drift-check Compare the Rust event types against the vendored
20 snapshot of the upstream TypeScript source of truth.
21 Offline and deterministic; this is the CI gate.
22
23DRIFT-CHECK OPTIONS
24 --upstream Additionally fetch upstream and report whether the
25 vendored baseline itself has gone stale. Needs the
26 network, so keep it out of the required CI job.
27 --refresh Re-fetch upstream and rewrite the vendored baseline,
28 recording the upstream commit and the fetch date.
29 This is how a human accepts an upstream change.
30
31EXIT CODES
32 0 no drift
33 1 drift found (or, with --upstream, the baseline is stale)
34 2 the check could not run
35";
36
37fn main() -> ExitCode {
38 let args: Vec<String> = std::env::args().skip(1).collect();
39 match dispatch(&args) {
40 Ok(code) => ExitCode::from(code),
41 Err(message) => {
42 eprintln!("xtask: {message}");
43 ExitCode::from(EXIT_ERROR)
44 }
45 }
46}
47
48fn dispatch(args: &[String]) -> Result<u8, String> {
49 let Some((subcommand, options)) = args.split_first() else {
50 print!("{HELP}");
51 return Ok(EXIT_ERROR);
52 };
53
54 match subcommand.as_str() {
55 "-h" | "--help" | "help" => {
56 print!("{HELP}");
57 Ok(drift::EXIT_OK)
58 }
59 "drift-check" => drift::run(parse_drift_args(options)?),
60 other => Err(format!(
61 "unknown subcommand `{other}`.\nRun `cargo run -p xtask -- --help` for the list."
62 )),
63 }
64}
65
66fn parse_drift_args(options: &[String]) -> Result<drift::Args, String> {
67 let mut parsed = drift::Args::default();
68 for option in options {
69 match option.as_str() {
70 "--upstream" => parsed.upstream = true,
71 "--refresh" => parsed.refresh = true,
72 other => {
73 return Err(format!(
74 "unknown option `{other}` for drift-check.\n\
75 Valid options are --upstream and --refresh."
76 ));
77 }
78 }
79 }
80 if parsed.refresh && parsed.upstream {
81 return Err("--refresh already re-reads upstream; drop --upstream.\n\
82 Run `drift-check` on its own afterwards to compare the Rust types against the \
83 new baseline."
84 .to_string());
85 }
86 Ok(parsed)
87}