Skip to main content

dstack/
cmd_deploy.rs

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    // 1. Build
11    eprintln!("[1/3] Building...");
12    run_cmd(&target.build, "Build")?;
13
14    // 2. Restart service
15    eprintln!("[2/3] Restarting {}...", target.service);
16    run_cmd(&format!("sudo systemctl restart {}", target.service), "Restart")?;
17
18    // 3. Smoke test
19    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}