use std::collections::BTreeMap;
use anyhow::Result;
use chrono::Utc;
use harmont_cloud::HarmontClient;
use hm_plugin_protocol::events::{BuildEvent, PlanSummary};
use uuid::Uuid;
use crate::cli::JobCommand;
use crate::settings;
use hm_exec::cloud::watch::stream_job_logs_as_events;
pub(crate) async fn run(_env: &BTreeMap<String, String>, cmd: JobCommand) -> Result<()> {
let (client, ctx) = settings::client()?;
let org = ctx.org()?;
match cmd {
JobCommand::List { pipeline, build } => list(&client, &org, &pipeline, build).await,
JobCommand::Show {
pipeline,
build,
job_id,
} => show(&client, &org, &pipeline, build, &job_id).await,
JobCommand::Log {
pipeline,
build,
job_id,
} => log_cmd(&client, &org, &pipeline, build, &job_id).await,
}
}
async fn list(client: &HarmontClient, org: &str, pipe: &str, build: i64) -> Result<()> {
let jobs = client.list_jobs(org, pipe, build).await?;
for j in &jobs {
tracing::info!(
"{} {:<10} {}",
j.id,
j.state.to_string(),
j.name.as_deref().unwrap_or("")
);
}
Ok(())
}
async fn show(client: &HarmontClient, org: &str, pipe: &str, build: i64, jid: &str) -> Result<()> {
let j = client
.raw()
.get_job(org, pipe, build, jid)
.await
.map_err(settings::map_raw)?
.into_inner();
tracing::info!("{}", serde_json::to_string_pretty(&j).unwrap_or_default());
Ok(())
}
async fn log_cmd(
client: &HarmontClient,
org: &str,
pipe: &str,
build: i64,
jid: &str,
) -> Result<()> {
let job_id = Uuid::parse_str(jid)
.map_err(|e| anyhow::anyhow!("job id '{jid}' is not a valid UUID: {e}"))?;
let token = client.log_token(org, pipe, build).await?;
let log_base = client.base_url().to_string();
let prefs = settings::RenderPrefs::detect();
let renderer = hm_render::renderer_for("human", prefs.color, true)?;
let (tx, rx) = tokio::sync::mpsc::channel(1024);
let driver = tokio::spawn(hm_render::drive(renderer, rx));
let name = jid.to_string();
let _ = tx
.send(BuildEvent::BuildStart {
run_id: Uuid::new_v4(),
plan: PlanSummary {
step_count: 1,
chain_count: 1,
default_runner: "cloud".to_string(),
},
started_at: Utc::now(),
})
.await;
let _ = tx
.send(BuildEvent::StepQueued {
step_id: job_id,
key: name.clone(),
chain_idx: 0,
parent_key: None,
display_name: name,
})
.await;
let _ = tx
.send(BuildEvent::StepStart {
step_id: job_id,
runner: "cloud".to_string(),
image: None,
})
.await;
stream_job_logs_as_events(client, &log_base, job_id, &token.token, &tx).await?;
let _ = tx
.send(BuildEvent::StepEnd {
step_id: job_id,
exit_code: 0,
duration_ms: 0,
snapshot: None,
})
.await;
let _ = tx
.send(BuildEvent::BuildEnd {
exit_code: 0,
duration_ms: 0,
})
.await;
let _ = driver.await;
Ok(())
}