Skip to main content

bupha_runner/
lib.rs

1//! bupha-runner — the runner *port*: a job becomes a spawned child the
2//! watcher can wait on or kill. Implementations live in
3//! `bupha-runner-*` crates; the core knows nothing about dagger, docker
4//! or shells.
5
6use std::io;
7use std::path::Path;
8use std::process::Child;
9
10/// A running job — the local impl wraps `Child`; remote runners
11/// (SSH, hosted agents) impl this over their own handle so the
12/// worker's wait/cancel logic stays unchanged.
13pub trait RunHandle: Send {
14    /// Non-blocking completion check — None if still running.
15    fn try_wait(&mut self) -> io::Result<Option<std::process::ExitStatus>>;
16    /// Block until the run finishes; exit status drives the status
17    /// sink ("success" vs "error").
18    fn wait(&mut self) -> io::Result<std::process::ExitStatus>;
19    /// Best-effort kill (superseded runs).
20    fn kill(&mut self) -> io::Result<()>;
21}
22
23impl RunHandle for Child {
24    fn try_wait(&mut self) -> io::Result<Option<std::process::ExitStatus>> {
25        Child::try_wait(self)
26    }
27    fn wait(&mut self) -> io::Result<std::process::ExitStatus> {
28        Child::wait(self)
29    }
30    fn kill(&mut self) -> io::Result<()> {
31        Child::kill(self)
32    }
33}
34
35/// Everything a runner needs to launch a job.
36pub struct RunCtx<'a> {
37    /// Detached worktree of the sha under test.
38    pub workdir: &'a Path,
39    /// Name of the env var holding the auth token (the runner decides
40    /// how to pass it — e.g. `env://` secret for dagger).
41    pub token_env: &'a str,
42}
43
44/// Job execution — runs a single sha's pipeline.
45pub trait Runner: Send + Sync {
46    /// Human name for logs ("dagger", "script").
47    fn name(&self) -> &'static str;
48    /// Spawn the run. The caller waits/kills via the returned Child —
49    /// keeping the handle outside the queue lock is what makes
50    /// cancel-in-flight safe.
51    fn spawn(&self, ctx: &RunCtx) -> io::Result<Box<dyn RunHandle>>;
52}