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 (legacy format)
43        #[arg(short, long, conflicts_with = "display")]
44        detailed: bool,
45
46        /// Display format for analysis results
47        #[arg(long, value_enum, default_value = "matrix")]
48        display: Option<DisplayFormat>,
49
50        /// Only analyze specific aspects (languages, frameworks, dependencies)
51        #[arg(long, value_delimiter = ',')]
52        only: Option<Vec<String>>,
53    },
54
55    /// Generate IaC files for a project
56    Generate {
57        /// Path to the project directory to analyze
58        #[arg(value_name = "PROJECT_PATH")]
59        path: PathBuf,
60
61        /// Output directory for generated files
62        #[arg(short, long, value_name = "OUTPUT_DIR")]
63        output: Option<PathBuf>,
64
65        /// Generate Dockerfile
66        #[arg(long)]
67        dockerfile: bool,
68
69        /// Generate Docker Compose file
70        #[arg(long)]
71        compose: bool,
72
73        /// Generate Terraform configuration
74        #[arg(long)]
75        terraform: bool,
76
77        /// Generate all supported IaC files
78        #[arg(long, conflicts_with_all = ["dockerfile", "compose", "terraform"])]
79        all: bool,
80
81        /// Perform a dry run without creating files
82        #[arg(long)]
83        dry_run: bool,
84
85        /// Overwrite existing files
86        #[arg(long)]
87        force: bool,
88    },
89
90    /// Validate existing IaC files against best practices
91    Validate {
92        /// Path to the directory containing IaC files
93        #[arg(value_name = "PATH")]
94        path: PathBuf,
95
96        /// Types of files to validate
97        #[arg(long, value_delimiter = ',')]
98        types: Option<Vec<String>>,
99
100        /// Fix issues automatically where possible
101        #[arg(long)]
102        fix: bool,
103    },
104
105    /// Show supported languages and frameworks
106    Support {
107        /// Show only languages
108        #[arg(long)]
109        languages: bool,
110
111        /// Show only frameworks
112        #[arg(long)]
113        frameworks: bool,
114
115        /// Show detailed information
116        #[arg(short, long)]
117        detailed: bool,
118    },
119
120    /// Analyze project dependencies in detail
121    Dependencies {
122        /// Path to the project directory to analyze
123        #[arg(value_name = "PROJECT_PATH")]
124        path: PathBuf,
125
126        /// Show license information for dependencies
127        #[arg(long)]
128        licenses: bool,
129
130        /// Check for known vulnerabilities
131        #[arg(long)]
132        vulnerabilities: bool,
133
134        /// Show only production dependencies
135        #[arg(long, conflicts_with = "dev_only")]
136        prod_only: bool,
137
138        /// Show only development dependencies
139        #[arg(long, conflicts_with = "prod_only")]
140        dev_only: bool,
141
142        /// Output format
143        #[arg(long, value_enum, default_value = "table")]
144        format: OutputFormat,
145    },
146
147    /// Check dependencies for known vulnerabilities
148    Vulnerabilities {
149        /// Check vulnerabilities in a specific path
150        #[arg(default_value = ".")]
151        path: PathBuf,
152
153        /// Show only vulnerabilities with severity >= threshold
154        #[arg(long, value_enum)]
155        severity: Option<SeverityThreshold>,
156
157        /// Output format
158        #[arg(long, value_enum, default_value = "table")]
159        format: OutputFormat,
160
161        /// Export report to file
162        #[arg(long)]
163        output: Option<PathBuf>,
164    },
165
166    /// Perform comprehensive security analysis
167    Security {
168        /// Path to the project directory to analyze
169        #[arg(value_name = "PROJECT_PATH", default_value = ".")]
170        path: PathBuf,
171
172        /// Include low severity findings
173        #[arg(long)]
174        include_low: bool,
175
176        /// Skip secrets detection
177        #[arg(long)]
178        no_secrets: bool,
179
180        /// Skip code pattern analysis
181        #[arg(long)]
182        no_code_patterns: bool,
183
184        /// Skip infrastructure analysis (not implemented yet)
185        #[arg(long, hide = true)]
186        no_infrastructure: bool,
187
188        /// Skip compliance checks (not implemented yet)
189        #[arg(long, hide = true)]
190        no_compliance: bool,
191
192        /// Compliance frameworks to check (not implemented yet)
193        #[arg(long, value_delimiter = ',', hide = true)]
194        frameworks: Vec<String>,
195
196        /// Output format
197        #[arg(long, value_enum, default_value = "table")]
198        format: OutputFormat,
199
200        /// Export report to file
201        #[arg(long)]
202        output: Option<PathBuf>,
203
204        /// Exit with error code on security findings
205        #[arg(long)]
206        fail_on_findings: bool,
207    },
208
209    /// Manage vulnerability scanning tools
210    Tools {
211        #[command(subcommand)]
212        command: ToolsCommand,
213    },
214}
215
216#[derive(Subcommand)]
217pub enum ToolsCommand {
218    /// Check which vulnerability scanning tools are installed
219    Status {
220        /// Output format
221        #[arg(long, value_enum, default_value = "table")]
222        format: OutputFormat,
223
224        /// Check tools for specific languages only
225        #[arg(long, value_delimiter = ',')]
226        languages: Option<Vec<String>>,
227    },
228
229    /// Install missing vulnerability scanning tools
230    Install {
231        /// Install tools for specific languages only
232        #[arg(long, value_delimiter = ',')]
233        languages: Option<Vec<String>>,
234
235        /// Also install OWASP Dependency Check (large download)
236        #[arg(long)]
237        include_owasp: bool,
238
239        /// Perform a dry run to show what would be installed
240        #[arg(long)]
241        dry_run: bool,
242
243        /// Skip confirmation prompts
244        #[arg(short, long)]
245        yes: bool,
246    },
247
248    /// Verify that installed tools are working correctly
249    Verify {
250        /// Test tools for specific languages only
251        #[arg(long, value_delimiter = ',')]
252        languages: Option<Vec<String>>,
253
254        /// Show detailed verification output
255        #[arg(short, long)]
256        verbose: bool,
257    },
258
259    /// Show tool installation guides for manual setup
260    Guide {
261        /// Show guide for specific languages only
262        #[arg(long, value_delimiter = ',')]
263        languages: Option<Vec<String>>,
264
265        /// Show platform-specific instructions
266        #[arg(long)]
267        platform: Option<String>,
268    },
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
272pub enum OutputFormat {
273    Table,
274    Json,
275}
276
277#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
278pub enum DisplayFormat {
279    /// Compact matrix/dashboard view (modern, easy to scan)
280    Matrix,
281    /// Detailed vertical view (legacy format with all details)
282    Detailed,  
283    /// Brief summary only
284    Summary,
285}
286
287#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
288pub enum SeverityThreshold {
289    Low,
290    Medium,
291    High,
292    Critical,
293}
294
295impl Cli {
296    /// Initialize logging based on verbosity level
297    pub fn init_logging(&self) {
298        if self.quiet {
299            return;
300        }
301
302        let level = match self.verbose {
303            0 => log::LevelFilter::Warn,
304            1 => log::LevelFilter::Info,
305            2 => log::LevelFilter::Debug,
306            _ => log::LevelFilter::Trace,
307        };
308
309        env_logger::Builder::from_default_env()
310            .filter_level(level)
311            .init();
312    }
313}