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(
9    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"
10)]
11pub struct Cli {
12    #[command(subcommand)]
13    pub command: Commands,
14
15    /// Path to configuration file
16    #[arg(short, long, global = true, value_name = "FILE")]
17    pub config: Option<PathBuf>,
18
19    /// Enable verbose logging (-v for info, -vv for debug, -vvv for trace)
20    #[arg(short, long, global = true, action = clap::ArgAction::Count)]
21    pub verbose: u8,
22
23    /// Suppress all output except errors
24    #[arg(short, long, global = true)]
25    pub quiet: bool,
26
27    /// Output in JSON format where applicable
28    #[arg(long, global = true)]
29    pub json: bool,
30
31    /// Clear the update check cache and force a new check
32    #[arg(long, global = true)]
33    pub clear_update_cache: bool,
34}
35
36#[derive(Subcommand)]
37pub enum Commands {
38    /// Analyze a project and display detected components
39    Analyze {
40        /// Path to the project directory to analyze
41        #[arg(value_name = "PROJECT_PATH")]
42        path: PathBuf,
43
44        /// Output analysis results in JSON format
45        #[arg(short, long)]
46        json: bool,
47
48        /// Show detailed analysis information (legacy format)
49        #[arg(short, long, conflicts_with = "display")]
50        detailed: bool,
51
52        /// Display format for analysis results
53        #[arg(long, value_enum, default_value = "matrix")]
54        display: Option<DisplayFormat>,
55
56        /// Only analyze specific aspects (languages, frameworks, dependencies)
57        #[arg(long, value_delimiter = ',')]
58        only: Option<Vec<String>>,
59
60        /// Color scheme for terminal output (auto-detect, dark, light)
61        #[arg(long, value_enum, default_value = "auto")]
62        color_scheme: Option<ColorScheme>,
63    },
64
65    /// Generate IaC files for a project
66    Generate {
67        /// Path to the project directory to analyze
68        #[arg(value_name = "PROJECT_PATH")]
69        path: PathBuf,
70
71        /// Output directory for generated files
72        #[arg(short, long, value_name = "OUTPUT_DIR")]
73        output: Option<PathBuf>,
74
75        /// Generate Dockerfile
76        #[arg(long)]
77        dockerfile: bool,
78
79        /// Generate Docker Compose file
80        #[arg(long)]
81        compose: bool,
82
83        /// Generate Terraform configuration
84        #[arg(long)]
85        terraform: bool,
86
87        /// Generate all supported IaC files
88        #[arg(long, conflicts_with_all = ["dockerfile", "compose", "terraform"])]
89        all: bool,
90
91        /// Perform a dry run without creating files
92        #[arg(long)]
93        dry_run: bool,
94
95        /// Overwrite existing files
96        #[arg(long)]
97        force: bool,
98    },
99
100    /// Validate existing IaC files against best practices
101    Validate {
102        /// Path to the directory containing IaC files
103        #[arg(value_name = "PATH")]
104        path: PathBuf,
105
106        /// Types of files to validate
107        #[arg(long, value_delimiter = ',')]
108        types: Option<Vec<String>>,
109
110        /// Fix issues automatically where possible
111        #[arg(long)]
112        fix: bool,
113    },
114
115    /// Show supported languages and frameworks
116    Support {
117        /// Show only languages
118        #[arg(long)]
119        languages: bool,
120
121        /// Show only frameworks
122        #[arg(long)]
123        frameworks: bool,
124
125        /// Show detailed information
126        #[arg(short, long)]
127        detailed: bool,
128    },
129
130    /// Analyze project dependencies in detail
131    Dependencies {
132        /// Path to the project directory to analyze
133        #[arg(value_name = "PROJECT_PATH")]
134        path: PathBuf,
135
136        /// Show license information for dependencies
137        #[arg(long)]
138        licenses: bool,
139
140        /// Check for known vulnerabilities
141        #[arg(long)]
142        vulnerabilities: bool,
143
144        /// Show only production dependencies
145        #[arg(long, conflicts_with = "dev_only")]
146        prod_only: bool,
147
148        /// Show only development dependencies
149        #[arg(long, conflicts_with = "prod_only")]
150        dev_only: bool,
151
152        /// Output format
153        #[arg(long, value_enum, default_value = "table")]
154        format: OutputFormat,
155    },
156
157    /// Check dependencies for known vulnerabilities
158    Vulnerabilities {
159        /// Check vulnerabilities in a specific path
160        #[arg(default_value = ".")]
161        path: PathBuf,
162
163        /// Show only vulnerabilities with severity >= threshold
164        #[arg(long, value_enum)]
165        severity: Option<SeverityThreshold>,
166
167        /// Output format
168        #[arg(long, value_enum, default_value = "table")]
169        format: OutputFormat,
170
171        /// Export report to file
172        #[arg(long)]
173        output: Option<PathBuf>,
174    },
175
176    /// Perform comprehensive security analysis
177    Security {
178        /// Path to the project directory to analyze
179        #[arg(value_name = "PROJECT_PATH", default_value = ".")]
180        path: PathBuf,
181
182        /// Security scan mode (lightning, fast, balanced, thorough, paranoid)
183        #[arg(long, value_enum, default_value = "thorough")]
184        mode: SecurityScanMode,
185
186        /// Include low severity findings
187        #[arg(long)]
188        include_low: bool,
189
190        /// Skip secrets detection
191        #[arg(long)]
192        no_secrets: bool,
193
194        /// Skip code pattern analysis
195        #[arg(long)]
196        no_code_patterns: bool,
197
198        /// Skip infrastructure analysis (not implemented yet)
199        #[arg(long, hide = true)]
200        no_infrastructure: bool,
201
202        /// Skip compliance checks (not implemented yet)
203        #[arg(long, hide = true)]
204        no_compliance: bool,
205
206        /// Compliance frameworks to check (not implemented yet)
207        #[arg(long, value_delimiter = ',', hide = true)]
208        frameworks: Vec<String>,
209
210        /// Output format
211        #[arg(long, value_enum, default_value = "table")]
212        format: OutputFormat,
213
214        /// Export report to file
215        #[arg(long)]
216        output: Option<PathBuf>,
217
218        /// Exit with error code on security findings
219        #[arg(long)]
220        fail_on_findings: bool,
221    },
222
223    /// Manage vulnerability scanning tools
224    Tools {
225        #[command(subcommand)]
226        command: ToolsCommand,
227    },
228}
229
230#[derive(Subcommand)]
231pub enum ToolsCommand {
232    /// Check which vulnerability scanning tools are installed
233    Status {
234        /// Output format
235        #[arg(long, value_enum, default_value = "table")]
236        format: OutputFormat,
237
238        /// Check tools for specific languages only
239        #[arg(long, value_delimiter = ',')]
240        languages: Option<Vec<String>>,
241    },
242
243    /// Install missing vulnerability scanning tools
244    Install {
245        /// Install tools for specific languages only
246        #[arg(long, value_delimiter = ',')]
247        languages: Option<Vec<String>>,
248
249        /// Also install OWASP Dependency Check (large download)
250        #[arg(long)]
251        include_owasp: bool,
252
253        /// Perform a dry run to show what would be installed
254        #[arg(long)]
255        dry_run: bool,
256
257        /// Skip confirmation prompts
258        #[arg(short, long)]
259        yes: bool,
260    },
261
262    /// Verify that installed tools are working correctly
263    Verify {
264        /// Test tools for specific languages only
265        #[arg(long, value_delimiter = ',')]
266        languages: Option<Vec<String>>,
267
268        /// Show detailed verification output
269        #[arg(short, long)]
270        verbose: bool,
271    },
272
273    /// Show tool installation guides for manual setup
274    Guide {
275        /// Show guide for specific languages only
276        #[arg(long, value_delimiter = ',')]
277        languages: Option<Vec<String>>,
278
279        /// Show platform-specific instructions
280        #[arg(long)]
281        platform: Option<String>,
282    },
283}
284
285#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
286pub enum OutputFormat {
287    Table,
288    Json,
289}
290
291#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
292pub enum DisplayFormat {
293    /// Compact matrix/dashboard view (modern, easy to scan)
294    Matrix,
295    /// Detailed vertical view (legacy format with all details)
296    Detailed,
297    /// Brief summary only
298    Summary,
299}
300
301#[derive(Clone, Copy, Debug, ValueEnum)]
302pub enum ColorScheme {
303    /// Auto-detect terminal background (default)
304    Auto,
305    /// Dark background terminal colors
306    Dark,
307    /// Light background terminal colors
308    Light,
309}
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
312pub enum SeverityThreshold {
313    Low,
314    Medium,
315    High,
316    Critical,
317}
318
319#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
320pub enum SecurityScanMode {
321    /// Lightning fast scan - critical files only (.env, configs)
322    Lightning,
323    /// Fast scan - smart sampling with priority patterns
324    Fast,
325    /// Balanced scan - good coverage with performance optimizations (recommended)
326    Balanced,
327    /// Thorough scan - comprehensive analysis of all files
328    Thorough,
329    /// Paranoid scan - most comprehensive including low-severity findings
330    Paranoid,
331}
332
333impl Cli {
334    /// Initialize logging based on verbosity level
335    pub fn init_logging(&self) {
336        if self.quiet {
337            return;
338        }
339
340        let level = match self.verbose {
341            0 => log::LevelFilter::Warn,
342            1 => log::LevelFilter::Info,
343            2 => log::LevelFilter::Debug,
344            _ => log::LevelFilter::Trace,
345        };
346
347        env_logger::Builder::from_default_env()
348            .filter_level(level)
349            .init();
350    }
351}