1#[derive(Debug, thiserror::Error)]
6pub enum DeployError {
7 #[error("chain query failed: {0}")]
8 Query(String),
9
10 #[error("transaction failed: code={code}, log={log}")]
11 Transaction { code: u32, log: String },
12
13 #[error("provider communication failed: {0}")]
14 Provider(String),
15
16 #[error("invalid SDL: {0}")]
17 Sdl(String),
18
19 #[error("manifest build failed: {0}")]
20 Manifest(String),
21
22 #[error("invalid workflow state: {0}")]
23 InvalidState(String),
24
25 #[error("storage error: {0}")]
26 Storage(String),
27
28 #[error("certificate error: {0}")]
29 Certificate(String),
30
31 #[error("JWT error: {0}")]
32 Jwt(String),
33
34 #[error("timeout: {0}")]
35 Timeout(String),
36
37 #[error("template error: {0}")]
38 Template(String),
39
40 #[error("signer error: {0}")]
41 Signer(String),
42}
43
44impl DeployError {
45 pub fn is_recoverable(&self) -> bool {
47 matches!(
48 self,
49 DeployError::Query(_) | DeployError::Provider(_) | DeployError::Timeout(_)
50 )
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn test_error_display() {
60 let err = DeployError::Query("connection failed".to_string());
61 assert_eq!(err.to_string(), "chain query failed: connection failed");
62
63 let err = DeployError::Transaction {
64 code: 5,
65 log: "insufficient funds".to_string(),
66 };
67 assert!(err.to_string().contains("code=5"));
68 assert!(err.to_string().contains("insufficient funds"));
69
70 let err = DeployError::Provider("404".to_string());
71 assert_eq!(err.to_string(), "provider communication failed: 404");
72
73 let err = DeployError::Sdl("invalid yaml".to_string());
74 assert_eq!(err.to_string(), "invalid SDL: invalid yaml");
75
76 let err = DeployError::Manifest("parsing failed".to_string());
77 assert_eq!(err.to_string(), "manifest build failed: parsing failed");
78
79 let err = DeployError::InvalidState("bad transition".to_string());
80 assert_eq!(err.to_string(), "invalid workflow state: bad transition");
81
82 let err = DeployError::Storage("disk full".to_string());
83 assert_eq!(err.to_string(), "storage error: disk full");
84
85 let err = DeployError::Certificate("expired".to_string());
86 assert_eq!(err.to_string(), "certificate error: expired");
87
88 let err = DeployError::Jwt("invalid signature".to_string());
89 assert_eq!(err.to_string(), "JWT error: invalid signature");
90
91 let err = DeployError::Timeout("30s".to_string());
92 assert_eq!(err.to_string(), "timeout: 30s");
93
94 let err = DeployError::Template("missing variable".to_string());
95 assert_eq!(err.to_string(), "template error: missing variable");
96 }
97
98 #[test]
99 fn test_error_is_recoverable() {
100 assert!(DeployError::Query("test".to_string()).is_recoverable());
101 assert!(DeployError::Provider("test".to_string()).is_recoverable());
102 assert!(DeployError::Timeout("test".to_string()).is_recoverable());
103
104 assert!(!DeployError::Sdl("test".to_string()).is_recoverable());
105 assert!(!DeployError::Manifest("test".to_string()).is_recoverable());
106 assert!(!DeployError::InvalidState("test".to_string()).is_recoverable());
107 assert!(!DeployError::Certificate("test".to_string()).is_recoverable());
108 assert!(!DeployError::Jwt("test".to_string()).is_recoverable());
109 assert!(!DeployError::Template("test".to_string()).is_recoverable());
110 }
111}