runx_runtime/dev/
types.rs1use 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;