Skip to content

Commit b712ec1

Browse files
committed
refactor: improve errors from API management (stephanebouget/github-security-alerts/#22)
Errors management and display can be improved in both CLI and GUI. Errors returned by GitHub API were opaque: no HTTP code, no body. Thus some errors were hidden, even if the origin was the API results. RepoAlerts has been updated to bring the error message to the frontend. HTTP errors management has been reviews with better JSON processing with serde. Add in the GUI a new badge for error cases (red). Closes #22 Assisted-by: Claude Sonnet 4.6 (OpenCode, LLMProxy) Signed-off-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com>
1 parent 5982b1d commit b712ec1

5 files changed

Lines changed: 69 additions & 23 deletions

File tree

src-tauri/src/alerts.rs

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,45 +54,81 @@ pub async fn get_github_security_alerts(app: tauri::AppHandle) -> Result<AlertsR
5454
.await
5555
{
5656
Ok(response) => {
57-
if response.status() == 422 {
58-
// 422 Unprocessable Entity usually means Dependabot is not enabled
59-
eprintln!("Dependabot not enabled for {}", repo);
57+
let status = response.status();
58+
59+
if status == 422 {
60+
// 422 Unprocessable Entity: Dependabot not enabled on this repo
61+
eprintln!("[{}] Dependabot not enabled (HTTP 422)", repo);
6062
repo_alerts.push(RepoAlerts {
6163
name: repo,
6264
alerts: 0,
6365
dependabot_enabled: false,
66+
error: None,
67+
});
68+
} else if !status.is_success() {
69+
// Any other non-2xx: capture the raw body for a useful error message
70+
let body = response.text().await.unwrap_or_default();
71+
let msg = format!("HTTP {} — {}", status.as_u16(), body);
72+
eprintln!("[{}] GitHub API error: {}", repo, msg);
73+
repo_alerts.push(RepoAlerts {
74+
name: repo,
75+
alerts: 0,
76+
dependabot_enabled: false,
77+
error: Some(msg),
6478
});
6579
} else {
66-
match response.json::<Vec<GitHubAlert>>().await {
67-
Ok(alerts) => {
68-
let open_alerts = alerts.iter()
69-
.filter(|a| a.state == "open")
70-
.count();
71-
total_alerts += open_alerts;
72-
repo_alerts.push(RepoAlerts {
73-
name: repo,
74-
alerts: open_alerts,
75-
dependabot_enabled: true,
76-
});
80+
// 2xx: try to parse the JSON body
81+
// Read raw bytes first so we can log them if parsing fails
82+
match response.bytes().await {
83+
Ok(bytes) => {
84+
match serde_json::from_slice::<Vec<GitHubAlert>>(&bytes) {
85+
Ok(alerts) => {
86+
let open_alerts = alerts.iter()
87+
.filter(|a| a.state == "open")
88+
.count();
89+
total_alerts += open_alerts;
90+
repo_alerts.push(RepoAlerts {
91+
name: repo,
92+
alerts: open_alerts,
93+
dependabot_enabled: true,
94+
error: None,
95+
});
96+
}
97+
Err(e) => {
98+
// Log the raw body so we can see what GitHub actually returned
99+
let raw = String::from_utf8_lossy(&bytes);
100+
let msg = format!("JSON parse error: {} — body: {}", e, raw);
101+
eprintln!("[{}] {}", repo, msg);
102+
repo_alerts.push(RepoAlerts {
103+
name: repo,
104+
alerts: 0,
105+
dependabot_enabled: false,
106+
error: Some(format!("JSON parse error: {}", e)),
107+
});
108+
}
109+
}
77110
}
78111
Err(e) => {
79-
eprintln!("Failed to parse alerts for {}: {}", repo, e);
80-
// If parsing fails, assume Dependabot is not enabled
112+
let msg = format!("Error reading response body: {}", e);
113+
eprintln!("[{}] {}", repo, msg);
81114
repo_alerts.push(RepoAlerts {
82115
name: repo,
83116
alerts: 0,
84117
dependabot_enabled: false,
118+
error: Some(msg),
85119
});
86120
}
87121
}
88122
}
89123
}
90124
Err(e) => {
91-
eprintln!("Failed to fetch alerts for {}: {}", repo, e);
125+
let msg = format!("Network error: {}", e);
126+
eprintln!("[{}] {}", repo, msg);
92127
repo_alerts.push(RepoAlerts {
93128
name: repo,
94129
alerts: 0,
95130
dependabot_enabled: false,
131+
error: Some(msg),
96132
});
97133
}
98134
}
@@ -102,4 +138,4 @@ pub async fn get_github_security_alerts(app: tauri::AppHandle) -> Result<AlertsR
102138
total_alerts,
103139
repos: repo_alerts,
104140
})
105-
}
141+
}

src-tauri/src/models.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub struct RepoAlerts {
4848
pub name: String,
4949
pub alerts: usize,
5050
pub dependabot_enabled: bool,
51+
pub error: Option<String>,
5152
}
5253

5354
#[derive(Debug, Serialize, Deserialize)]

src/app/core/services/tauri/tauri.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface RepoAlerts {
1616
name: string;
1717
alerts: number;
1818
dependabot_enabled: boolean;
19+
error?: string;
1920
}
2021

2122
export interface AlertsResponse {

src/app/shared/components/alerts-list/alerts-list.component.html

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,15 @@
6060
</div>
6161
<div
6262
class="repo-badge"
63-
[class.safe]="repo.alerts === 0 && repo.dependabot_enabled"
63+
[class.safe]="repo.alerts === 0 && repo.dependabot_enabled && !repo.error"
6464
[class.danger]="repo.alerts > 0"
65-
[class.disabled]="!repo.dependabot_enabled"
66-
[attr.title]="!repo.dependabot_enabled ? 'Dependabot not enabled' : null"
65+
[class.disabled]="!repo.dependabot_enabled && !repo.error"
66+
[class.error]="!!repo.error"
67+
[attr.title]="repo.error ? repo.error : (!repo.dependabot_enabled ? 'Dependabot not enabled' : null)"
6768
>
68-
<i *ngIf="repo.alerts === 0 && repo.dependabot_enabled" class="ti ti-check"></i>
69-
<i *ngIf="!repo.dependabot_enabled" class="ti ti-minus" style="color: #64748b"></i>
69+
<i *ngIf="repo.alerts === 0 && repo.dependabot_enabled && !repo.error" class="ti ti-check"></i>
70+
<i *ngIf="!repo.dependabot_enabled && !repo.error" class="ti ti-minus" style="color: #64748b"></i>
71+
<i *ngIf="repo.error" class="ti ti-alert-circle"></i>
7072
<span *ngIf="repo.alerts > 0">{{ repo.alerts }}</span>
7173
</div>
7274
</div>

src/app/shared/components/alerts-list/alerts-list.component.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@
179179
color: colors.$text-secondary;
180180
cursor: help;
181181
}
182+
183+
&.error {
184+
background: rgba(colors.$danger-color, 0.1);
185+
color: colors.$danger-color;
186+
cursor: help;
187+
}
182188
}
183189
}
184190

0 commit comments

Comments
 (0)