1use crate::config::Config;
2use std::process::Command;
3
4pub fn deploy(cfg: &Config, service: &str) -> anyhow::Result<()> {
5 let target = cfg.deploy.get(service)
6 .ok_or_else(|| anyhow::anyhow!("No deploy target '{}'. Available: {:?}", service, cfg.deploy.keys().collect::<Vec<_>>()))?;
7
8 eprintln!("=== Deploying {} ===", service);
9
10 eprintln!("[1/3] Building...");
12 run_cmd(&target.build, "Build")?;
13
14 eprintln!("[2/3] Restarting {}...", target.service);
16 run_cmd(&format!("sudo systemctl restart {}", target.service), "Restart")?;
17
18 if let Some(ref smoke) = target.smoke {
20 eprintln!("[3/3] Smoke test...");
21 std::thread::sleep(std::time::Duration::from_secs(2));
22 match run_cmd(smoke, "Smoke test") {
23 Ok(_) => eprintln!("Smoke test passed."),
24 Err(e) => eprintln!("WARNING: Smoke test failed: {}. Consider rollback.", e),
25 }
26 } else {
27 eprintln!("[3/3] No smoke test configured, skipping.");
28 }
29
30 eprintln!("=== {} deployed ===", service);
31 Ok(())
32}
33
34pub fn deploy_all(cfg: &Config) -> anyhow::Result<()> {
35 if cfg.deploy.is_empty() {
36 anyhow::bail!("No deploy targets configured in config.toml");
37 }
38 for name in cfg.deploy.keys() {
39 deploy(cfg, name)?;
40 }
41 Ok(())
42}
43
44fn run_cmd(cmd: &str, label: &str) -> anyhow::Result<()> {
45 let status = Command::new("bash").arg("-c").arg(cmd).status()?;
46 if !status.success() {
47 anyhow::bail!("{} failed (exit {})", label, status.code().unwrap_or(-1));
48 }
49 Ok(())
50}