1use crate::auth::{gh_cli, ssh};
7use std::process::Command;
8
9#[derive(Debug, Clone)]
11pub struct CheckResult {
12 pub name: String,
14 pub passed: bool,
16 pub message: String,
18 pub suggestion: Option<String>,
20 pub critical: bool,
22}
23
24pub async fn check_requirements() -> Vec<CheckResult> {
29 match tokio::task::spawn_blocking(check_requirements_sync).await {
30 Ok(results) => results,
31 Err(e) => vec![CheckResult {
32 name: "System checks".to_string(),
33 passed: false,
34 message: format!("failed to run checks: {}", e),
35 suggestion: Some("Try running checks again".to_string()),
36 critical: false,
37 }],
38 }
39}
40
41pub fn check_requirements_sync() -> Vec<CheckResult> {
43 vec![
44 check_git_installed(),
45 check_gh_installed(),
46 check_gh_authenticated(),
47 check_ssh_keys(),
48 check_ssh_github_access(),
49 ]
50}
51
52fn check_git_installed() -> CheckResult {
54 match Command::new("git").arg("--version").output() {
55 Ok(output) if output.status.success() => {
56 let version = String::from_utf8_lossy(&output.stdout).trim().to_string();
57 CheckResult {
58 name: "Git".to_string(),
59 passed: true,
60 message: version,
61 suggestion: None,
62 critical: true,
63 }
64 }
65 _ => CheckResult {
66 name: "Git".to_string(),
67 passed: false,
68 message: "not found".to_string(),
69 suggestion: Some("Install git: https://git-scm.com/downloads".to_string()),
70 critical: true,
71 },
72 }
73}
74
75fn check_gh_installed() -> CheckResult {
77 if gh_cli::is_installed() {
78 let version = Command::new("gh")
79 .arg("--version")
80 .output()
81 .ok()
82 .map(|o| {
83 String::from_utf8_lossy(&o.stdout)
84 .lines()
85 .next()
86 .unwrap_or("")
87 .trim()
88 .to_string()
89 })
90 .unwrap_or_else(|| "installed".to_string());
91 CheckResult {
92 name: "GitHub CLI".to_string(),
93 passed: true,
94 message: version,
95 suggestion: None,
96 critical: true,
97 }
98 } else {
99 CheckResult {
100 name: "GitHub CLI".to_string(),
101 passed: false,
102 message: "not found".to_string(),
103 suggestion: Some("Install from https://cli.github.com/".to_string()),
104 critical: true,
105 }
106 }
107}
108
109fn check_gh_authenticated() -> CheckResult {
111 if !gh_cli::is_installed() {
112 return CheckResult {
113 name: "GitHub Auth".to_string(),
114 passed: false,
115 message: "gh CLI not installed".to_string(),
116 suggestion: Some("Install gh CLI first, then run: gh auth login".to_string()),
117 critical: true,
118 };
119 }
120
121 if gh_cli::is_authenticated() {
122 let username = gh_cli::get_username().unwrap_or_else(|_| "authenticated".to_string());
123 CheckResult {
124 name: "GitHub Auth".to_string(),
125 passed: true,
126 message: format!("logged in as {}", username),
127 suggestion: None,
128 critical: true,
129 }
130 } else {
131 CheckResult {
132 name: "GitHub Auth".to_string(),
133 passed: false,
134 message: "not authenticated".to_string(),
135 suggestion: Some("Run: gh auth login".to_string()),
136 critical: true,
137 }
138 }
139}
140
141fn check_ssh_keys() -> CheckResult {
143 if ssh::has_ssh_keys() {
144 let keys = ssh::get_ssh_key_files();
145 let key_names: Vec<String> = keys
146 .iter()
147 .filter_map(|p| p.file_name().map(|f| f.to_string_lossy().to_string()))
148 .collect();
149 CheckResult {
150 name: "SSH Keys".to_string(),
151 passed: true,
152 message: key_names.join(", "),
153 suggestion: None,
154 critical: false,
155 }
156 } else {
157 CheckResult {
158 name: "SSH Keys".to_string(),
159 passed: false,
160 message: "no SSH keys found in ~/.ssh".to_string(),
161 suggestion: Some(
162 "Generate a key: ssh-keygen -t ed25519 -C \"your_email@example.com\"".to_string(),
163 ),
164 critical: false,
165 }
166 }
167}
168
169fn check_ssh_github_access() -> CheckResult {
171 if ssh::has_github_ssh_access() {
172 CheckResult {
173 name: "SSH GitHub".to_string(),
174 passed: true,
175 message: "authenticated".to_string(),
176 suggestion: None,
177 critical: false,
178 }
179 } else {
180 CheckResult {
181 name: "SSH GitHub".to_string(),
182 passed: false,
183 message: "cannot reach github.com via SSH".to_string(),
184 suggestion: Some(
185 "Add your SSH key to GitHub: https://github.com/settings/keys".to_string(),
186 ),
187 critical: false,
188 }
189 }
190}
191
192#[cfg(test)]
193#[path = "checks_tests.rs"]
194mod tests;