Skip to main content

mecha10_deploy/services/deployment/
types.rs

1//! Deployment service types
2
3use mecha10_core::enum_str_method;
4use std::path::PathBuf;
5use std::str::FromStr;
6
7#[derive(Debug, Clone)]
8pub struct DeployConfig {
9    pub host: String,
10    pub user: String,
11    pub port: u16,
12    pub ssh_key: Option<PathBuf>,
13    pub remote_dir: String,
14    pub service_name: String,
15    pub backup_dir: String,
16    pub health_check_timeout: u64,
17    pub health_check_retries: u32,
18}
19
20impl Default for DeployConfig {
21    fn default() -> Self {
22        Self {
23            host: "robot.local".to_string(),
24            user: "mecha10".to_string(),
25            port: 22,
26            ssh_key: None,
27            remote_dir: "/opt/mecha10".to_string(),
28            service_name: "mecha10-robot".to_string(),
29            backup_dir: "/opt/mecha10/backups".to_string(),
30            health_check_timeout: 30,
31            health_check_retries: 3,
32        }
33    }
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum DeployStrategy {
38    Direct,
39    Rolling,
40    BlueGreen,
41}
42
43impl FromStr for DeployStrategy {
44    type Err = String;
45
46    fn from_str(s: &str) -> Result<Self, Self::Err> {
47        match s {
48            "direct" => Ok(DeployStrategy::Direct),
49            "rolling" => Ok(DeployStrategy::Rolling),
50            "blue-green" | "bluegreen" => Ok(DeployStrategy::BlueGreen),
51            _ => Err(format!("Invalid deployment strategy: {}", s)),
52        }
53    }
54}
55
56enum_str_method!(
57    pub fn as_str(DeployStrategy) -> &str {
58        Direct => "direct",
59        Rolling => "rolling",
60        BlueGreen => "blue-green",
61    }
62);
63
64#[derive(Debug, Clone)]
65pub struct DeployResult {
66    pub success: bool,
67    pub message: String,
68    pub health_check_passed: bool,
69    pub backup_created: bool,
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn deploy_strategy_parses_remaining_strategies() {
78        assert_eq!("direct".parse::<DeployStrategy>(), Ok(DeployStrategy::Direct));
79        assert_eq!("rolling".parse::<DeployStrategy>(), Ok(DeployStrategy::Rolling));
80        assert_eq!("blue-green".parse::<DeployStrategy>(), Ok(DeployStrategy::BlueGreen));
81        assert_eq!("bluegreen".parse::<DeployStrategy>(), Ok(DeployStrategy::BlueGreen));
82    }
83
84    #[test]
85    fn deploy_strategy_rejects_removed_canary_strategy() {
86        assert!("canary".parse::<DeployStrategy>().is_err());
87    }
88
89    #[test]
90    fn deploy_strategy_rejects_unknown_strategy() {
91        assert!("invalid".parse::<DeployStrategy>().is_err());
92    }
93
94    #[test]
95    fn deploy_strategy_as_str_matches_from_str() {
96        for (s, expected) in [
97            ("direct", DeployStrategy::Direct),
98            ("rolling", DeployStrategy::Rolling),
99            ("blue-green", DeployStrategy::BlueGreen),
100        ] {
101            let parsed: DeployStrategy = s.parse().unwrap();
102            assert_eq!(parsed, expected);
103            assert_eq!(parsed.as_str(), s);
104        }
105    }
106}