Skip to main content

runx_runtime/dev/
types.rs

1use std::collections::BTreeMap;
2use std::path::PathBuf;
3
4use runx_contracts::JsonObject;
5pub use runx_contracts::{
6    DevFixtureAssertion, DevFixtureAssertionKind, DevFixtureResult, DevFixtureStatus, DevReport,
7    DevReportSchema, DevReportStatus,
8};
9use thiserror::Error;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct DevLoopOptions {
13    pub root: PathBuf,
14    pub unit_path: Option<PathBuf>,
15    pub lane: DevLane,
16}
17
18impl DevLoopOptions {
19    #[must_use]
20    pub fn new(root: impl Into<PathBuf>) -> Self {
21        Self {
22            root: root.into(),
23            unit_path: None,
24            lane: DevLane::Deterministic,
25        }
26    }
27}
28
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub enum DevLane {
31    Deterministic,
32    RepoIntegration,
33    Agent,
34    All,
35    Other(String),
36}
37
38impl DevLane {
39    #[must_use]
40    pub fn as_str(&self) -> &str {
41        match self {
42            Self::Deterministic => "deterministic",
43            Self::RepoIntegration => "repo-integration",
44            Self::Agent => "agent",
45            Self::All => "all",
46            Self::Other(value) => value,
47        }
48    }
49}
50
51impl From<&str> for DevLane {
52    fn from(value: &str) -> Self {
53        match value {
54            "deterministic" => Self::Deterministic,
55            "repo-integration" => Self::RepoIntegration,
56            "agent" => Self::Agent,
57            "all" => Self::All,
58            other => Self::Other(other.to_owned()),
59        }
60    }
61}
62
63#[derive(Clone, Debug, PartialEq)]
64pub struct ParsedDevFixture {
65    pub path: PathBuf,
66    pub name: String,
67    pub lane: String,
68    pub target: JsonObject,
69    pub document: JsonObject,
70}
71
72#[derive(Clone, Debug, PartialEq, Eq)]
73pub struct DevFixtureExecutionRoots {
74    pub cwd: PathBuf,
75    pub repo_root: PathBuf,
76}
77
78#[derive(Clone, Debug)]
79pub struct PreparedDevFixtureWorkspace {
80    pub root: Option<PathBuf>,
81    pub tokens: BTreeMap<String, String>,
82}
83
84#[derive(Debug, Error)]
85pub enum DevError {
86    #[error("failed to read dev fixture {path}: {source}")]
87    ReadFixture {
88        path: PathBuf,
89        #[source]
90        source: std::io::Error,
91    },
92    #[error("failed to parse dev fixture {path}: {source}")]
93    ParseFixture {
94        path: PathBuf,
95        #[source]
96        source: serde_norway::Error,
97    },
98    #[error("failed to read {path}: {source}")]
99    Io {
100        path: PathBuf,
101        #[source]
102        source: std::io::Error,
103    },
104    #[error("failed to parse JSON at {path}: {source}")]
105    Json {
106        path: PathBuf,
107        #[source]
108        source: serde_json::Error,
109    },
110    #[error("dev fixture workspace path must be relative: {path}")]
111    AbsoluteWorkspacePath { path: String },
112    #[error("dev fixture workspace path escapes root: {path}")]
113    EscapingWorkspacePath { path: String },
114    #[error("failed to run fixture command {command}: {source}")]
115    Spawn {
116        command: String,
117        #[source]
118        source: std::io::Error,
119    },
120    #[error("dev fixture command `{command}` failed with status {status}: {output}")]
121    FixtureCommand {
122        command: String,
123        status: i32,
124        output: String,
125    },
126    #[error(transparent)]
127    Runtime(#[from] crate::RuntimeError),
128}
129
130pub trait DevFixtureExecutor {
131    fn run_fixture(
132        &self,
133        root: &std::path::Path,
134        fixture: &ParsedDevFixture,
135    ) -> Result<DevFixtureResult, DevError>;
136}
137
138#[derive(Clone, Debug, Default)]
139pub struct LocalDevFixtureExecutor;