syncable_cli/
cli.rs

1use clap::{Parser, Subcommand, ValueEnum};
2use std::path::PathBuf;
3
4#[derive(Parser)]
5#[command(name = "sync-ctl")]
6#[command(version = env!("CARGO_PKG_VERSION"))]
7#[command(about = "Generate Infrastructure as Code from your codebase")]
8#[command(long_about = "A powerful CLI tool that analyzes your codebase and automatically generates optimized Infrastructure as Code configurations including Dockerfiles, Docker Compose files, and Terraform configurations.")]
9pub struct Cli {
10    #[command(subcommand)]
11    pub command: Commands,
12
13    /// Path to configuration file
14    #[arg(short, long, global = true, value_name = "FILE")]
15    pub config: Option<PathBuf>,
16
17    /// Enable verbose logging (-v for info, -vv for debug, -vvv for trace)
18    #[arg(short, long, global = true, action = clap::ArgAction::Count)]
19    pub verbose: u8,
20
21    /// Suppress all output except errors
22    #[arg(short, long, global = true)]
23    pub quiet: bool,
24
25    /// Output in JSON format where applicable
26    #[arg(long, global = true)]
27    pub json: bool,
28}
29
30#[derive(Subcommand)]
31pub enum Commands {
32    /// Analyze a project and display detected components
33    Analyze {
34        /// Path to the project directory to analyze
35        #[arg(value_name = "PROJECT_PATH")]
36        path: PathBuf,
37
38        /// Output analysis results in JSON format
39        #[arg(short, long)]
40        json: bool,
41
42        /// Show detailed analysis information
43        #[arg(short, long)]
44        detailed: bool,
45
46        /// Only analyze specific aspects (languages, frameworks, dependencies)
47        #[arg(long, value_delimiter = ',')]
48        only: Option<Vec<String>>,
49    },
50
51    /// Generate IaC files for a project
52    Generate {
53        /// Path to the project directory to analyze
54        #[arg(value_name = "PROJECT_PATH")]
55        path: PathBuf,
56
57        /// Output directory for generated files
58        #[arg(short, long, value_name = "OUTPUT_DIR")]
59        output: Option<PathBuf>,
60
61        /// Generate Dockerfile
62        #[arg(long)]
63        dockerfile: bool,
64
65        /// Generate Docker Compose file
66        #[arg(long)]
67        compose: bool,
68
69        /// Generate Terraform configuration
70        #[arg(long)]
71        terraform: bool,
72
73        /// Generate all supported IaC files
74        #[arg(long, conflicts_with_all = ["dockerfile", "compose", "terraform"])]
75        all: bool,
76
77        /// Perform a dry run without creating files
78        #[arg(long)]
79        dry_run: bool,
80
81        /// Overwrite existing files
82        #[arg(long)]
83        force: bool,
84    },
85
86    /// Validate existing IaC files against best practices
87    Validate {
88        /// Path to the directory containing IaC files
89        #[arg(value_name = "PATH")]
90        path: PathBuf,
91
92        /// Types of files to validate
93        #[arg(long, value_delimiter = ',')]
94        types: Option<Vec<String>>,
95
96        /// Fix issues automatically where possible
97        #[arg(long)]
98        fix: bool,
99    },
100
101    /// Show supported languages and frameworks
102    Support {
103        /// Show only languages
104        #[arg(long)]
105        languages: bool,
106
107        /// Show only frameworks
108        #[arg(long)]
109        frameworks: bool,
110
111        /// Show detailed information
112        #[arg(short, long)]
113        detailed: bool,
114    },
115
116    /// Analyze project dependencies in detail
117    Dependencies {
118        /// Path to the project directory to analyze
119        #[arg(value_name = "PROJECT_PATH")]
120        path: PathBuf,
121
122        /// Show license information for dependencies
123        #[arg(long)]
124        licenses: bool,
125
126        /// Check for known vulnerabilities
127        #[arg(long)]
128        vulnerabilities: bool,
129
130        /// Show only production dependencies
131        #[arg(long, conflicts_with = "dev_only")]
132        prod_only: bool,
133
134        /// Show only development dependencies
135        #[arg(long, conflicts_with = "prod_only")]
136        dev_only: bool,
137
138        /// Output format
139        #[arg(long, value_enum, default_value = "table")]
140        format: OutputFormat,
141    },
142
143    /// Check dependencies for known vulnerabilities
144    Vulnerabilities {
145        /// Check vulnerabilities in a specific path
146        #[arg(default_value = ".")]
147        path: PathBuf,
148
149        /// Show only vulnerabilities with severity >= threshold
150        #[arg(long, value_enum)]
151        severity: Option<SeverityThreshold>,
152
153        /// Output format
154        #[arg(long, value_enum, default_value = "table")]
155        format: OutputFormat,
156
157        /// Export report to file
158        #[arg(long)]
159        output: Option<PathBuf>,
160    },
161
162    /// Perform comprehensive security analysis
163    Security {
164        /// Path to the project directory to analyze
165        #[arg(value_name = "PROJECT_PATH", default_value = ".")]
166        path: PathBuf,
167
168        /// Include low severity findings
169        #[arg(long)]
170        include_low: bool,
171
172        /// Skip secrets detection
173        #[arg(long)]
174        no_secrets: bool,
175
176        /// Skip code pattern analysis
177        #[arg(long)]
178        no_code_patterns: bool,
179
180        /// Skip infrastructure analysis (not implemented yet)
181        #[arg(long, hide = true)]
182        no_infrastructure: bool,
183
184        /// Skip compliance checks (not implemented yet)
185        #[arg(long, hide = true)]
186        no_compliance: bool,
187
188        /// Compliance frameworks to check (not implemented yet)
189        #[arg(long, value_delimiter = ',', hide = true)]
190        frameworks: Vec<String>,
191
192        /// Output format
193        #[arg(long, value_enum, default_value = "table")]
194        format: OutputFormat,
195
196        /// Export report to file
197        #[arg(long)]
198        output: Option<PathBuf>,
199
200        /// Exit with error code on security findings
201        #[arg(long)]
202        fail_on_findings: bool,
203    },
204}
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
207pub enum OutputFormat {
208    Table,
209    Json,
210}
211
212#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
213pub enum SeverityThreshold {
214    Low,
215    Medium,
216    High,
217    Critical,
218}
219
220impl Cli {
221    /// Initialize logging based on verbosity level
222    pub fn init_logging(&self) {
223        if self.quiet {
224            return;
225        }
226
227        let level = match self.verbose {
228            0 => log::LevelFilter::Warn,
229            1 => log::LevelFilter::Info,
230            2 => log::LevelFilter::Debug,
231            _ => log::LevelFilter::Trace,
232        };
233
234        env_logger::Builder::from_default_env()
235            .filter_level(level)
236            .init();
237    }
238}