fix(#2565): lenient notifications deserialize in hive-forge read-guard

This commit is contained in:
atlas 2026-07-17 16:27:26 +02:00 committed by mara
commit b670291347
2 changed files with 92 additions and 14 deletions

View file

@ -195,6 +195,33 @@ impl Client {
.map(|b| b.to_vec())
.with_context(|| format!("read bytes for GET {url}"))
}
/// GET a JSON `/api/v1` route and deserialize into `T`, bypassing the
/// typed `forgejo-api` client. Use this where the typed client's
/// structs are too strict against the running Forgejo version: the
/// crate pins one schema, but the server tracks the latest release
/// line, so a drifted field breaks deserialization for the whole
/// call. Callers pass a *lenient* local struct (only the fields they
/// use, all `#[serde(default)]`) so a schema change can't wedge the
/// call. `path` starts with `/` and is relative to `/api/v1`; `query`
/// is appended as URL query parameters.
///
/// # Errors
/// Returns an error on transport failure, a non-2xx response (body
/// included), or if the response body doesn't deserialize into `T`.
pub fn get_api_json<T: serde::de::DeserializeOwned>(
&self,
path: &str,
query: &[(&str, &str)],
) -> Result<T> {
let base = format!("{}/api/v1{path}", self.base);
let url = url::Url::parse_with_params(&base, query.iter().copied())
.with_context(|| format!("build url {base}"))?;
let resp = self.web.get(url.clone()).send().context("GET")?;
let resp = check_status(resp, &format!("GET {url}"))?;
resp.json::<T>()
.with_context(|| format!("decode JSON for GET {url}"))
}
}
/// Split an `owner/name` repo string into its two path segments for