fix: check Gitea API response status and fallback for PR reviews
Some checks failed
CI / Check (pull_request) Failing after 1m28s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
Some checks failed
CI / Check (pull_request) Failing after 1m28s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
The Gitea tracker was silently swallowing HTTP error responses — only network failures were caught, so 4xx/5xx from Gitea went unnoticed and the agent logged success even when reviews weren't posted. - Add response status checking to create_pr_review, update_issue_status, and add_comment - Add fallback in create_pr_review: if inline comments fail, retry as a plain PR comment so the summary still gets posted Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -98,7 +98,8 @@ impl IssueTracker for GiteaTracker {
|
|||||||
_ => "open",
|
_ => "open",
|
||||||
};
|
};
|
||||||
|
|
||||||
self.http
|
let resp = self
|
||||||
|
.http
|
||||||
.patch(&url)
|
.patch(&url)
|
||||||
.header(
|
.header(
|
||||||
"Authorization",
|
"Authorization",
|
||||||
@@ -109,6 +110,14 @@ impl IssueTracker for GiteaTracker {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| CoreError::IssueTracker(format!("Gitea update issue failed: {e}")))?;
|
.map_err(|e| CoreError::IssueTracker(format!("Gitea update issue failed: {e}")))?;
|
||||||
|
|
||||||
|
if !resp.status().is_success() {
|
||||||
|
let status = resp.status();
|
||||||
|
let text = resp.text().await.unwrap_or_default();
|
||||||
|
return Err(CoreError::IssueTracker(format!(
|
||||||
|
"Gitea update issue returned {status}: {text}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +132,8 @@ impl IssueTracker for GiteaTracker {
|
|||||||
"/repos/{owner}/{repo}/issues/{external_id}/comments"
|
"/repos/{owner}/{repo}/issues/{external_id}/comments"
|
||||||
));
|
));
|
||||||
|
|
||||||
self.http
|
let resp = self
|
||||||
|
.http
|
||||||
.post(&url)
|
.post(&url)
|
||||||
.header(
|
.header(
|
||||||
"Authorization",
|
"Authorization",
|
||||||
@@ -134,6 +144,14 @@ impl IssueTracker for GiteaTracker {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| CoreError::IssueTracker(format!("Gitea add comment failed: {e}")))?;
|
.map_err(|e| CoreError::IssueTracker(format!("Gitea add comment failed: {e}")))?;
|
||||||
|
|
||||||
|
if !resp.status().is_success() {
|
||||||
|
let status = resp.status();
|
||||||
|
let text = resp.text().await.unwrap_or_default();
|
||||||
|
return Err(CoreError::IssueTracker(format!(
|
||||||
|
"Gitea add comment returned {status}: {text}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +176,8 @@ impl IssueTracker for GiteaTracker {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.http
|
let resp = self
|
||||||
|
.http
|
||||||
.post(&url)
|
.post(&url)
|
||||||
.header(
|
.header(
|
||||||
"Authorization",
|
"Authorization",
|
||||||
@@ -173,6 +192,47 @@ impl IssueTracker for GiteaTracker {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| CoreError::IssueTracker(format!("Gitea PR review failed: {e}")))?;
|
.map_err(|e| CoreError::IssueTracker(format!("Gitea PR review failed: {e}")))?;
|
||||||
|
|
||||||
|
if !resp.status().is_success() {
|
||||||
|
let status = resp.status();
|
||||||
|
let text = resp.text().await.unwrap_or_default();
|
||||||
|
|
||||||
|
// If inline comments caused the failure, retry with just the summary body
|
||||||
|
if !comments.is_empty() {
|
||||||
|
tracing::warn!(
|
||||||
|
"Gitea PR review with inline comments failed ({status}): {text}, retrying as plain comment"
|
||||||
|
);
|
||||||
|
let fallback_url =
|
||||||
|
self.api_url(&format!("/repos/{owner}/{repo}/issues/{pr_number}/comments"));
|
||||||
|
let fallback_resp = self
|
||||||
|
.http
|
||||||
|
.post(&fallback_url)
|
||||||
|
.header(
|
||||||
|
"Authorization",
|
||||||
|
format!("token {}", self.token.expose_secret()),
|
||||||
|
)
|
||||||
|
.json(&serde_json::json!({ "body": body }))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
CoreError::IssueTracker(format!("Gitea PR comment fallback failed: {e}"))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if !fallback_resp.status().is_success() {
|
||||||
|
let fb_status = fallback_resp.status();
|
||||||
|
let fb_text = fallback_resp.text().await.unwrap_or_default();
|
||||||
|
return Err(CoreError::IssueTracker(format!(
|
||||||
|
"Gitea PR comment fallback returned {fb_status}: {fb_text}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(CoreError::IssueTracker(format!(
|
||||||
|
"Gitea PR review returned {status}: {text}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user