clnrm_core/cli/commands/
init.rs

1//! Init command implementation
2//!
3//! Handles project initialization with template generation and directory
4//! structure creation.
5
6use crate::error::{CleanroomError, Result};
7use crate::telemetry::cli_helpers::CliInitSpanBuilder;
8
9/// Initialize a new test project in the current directory
10pub fn init_project(force: bool, with_config: bool) -> Result<()> {
11    // Get absolute project path for telemetry
12    let project_path = std::env::current_dir()
13        .map(|p| p.to_string_lossy().to_string())
14        .unwrap_or_else(|_| ".".to_string());
15
16    // Check if already initialized
17    let tests_dir = std::path::Path::new("tests");
18    let scenarios_dir = std::path::Path::new("scenarios");
19    let basic_test_file = tests_dir.join("basic.clnrm.toml");
20
21    let exists_before = tests_dir.exists() && scenarios_dir.exists() && basic_test_file.exists();
22
23    // Start telemetry span
24    let span = CliInitSpanBuilder::new(project_path, exists_before, force).start();
25
26    println!("🚀 Initializing cleanroom test project in current directory");
27
28    if exists_before {
29        if !force {
30            let error = CleanroomError::validation_error("Project already initialized")
31                .with_context("Use --force to reinitialize");
32
33            span.finish(
34                false,
35                false,
36                None,
37                0,
38                Some(("ConfigAlreadyExists".to_string(), error.to_string())),
39            );
40
41            return Err(error);
42        }
43        println!("Reinitializing existing project (--force flag used)");
44    }
45
46    // Track created files for telemetry
47    let mut files_created = 0;
48
49    // Create directory structure
50    std::fs::create_dir_all(tests_dir)?;
51    std::fs::create_dir_all(scenarios_dir)?;
52
53    // Create basic test file
54    let test_content = r#"# Cleanroom Test Definition
55# Generated by clnrm init
56
57[test.metadata]
58name = "basic_test"
59description = "Basic integration test"
60timeout = "120s"
61
62[services.test_container]
63type = "generic_container"
64image = "alpine:latest"
65
66[[steps]]
67name = "hello_world"
68command = ["echo", "Hello from cleanroom!"]
69expected_output_regex = "Hello from cleanroom!"
70
71[[steps]]
72name = "verify_environment"
73command = ["uname", "-s"]
74expected_output_regex = "Linux"
75"#;
76
77    std::fs::write(&basic_test_file, test_content)?;
78    files_created += 1;
79
80    let config_path = basic_test_file.to_string_lossy().to_string();
81
82    // Create README
83    let readme_content = r#"# Cleanroom Test Project
84
85This project uses the cleanroom testing framework for hermetic integration testing.
86
87## Quick Start
88
89```bash
90# Run tests
91clnrm run tests/
92
93# Validate configuration
94clnrm validate tests/
95
96# Show available plugins
97clnrm plugins
98```
99
100## Project Structure
101
102- `tests/` - Test definition files (.clnrm.toml)
103- `scenarios/` - Test scenario definitions
104- `cleanroom.toml` - Optional framework configuration
105- `README.md` - This file
106
107## Framework Self-Testing
108
109This project demonstrates the cleanroom framework testing itself through the "eat your own dog food" principle.
110"#;
111
112    std::fs::write("README.md", readme_content)?;
113    files_created += 1;
114
115    // Create cleanroom.toml if requested
116    if with_config {
117        let config_content = r#"# Cleanroom Framework Configuration (optional)
118# The framework works without this file - only add when customizing
119
120[project]
121name = "my-project"
122version = "0.1.0"
123
124# Uncomment to enable parallel execution
125# [cli]
126# parallel = true
127# jobs = 4
128
129# Uncomment to enable container reuse (10-50x faster)
130# [containers]
131# reuse_enabled = true
132# default_image = "alpine:latest"
133
134# See docs for all options: https://docs.cleanroom.dev/config
135"#;
136        std::fs::write("cleanroom.toml", config_content)?;
137        files_created += 1;
138        println!("✅ Project initialized successfully with configuration");
139        println!("📁 Created: tests/basic.clnrm.toml, cleanroom.toml, README.md");
140    } else {
141        println!("✅ Project initialized successfully (zero-config)");
142        println!("📁 Created: tests/basic.clnrm.toml, README.md");
143    }
144
145    // Finish telemetry span with success
146    span.finish(true, true, Some(config_path), files_created, None);
147
148    Ok(())
149}