1use bupha_runner::{RunCtx, RunHandle, Runner};
6use serde::Deserialize;
7use std::io;
8use std::process::Command;
9
10#[derive(Debug, Deserialize)]
13pub struct DaggerCfg {
14 #[serde(default = "crate::default_function")]
15 pub function: String,
16 #[serde(default = "crate::default_shards")]
17 pub shards: String,
18 #[serde(default = "crate::default_jobs")]
19 pub jobs: String,
20 #[serde(default)]
21 pub dogfood_jobs: String,
22 #[serde(default)]
23 pub sequential: bool,
24 #[serde(default)]
27 pub sccache_conf: Option<String>,
28 #[serde(default)]
29 pub cli_source: Option<String>,
30 #[serde(default)]
31 pub extra_args: Vec<String>,
32}
33
34fn default_function() -> String {
35 "ci".into()
36}
37fn default_shards() -> String {
38 "1".into()
39}
40fn default_jobs() -> String {
41 "1".into()
42}
43
44pub struct DaggerRunner {
45 cfg: DaggerCfg,
46 cli_source: Option<String>,
49}
50
51impl DaggerRunner {
52 pub fn new(cfg: DaggerCfg, cli_source: Option<String>) -> Self {
53 Self { cfg, cli_source }
54 }
55}
56
57impl Runner for DaggerRunner {
58 fn name(&self) -> &'static str {
59 "dagger"
60 }
61
62 fn spawn(&self, ctx: &RunCtx) -> io::Result<Box<dyn RunHandle>> {
63 let c = &self.cfg;
64 let mut cmd = Command::new("dagger");
65 cmd.current_dir(ctx.workdir).args([
69 "call",
70 &c.function,
71 "--shards",
72 &c.shards,
73 "--jobs",
74 &c.jobs,
75 "--token",
76 &format!("env://{}", ctx.token_env),
77 ]);
78 if !c.dogfood_jobs.is_empty() {
79 cmd.args(["--dogfood-jobs", &c.dogfood_jobs]);
80 }
81 if let Some(conf) = c.sccache_conf.as_deref() {
82 cmd.args(["--sccache-conf", &format!("file://{conf}")]);
83 }
84 if c.sequential {
85 cmd.arg("--sequential");
86 }
87 if let Some(src) = &self.cli_source {
88 cmd.args(["--cli-source", src]);
89 }
90 cmd.args(&c.extra_args);
91 cmd.spawn().map(|c| Box::new(c) as Box<dyn RunHandle>)
92 }
93}