Skip to main content

smbcloud_model/
deploy_config.rs

1use {
2    crate::{project::DeploymentMethod, runner::Runner},
3    serde::{Deserialize, Serialize},
4};
5
6/// Server-side deploy configuration returned by the API.
7///
8/// The CLI fetches this from `GET /v1/frontend_apps/{id}/deploy_config`
9/// and merges the populated fields into the local `.smb/config.toml`.
10#[derive(Debug, Serialize, Deserialize, Clone)]
11pub struct DeployConfig {
12    pub id: String,
13    pub name: String,
14    pub runner: Runner,
15    pub deployment_method: DeploymentMethod,
16    #[serde(default)]
17    pub source_path: Option<String>,
18    #[serde(default)]
19    pub kind: Option<String>,
20    #[serde(default)]
21    pub remote_path: Option<String>,
22    #[serde(default)]
23    pub output_path: Option<String>,
24    #[serde(default)]
25    pub build_command: Option<String>,
26    #[serde(default)]
27    pub install_command: Option<String>,
28    #[serde(default)]
29    pub binary_name: Option<String>,
30    #[serde(default)]
31    pub build_target: Option<String>,
32    #[serde(default)]
33    pub package_manager: Option<String>,
34    #[serde(default)]
35    pub pm2_app: Option<String>,
36    #[serde(default)]
37    pub pm2_env: Option<std::collections::HashMap<String, serde_json::Value>>,
38    /// Runtime supervisor. `nextjs-ssr`: `"pm2"` (default) or `"systemd"`;
39    /// `systemd` restarts via a git-owned
40    /// `systemctl --user restart <pm2_app>.service` instead of `pm2`.
41    /// `rust`: `"nohup"` (default) or `"systemd"`, restarting
42    /// `<binary_name>.service` the same way.
43    #[serde(default)]
44    pub process_manager: Option<String>,
45    #[serde(default)]
46    pub port: Option<u16>,
47    #[serde(default)]
48    pub shared_lib_path: Option<String>,
49    #[serde(default)]
50    pub project_id: Option<i32>,
51    #[serde(default)]
52    pub deploy_repo_id: Option<i64>,
53    #[serde(default)]
54    pub repository: Option<String>,
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn deserializes_full_deploy_config() {
63        let json = r#"{
64            "id": "80b309e8-c39a-45b6-9121-e616fde3cd42",
65            "name": "onde-cloud",
66            "runner": 0,
67            "deployment_method": 1,
68            "source_path": ".",
69            "kind": "rust",
70            "remote_path": "apps/rest-api/onde-cloud",
71            "output_path": null,
72            "build_command": null,
73            "install_command": null,
74            "binary_name": "onde-cloud",
75            "build_target": "x86_64-unknown-linux-gnu",
76            "package_manager": null,
77            "pm2_app": null,
78            "port": 8090,
79            "shared_lib_path": null,
80            "project_id": 50,
81            "deploy_repo_id": 18,
82            "repository": "test"
83        }"#;
84
85        let config: DeployConfig = serde_json::from_str(json).expect("should deserialize");
86        assert_eq!(config.id, "80b309e8-c39a-45b6-9121-e616fde3cd42");
87        assert_eq!(config.kind.as_deref(), Some("rust"));
88        assert_eq!(
89            config.remote_path.as_deref(),
90            Some("apps/rest-api/onde-cloud")
91        );
92        assert_eq!(config.binary_name.as_deref(), Some("onde-cloud"));
93        assert_eq!(
94            config.build_target.as_deref(),
95            Some("x86_64-unknown-linux-gnu")
96        );
97        assert_eq!(config.port, Some(8090));
98        assert_eq!(config.runner, Runner::NodeJs);
99    }
100
101    #[test]
102    fn deserializes_minimal_deploy_config() {
103        let json = r#"{
104            "id": "abc-123",
105            "name": "my-app",
106            "runner": 4,
107            "deployment_method": 0
108        }"#;
109
110        let config: DeployConfig = serde_json::from_str(json).expect("should deserialize");
111        assert_eq!(config.id, "abc-123");
112        assert_eq!(config.runner, Runner::Rust);
113        assert!(config.kind.is_none());
114        assert!(config.remote_path.is_none());
115        assert!(config.port.is_none());
116    }
117}