swarm-controller: answer 404, not 503, for an issue-report on a nonexistent repo
get_issue_report mapped every error from Client::issue_report to 503 (StatusUnavailable) unconditionally. issue_report calls issue_list_issues(org, repo, ...) first, and a Forgejo 404 there — a typo'd or deleted repo — was flattened into the same 503 a genuine forge outage produces, which tells a client to retry a request that will never succeed. Downcast the anyhow error back to forgejo_api::ForgejoError (same pattern main.rs's wanted_error_status uses for swarm_queue_client::Error) and check it structurally against the ApiErrorKind::NotFound / UnexpectedStatusCode(404) shapes forgejo's generated client produces for a 404, rather than string-matching the rendered message. Only that case answers 404, naming the org/repo; every other forge failure still answers 503. Updates the route's OpenAPI response list to document the 404. Closes #4701
This commit is contained in:
parent
d048fee698
commit
244db367c4
2 changed files with 131 additions and 7 deletions
|
|
@ -1103,6 +1103,27 @@ fn folds_into_success(e: &ForgejoError, existing: bool) -> bool {
|
|||
is_confirmed_conflict(e) || (is_ambiguous_validation_failure(e) && existing)
|
||||
}
|
||||
|
||||
/// Whether a forge call failed because the named repo itself doesn't exist —
|
||||
/// forgejo answers a plain HTTP 404 for `owner/repo` not found, which the
|
||||
/// generated client surfaces as `ApiErrorKind::NotFound`. Checked
|
||||
/// defensively against `ApiErrorKind::Other`/`UnexpectedStatusCode` too,
|
||||
/// same dual-check shape [`is_already_exists`] uses for 409/422 — belt and
|
||||
/// braces against a response whose body didn't parse as the expected shape.
|
||||
/// Used by [`crate::issue_report::get_issue_report`] to tell "no such repo"
|
||||
/// (404, retrying won't help) apart from every other forge failure (503,
|
||||
/// might clear up) — see that module for why the distinction matters.
|
||||
pub(crate) fn is_repo_not_found(e: &ForgejoError) -> bool {
|
||||
match e {
|
||||
ForgejoError::ApiError(api) => match api.error_kind() {
|
||||
ApiErrorKind::NotFound { .. } => true,
|
||||
ApiErrorKind::Other(s) => *s == StatusCode::NOT_FOUND,
|
||||
_ => false,
|
||||
},
|
||||
ForgejoError::UnexpectedStatusCode(s) => *s == StatusCode::NOT_FOUND,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn validation_failed_error() -> ForgejoError {
|
||||
ForgejoError::ApiError(ApiErrorKind::ValidationFailed.into())
|
||||
|
|
|
|||
Loading…
Reference in a new issue