Skip to main content

tracel_xtask/commands/
docker_compose.rs

1use std::process::Command as StdCommand;
2
3use crate::prelude::{Context, Environment, run_process};
4
5#[tracel_xtask_macros::declare_command_args(None, DockerComposeSubCommand)]
6pub struct DockerComposeCmdArgs {}
7
8pub fn handle_command(
9    args: DockerComposeCmdArgs,
10    env: Environment,
11    _ctx: Context,
12) -> anyhow::Result<()> {
13    match args.get_command() {
14        DockerComposeSubCommand::Up => {
15            up_docker_compose(&env, &args.project, args.build, args.services)
16        }
17        DockerComposeSubCommand::Down => down_docker_compose(&env, &args.project),
18    }
19}
20
21fn get_config_filename(config: &str) -> String {
22    format!("docker-compose.{config}.yml")
23}
24
25pub fn up_docker_compose(
26    env: &Environment,
27    project: &str,
28    build: bool,
29    services: Vec<String>,
30) -> anyhow::Result<()> {
31    let env_name = env.to_string();
32    let project = format!("{project}-{env_name}");
33    let config = get_config_filename(&env_name);
34    let env_files = env.get_env_files();
35    let mut args = vec!["compose", "-f", &config, "-p", &project];
36    env_files.iter().for_each(|f| {
37        let path = std::path::Path::new(f);
38        if path.exists() {
39            args.extend(vec!["--env-file", f]);
40        }
41    });
42    args.extend(vec!["up", "-d"]);
43    if build {
44        args.extend(vec!["--build"]);
45    }
46    args.extend(services.iter().map(String::as_str));
47    let result = run_process(
48        "docker",
49        &args,
50        None,
51        None,
52        "Failed to execute 'docker compose' to start the container!",
53    );
54    if result.is_err() {
55        run_process(
56            "docker-compose",
57            &args[1..],
58            None,
59            None,
60            "Failed to execute 'docker compose' to start the container!",
61        )
62    } else {
63        result
64    }
65}
66
67pub fn down_docker_compose(env: &Environment, project: &str) -> anyhow::Result<()> {
68    let env_name = env.to_string();
69    let project = format!("{project}-{env_name}");
70    let config = get_config_filename(&env_name);
71    let env_files = env.get_env_files();
72    let mut args = vec!["compose", "-f", &config, "-p", &project];
73    env_files.iter().for_each(|f| {
74        let path = std::path::Path::new(f);
75        if path.exists() {
76            args.extend(vec!["--env-file", f]);
77        }
78    });
79    args.extend(vec!["down"]);
80    let result = run_process(
81        "docker",
82        &args,
83        None,
84        None,
85        "Failed to execute 'docker compose' to stop the container!",
86    );
87    if result.is_err() {
88        run_process(
89            "docker-compose",
90            &args[1..],
91            None,
92            None,
93            "Failed to execute 'docker compose' to stop the container!",
94        )
95    } else {
96        result
97    }
98}
99
100pub fn tail_container_command(container_name: &str) -> StdCommand {
101    let mut command = StdCommand::new("docker");
102    command.args(["logs", "-f", container_name]);
103    command
104}