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    /// Manage vulnerability scanning tools
206    Tools {
207        #[command(subcommand)]
208        command: ToolsCommand,
209    },
210}
211
212#[derive(Subcommand)]
213pub enum ToolsCommand {
214    /// Check which vulnerability scanning tools are installed
215    Status {
216        /// Output format
217        #[arg(long, value_enum, default_value = "table")]
218        format: OutputFormat,
219
220        /// Check tools for specific languages only
221        #[arg(long, value_delimiter = ',')]
222        languages: Option<Vec<String>>,
223    },
224
225    /// Install missing vulnerability scanning tools
226    Install {
227        /// Install tools for specific languages only
228        #[arg(long, value_delimiter = ',')]
229        languages: Option<Vec<String>>,
230
231        /// Also install OWASP Dependency Check (large download)
232        #[arg(long)]
233        include_owasp: bool,
234
235        /// Perform a dry run to show what would be installed
236        #[arg(long)]
237        dry_run: bool,
238
239        /// Skip confirmation prompts
240        #[arg(short, long)]
241        yes: bool,
242    },
243
244    /// Verify that installed tools are working correctly
245    Verify {
246        /// Test tools for specific languages only
247        #[arg(long, value_delimiter = ',')]
248        languages: Option<Vec<String>>,
249
250        /// Show detailed verification output
251        #[arg(short, long)]
252        verbose: bool,
253    },
254
255    /// Show tool installation guides for manual setup
256    Guide {
257        /// Show guide for specific languages only
258        #[arg(long, value_delimiter = ',')]
259        languages: Option<Vec<String>>,
260
261        /// Show platform-specific instructions
262        #[arg(long)]
263        platform: Option<String>,
264    },
265}
266
267#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
268pub enum OutputFormat {
269    Table,
270    Json,
271}
272
273#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
274pub enum SeverityThreshold {
275    Low,
276    Medium,
277    High,
278    Critical,
279}
280
281impl Cli {
282    /// Initialize logging based on verbosity level
283    pub fn init_logging(&self) {
284        if self.quiet {
285            return;
286        }
287
288        let level = match self.verbose {
289            0 => log::LevelFilter::Warn,
290            1 => log::LevelFilter::Info,
291            2 => log::LevelFilter::Debug,
292            _ => log::LevelFilter::Trace,
293        };
294
295        env_logger::Builder::from_default_env()
296            .filter_level(level)
297            .init();
298    }
299}