1 use {
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)]
11 pub 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)]
58 mod 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 }