1use std::time::Duration;
2use thiserror::Error;
3
4pub type Result<T> = std::result::Result<T, GoblinError>;
5
6#[derive(Error, Debug)]
7pub enum GoblinError {
8 #[error("Script not found: {name}")]
9 ScriptNotFound { name: String },
10
11 #[error("Plan not found: {name}")]
12 PlanNotFound { name: String },
13
14 #[error("Script execution failed: {script} - {message}")]
15 ScriptExecutionFailed { script: String, message: String },
16
17 #[error("Script execution timed out: {script} after {timeout:?}")]
18 ScriptTimeout { script: String, timeout: Duration },
19
20 #[error("Test failed for script: {script}")]
21 TestFailed { script: String },
22
23 #[error("Configuration error: {message}")]
24 ConfigError { message: String },
25
26 #[error("IO error: {0}")]
27 IoError(#[from] std::io::Error),
28
29 #[error("TOML parsing error: {0}")]
30 TomlError(#[from] toml::de::Error),
31
32 #[error("Serialization error: {0}")]
33 SerializationError(#[from] toml::ser::Error),
34
35 #[error("Invalid step configuration: {message}")]
36 InvalidStepConfig { message: String },
37
38 #[error("Circular dependency detected in plan: {plan}")]
39 CircularDependency { plan: String },
40
41 #[error("Missing input dependency: {step} requires {dependency}")]
42 MissingDependency { step: String, dependency: String },
43
44 #[error("Engine error: {message}")]
45 EngineError { message: String },
46}
47
48impl GoblinError {
49 pub fn script_not_found(name: impl Into<String>) -> Self {
50 Self::ScriptNotFound { name: name.into() }
51 }
52
53 pub fn plan_not_found(name: impl Into<String>) -> Self {
54 Self::PlanNotFound { name: name.into() }
55 }
56
57 pub fn script_execution_failed(script: impl Into<String>, message: impl Into<String>) -> Self {
58 Self::ScriptExecutionFailed {
59 script: script.into(),
60 message: message.into(),
61 }
62 }
63
64 pub fn script_timeout(script: impl Into<String>, timeout: Duration) -> Self {
65 Self::ScriptTimeout {
66 script: script.into(),
67 timeout,
68 }
69 }
70
71 pub fn test_failed(script: impl Into<String>) -> Self {
72 Self::TestFailed {
73 script: script.into(),
74 }
75 }
76
77 pub fn config_error(message: impl Into<String>) -> Self {
78 Self::ConfigError {
79 message: message.into(),
80 }
81 }
82
83 pub fn invalid_step_config(message: impl Into<String>) -> Self {
84 Self::InvalidStepConfig {
85 message: message.into(),
86 }
87 }
88
89 pub fn circular_dependency(plan: impl Into<String>) -> Self {
90 Self::CircularDependency { plan: plan.into() }
91 }
92
93 pub fn missing_dependency(step: impl Into<String>, dependency: impl Into<String>) -> Self {
94 Self::MissingDependency {
95 step: step.into(),
96 dependency: dependency.into(),
97 }
98 }
99
100 pub fn engine_error(message: impl Into<String>) -> Self {
101 Self::EngineError {
102 message: message.into(),
103 }
104 }
105}