dashboard: return problem details directly from client-error handlers

This commit is contained in:
damocles 2026-06-22 15:07:57 +02:00 committed by mara
commit 65ad994c85
8 changed files with 102 additions and 100 deletions

View file

@ -18,7 +18,7 @@ use serde::Deserialize;
use problem_details::ProblemDetails;
use super::{AppState, error_response};
use super::{AppState, error_problem, error_response};
use crate::actions;
use crate::coordinator::Coordinator;
use crate::lifecycle;
@ -180,19 +180,22 @@ pub(super) async fn get_approval_diff(
State(state): State<AppState>,
AxumPath(id): AxumPath<i64>,
axum::extract::Query(q): axum::extract::Query<DiffBaseQuery>,
) -> Response {
) -> Result<Response, ProblemDetails> {
let base = q.base.as_deref().unwrap_or("applied");
let approval = match state.coord.approvals.get(id) {
Ok(Some(a)) => a,
Ok(None) => return error_response(&format!("approval {id} not found")),
Err(e) => return error_response(&format!("approval {id}: {e:#}")),
Ok(None) => return Err(error_problem(&format!("approval {id} not found"))),
Err(e) => return Err(error_problem(&format!("approval {id}: {e:#}"))),
};
if !matches!(approval.kind, hive_sh4re::ApprovalKind::ApplyCommit) {
return error_response("spawn approvals carry no commit to diff");
return Err(error_problem("spawn approvals carry no commit to diff"));
}
let applied = Coordinator::agent_applied_dir(&approval.agent);
if !applied.join(".git").exists() {
return plain_text(format!("(no applied git repo at {})", applied.display()));
return Ok(plain_text(format!(
"(no applied git repo at {})",
applied.display()
)));
}
let target = format!("refs/tags/proposal/{id}");
let base_ref = match base {
@ -212,21 +215,22 @@ pub(super) async fn get_approval_diff(
.map(|n| format!("refs/tags/proposal/{n}"))
}
other => {
return ProblemDetails::from_status_code(StatusCode::BAD_REQUEST)
.with_detail(format!("unknown diff base {other:?}"))
.into_response();
return Err(ProblemDetails::from_status_code(StatusCode::BAD_REQUEST)
.with_detail(format!("unknown diff base {other:?}")));
}
};
let Some(base_ref) = base_ref else {
return plain_text(match base {
return Ok(plain_text(match base {
"approved" => "(no earlier approved proposal to diff against)".to_owned(),
_ => "(no previous proposal to diff against)".to_owned(),
});
}));
};
match git_diff_refs(&applied, &base_ref, &target).await {
Ok(s) if s.is_empty() => plain_text("(identical — no changes vs this base)".to_owned()),
Ok(s) => plain_text(s),
Err(e) => error_response(&format!("git diff: {e:#}")),
Ok(s) if s.is_empty() => Ok(plain_text(
"(identical — no changes vs this base)".to_owned(),
)),
Ok(s) => Ok(plain_text(s)),
Err(e) => Err(error_problem(&format!("git diff: {e:#}"))),
}
}