dampen_cli/commands/
release.rs

1#![allow(clippy::print_stderr, clippy::print_stdout)]
2
3//! Release command - builds production-optimized binaries with codegen mode
4//!
5//! This command wraps `cargo build --release` with the `codegen` feature flag,
6//! providing optimized production builds with zero runtime overhead.
7
8use std::path::Path;
9use std::process::Command;
10
11/// Release command arguments
12#[derive(clap::Args)]
13pub struct ReleaseArgs {
14    /// Package to build (if workspace has multiple packages)
15    #[arg(short, long)]
16    package: Option<String>,
17
18    /// Additional features to enable (beyond codegen)
19    #[arg(long, value_delimiter = ',')]
20    features: Vec<String>,
21
22    /// Verbose output
23    #[arg(short, long)]
24    verbose: bool,
25
26    /// Target directory for build artifacts
27    #[arg(long)]
28    target_dir: Option<String>,
29}
30
31/// Execute the release command
32///
33/// Builds the application in production mode with full optimizations.
34///
35/// # Mode Behavior
36///
37/// - **Release Mode**: Compile-time code generation with full optimizations
38/// - Zero runtime overhead for maximum performance
39/// - Ideal for production deployments
40/// - Requires build.rs for code generation
41///
42/// # Examples
43///
44/// ```bash
45/// # Basic release build
46/// dampen release
47///
48/// # Build specific package in workspace
49/// dampen release -p my-app
50///
51/// # Enable additional features
52/// dampen release --features tokio,logging
53///
54/// # Custom target directory
55/// dampen release --target-dir ./dist
56/// ```
57pub fn execute(args: &ReleaseArgs) -> Result<(), String> {
58    // Check if Cargo.toml exists
59    if !Path::new("Cargo.toml").exists() {
60        return Err("Cargo.toml not found. Are you in a Rust project directory?".to_string());
61    }
62
63    // Check if build.rs exists
64    if !Path::new("build.rs").exists() {
65        return Err(
66            "build.rs not found. This project may not be configured for production builds."
67                .to_string(),
68        );
69    }
70
71    if args.verbose {
72        eprintln!("Building for production (release mode with codegen)...");
73    }
74
75    // Build the cargo command
76    let mut cmd = Command::new("cargo");
77    cmd.arg("build");
78    cmd.arg("--release");
79
80    // Add package specification if provided
81    if let Some(ref package) = args.package {
82        cmd.arg("-p").arg(package);
83    }
84
85    // Add target directory if provided
86    if let Some(ref target_dir) = args.target_dir {
87        cmd.arg("--target-dir").arg(target_dir);
88    }
89
90    if args.verbose {
91        cmd.arg("--verbose");
92    }
93
94    // Build features list: always include 'codegen', plus user-specified features
95    let mut all_features = vec!["codegen".to_string()];
96    all_features.extend(args.features.clone());
97
98    // Add features flag
99    cmd.arg("--features").arg(all_features.join(","));
100
101    // Execute cargo build --release
102    if args.verbose {
103        let features_str = all_features.join(",");
104        eprintln!(
105            "Executing: cargo build --release --features {}",
106            features_str
107        );
108    }
109
110    let status = cmd
111        .status()
112        .map_err(|e| format!("Failed to execute cargo: {}", e))?;
113
114    if !status.success() {
115        return Err("Release build failed".to_string());
116    }
117
118    if args.verbose {
119        eprintln!("Release build successful! Binary is in target/release/");
120    }
121
122    eprintln!("Production build completed successfully!");
123    Ok(())
124}