mirror: return concrete Result from trigger, convert to diagnostic at callsite
trigger now returns Result<(), impl Diagnostic + Send + Sync> instead of
miette::Result<()>, keeping MirrorErrors fully private. The callsite in
server.rs converts to miette::Report via the blanket From impl.
Also adds MirrorError::Secret for secret::Error and MirrorError::Quire
for miette::Report (from quire.repo() which returns miette::Result).
https://claude.ai/code/session_01MtUMXi7Z3GCDWQFY8puWpu
diff --git a/quire-server/src/bin/quire/server.rs b/quire-server/src/bin/quire/server.rs
index b39b434..cc2c306 100644
--- a/quire-server/src/bin/quire/server.rs
+++ b/quire-server/src/bin/quire/server.rs
@@ -158,6 +158,6 @@ async fn handle_event_connection(mut stream: tokio::net::UnixStream, quire: Quir
ci::trigger(&quire, &event);
if let Err(e) = mirror::trigger(&quire, &event) {
- tracing::error!(repo = %event.repo, error = %e, "mirror failed");
+ tracing::error!(repo = %event.repo, error = %miette::Report::from(e), "mirror failed");
}
}
diff --git a/quire-server/src/mirror.rs b/quire-server/src/mirror.rs
index 23837af..bd128c4 100644
--- a/quire-server/src/mirror.rs
+++ b/quire-server/src/mirror.rs
@@ -2,20 +2,25 @@
//!
//! Triggered from the push event handler, independent of CI.
-use miette::{Diagnostic, IntoDiagnostic as _};
use quire_core::event::{PushEvent, PushRef};
use thiserror::Error;
use crate::quire::Quire;
-#[derive(Debug, Error, Diagnostic)]
+#[derive(Debug, Error, miette::Diagnostic)]
#[error("mirror: {} ref(s) failed", errors.len())]
struct MirrorErrors {
#[related]
errors: Vec<MirrorError>,
}
-#[derive(Debug, Error, Diagnostic)]
+impl From<MirrorError> for MirrorErrors {
+ fn from(e: MirrorError) -> Self {
+ MirrorErrors { errors: vec![e] }
+ }
+}
+
+#[derive(Debug, Error, miette::Diagnostic)]
enum MirrorError {
#[error("repo not found on disk: {0}")]
RepoNotFound(String),
@@ -29,8 +34,15 @@ enum MirrorError {
#[error(transparent)]
App(#[from] crate::Error),
+ #[error(transparent)]
+ Secret(#[from] quire_core::secret::Error),
+
#[error(transparent)]
Io(#[from] std::io::Error),
+
+ #[error("{0}")]
+ #[diagnostic(transparent)]
+ Quire(miette::Report),
}
/// Mirror updated refs to a configured remote.
@@ -38,19 +50,22 @@ enum MirrorError {
/// Reads `github.mirror-token` from global config for auth. For each updated
/// ref, reads `.quire/config.fnl` at the new SHA to obtain the `github.mirror`
/// URL. Skips repos with no mirror URL configured.
-pub fn trigger(quire: &Quire, event: &PushEvent) -> miette::Result<()> {
- let repo = quire.repo(&event.repo)?;
+pub fn trigger(
+ quire: &Quire,
+ event: &PushEvent,
+) -> Result<(), impl miette::Diagnostic + Send + Sync + 'static> {
+ let repo = quire.repo(&event.repo).map_err(MirrorError::Quire)?;
if !repo.exists() {
return Err(MirrorError::RepoNotFound(event.repo.clone()).into());
}
- let config = quire.global_config().into_diagnostic()?;
+ let config = quire.global_config().map_err(MirrorError::App)?;
let mirror_token = config
.github
.mirror_token
.map(|s| s.reveal().map(str::to_owned))
.transpose()
- .into_diagnostic()?;
+ .map_err(MirrorError::Secret)?;
let errors: Vec<MirrorError> = event
.updated_refs()
@@ -61,7 +76,7 @@ pub fn trigger(quire: &Quire, event: &PushEvent) -> miette::Result<()> {
if errors.is_empty() {
Ok(())
} else {
- Err(MirrorErrors { errors }.into())
+ Err(MirrorErrors { errors })
}
}