#![allow(clippy::format_push_string)]
use crate::deployment::contract::DeploymentContract;
#[must_use]
pub fn generate_compose_fragment(contract: &DeploymentContract) -> String {
let binary = contract.binary();
let mut out = String::with_capacity(512);
out.push_str(&format!(
"# Generated by hyperi-rustlib deployment module\nservices:\n {}:\n",
contract.app_name
));
out.push_str(&format!(
" image: {}/{}:${{{}_VERSION:-latest}}\n",
contract.image_registry,
contract.app_name,
contract.env_prefix.replace("__", "_")
));
if !contract.depends_on.is_empty() {
out.push_str(" depends_on:\n");
for dep in &contract.depends_on {
out.push_str(&format!(
" {dep}:\n condition: service_healthy\n"
));
}
}
out.push_str(" ports:\n");
out.push_str(&format!(
" - \"{}:{}\"\n",
contract.metrics_port, contract.metrics_port
));
for p in &contract.extra_ports {
out.push_str(&format!(" - \"{}:{}\"\n", p.port, p.port));
}
out.push_str(" volumes:\n");
out.push_str(&format!(
" - ./config/{}:{}:ro\n",
contract.config_filename(),
contract.config_mount_path,
));
out.push_str(&format!(
" healthcheck:\n\
\x20 test: [\"CMD\", \"curl\", \"-sf\", \"http://localhost:{}{}\"]
interval: 10s\n\
\x20 timeout: 3s\n\
\x20 retries: 5\n",
contract.metrics_port, contract.health.liveness_path,
));
if !contract.entrypoint_args.is_empty() {
out.push_str(&format!(" command: [\"{binary}\""));
for arg in &contract.entrypoint_args {
out.push_str(&format!(", \"{arg}\""));
}
out.push_str("]\n");
}
out
}