1use std::{
2 process::ExitStatus,
3 sync::{mpsc::Sender, Arc},
4 time::Instant,
5};
6
7use anyhow::Error;
8use fluentci_ext::Extension;
9use fluentci_types::Output;
10use owo_colors::OwoColorize;
11
12#[derive(Debug, Clone, Default)]
13pub struct VertexExecOutput {
14 pub stdout: String,
15 pub stderr: String,
16 pub status: ExitStatus,
17}
18
19pub trait Runnable {
20 fn run(
21 &mut self,
22 tx: Sender<String>,
23 out: Output,
24 last_cmd: bool,
25 work_dir: &str,
26 ) -> Result<ExitStatus, Error>;
27}
28
29#[derive(Clone)]
30pub struct Vertex {
31 pub id: String,
32 pub label: String,
33 pub command: String,
34 pub needs: Vec<String>,
35 pub runner: Arc<Box<dyn Extension + Send + Sync>>,
36}
37
38impl Runnable for Vertex {
39 fn run(
40 &mut self,
41 tx: Sender<String>,
42 out: Output,
43 last_cmd: bool,
44 work_dir: &str,
45 ) -> Result<ExitStatus, Error> {
46 let start_time = Instant::now();
47 let label = format!("[{}]", self.label);
48 println!("{} {}", label.cyan(), self.id.bright_yellow());
49 println!("{} {}", label.cyan(), self.command.bright_green());
50 fluentci_logging::info(&format!("{} {}", label, self.id), "fluentci-core")?;
51
52 if let Some(runner) = Arc::get_mut(&mut self.runner) {
53 let result = runner.exec(&self.command, tx, out, last_cmd, work_dir)?;
54 let end_time = Instant::now();
55 let duration = end_time.duration_since(start_time).as_millis();
56 fluentci_logging::info_with_duration(
57 &format!("{} {}", label, self.command),
58 "fluentci-core",
59 duration,
60 )?;
61 return Ok(result);
62 } else {
63 Err(Error::msg("Failed to obtain mutable reference to runner"))
64 }
65 }
66}