1use std::path::Path;
2
3use tokio::process::Command;
4
5use std::env;
6use std::process::Output;
7
8use crate::cluster;
9use crate::cluster::{local, progress};
10use crate::engine::runner::commit::When;
11use crate::engine::runner::git_ops;
12
13async fn git(dir: &Path, args: &[&str]) -> anyhow::Result<Output> {
14 Ok(Command::new("git")
15 .args(args)
16 .current_dir(dir)
17 .output()
18 .await?)
19}
20
21pub async fn run(done: &str, left: &str, state: &str) -> anyhow::Result<()> {
24 let cwd = env::current_dir()?;
25 let top = git(&cwd, &["rev-parse", "--show-toplevel"]).await?;
26 anyhow::ensure!(
27 top.status.success(),
28 "orch progress runs inside a task worktree"
29 );
30 let worktree = String::from_utf8_lossy(&top.stdout).trim().to_string();
31 let dir = Path::new(&worktree);
32
33 let task_id = env::var("TASK_ID").unwrap_or_default();
34 let agent = env::var("ORCH_AGENT").unwrap_or_else(|_| "agent".to_string());
35 let (cli_committed, cli_error) =
36 match git_ops::auto_commit(dir, &task_id, done, &agent, 0, When::Tested).await {
37 Ok(committed) => (committed, None),
38 Err(e) => (false, Some(format!("{e:#}"))),
39 };
40
41 let report = progress::Report {
42 worktree,
43 done: done.to_string(),
44 left: left.to_string(),
45 state: state.to_string(),
46 cli_committed,
47 cli_error,
48 };
49 if !cluster::enabled() {
50 eprintln!("committed locally. Recording progress needs a cluster section in the config");
51 return Ok(());
52 }
53
54 let Some(endpoint) = local::daemon_endpoint().await else {
55 eprintln!("orch service is not running: committed locally, nothing recorded or pushed");
56 return Ok(());
57 };
58 let record = local::send_progress(&endpoint, &report).await?;
59 println!(
60 "{} {} committed by {}, pushed by {}",
61 record.branch,
62 record.commit.chars().take(12).collect::<String>(),
63 record.committed_by,
64 record.pushed_by
65 );
66 if let Some(err) = record.error {
67 eprintln!("{err}");
68 }
69
70 Ok(())
71}