use crate::cli::BuildArgs;
use crate::config::GlobalConfig;
use crate::docker::Engine;
use crate::docker::build::{BuildCommand, arch_to_platform, image_name};
use crate::environment::EnvironmentManager;
use crate::template::{ProcessContext, process_templates};
use crate::{EnvFeaturizedName, Error, Result};
use colored::Colorize;
pub fn execute_build(args: &BuildArgs, verbose: bool) -> Result<()> {
let manager = EnvironmentManager::new()?;
let paths = manager.paths();
let global_config = GlobalConfig::load(&paths.global_config())?;
let env_feat_name = EnvFeaturizedName::parse(&args.env)?;
let env = manager.search_result(&env_feat_name.name)?;
let mut config = env.config.clone();
if !env_feat_name.features.is_empty() {
eprintln!("Taking base configuration '{}'", env_feat_name.name.green());
for feature in &env_feat_name.features {
eprintln!(" - Applying feature '{}'", feature.cyan());
}
config.apply_features(&env_feat_name.features)?;
}
if verbose {
eprintln!("Building environment: {}", env.name.green());
}
let engine = match &args.engine {
Some(e) => e.parse::<Engine>()?,
None => global_config.get_container_engine()?,
};
let arch = args.arch.as_deref().or(global_config.arch.as_deref());
let platform = if let Some(a) = arch {
Some(arch_to_platform(a).ok_or_else(|| Error::InvalidArchitecture(a.to_string()))?)
} else {
None
};
let img_name = image_name(&env.name, arch);
let build_cmd = BuildCommand {
engine,
image_name: img_name.clone(),
context_path: env.path.display().to_string(),
dockerfile_path: paths.dockerfile(&env.env_path()).display().to_string(),
platform,
no_cache: args.rebuild,
};
if args.dry_run {
println!("{}", "Dry run - would execute:".blue());
println!(" {}", build_cmd);
return Ok(());
}
if !config.templates.is_empty() {
if verbose {
eprintln!("{} Processing templates...", "→".blue());
}
process_templates(&env.path, &config.templates, ProcessContext::Build, verbose)?;
}
println!(
"{} {} with {}",
"Building".blue(),
img_name.green().bold(),
engine.to_string().cyan()
);
if verbose {
eprintln!(" Command: {}", build_cmd);
}
let status = crate::docker::execute_command_status(&engine, build_cmd.args(), &env.path)?;
if !status.success() {
return Err(Error::ContainerCommandFailed(format!(
"Build failed with exit code: {:?}",
status.code()
)));
}
println!("{} Image {} built successfully", "✓".green(), img_name);
Ok(())
}