diff --git a/hive-forge/src/verbs/dependency.rs b/hive-forge/src/verbs/dependency.rs index 76f5a6cb..7fd82521 100644 --- a/hive-forge/src/verbs/dependency.rs +++ b/hive-forge/src/verbs/dependency.rs @@ -13,6 +13,7 @@ use std::collections::HashSet; use anyhow::{Result, bail}; use clap::{Args as ClapArgs, Subcommand}; +use forgejo_api::ForgejoError; use forgejo_api::structs::IssueMeta; use serde_json::Value; @@ -70,14 +71,18 @@ pub fn run(client: &Client, args: Args) -> Result<()> { /// verify by reading the dependency list back rather than trusting the /// HTTP status this verb family returns. /// -/// Measured: the status code lies in both directions on this endpoint -/// pair. `create` can 500 on a call that actually wrote the -/// edge (an intermittent server-side double-processing, not a client -/// retry — ruled out separately). `remove` can answer `201 Created` on a -/// call that actually deleted the edge, which the typed client's -/// endpoint spec maps to an error since 201 isn't the expected status for -/// a deletion. So a `send()` error here only means "maybe" — the -/// authoritative signal is whether the edge is actually there afterward. +/// Measured: `create` can 500 on a call that actually wrote the edge (an +/// intermittent server-side double-processing, not a client retry — +/// ruled out separately). A `send()` error there only means "maybe" — +/// the authoritative signal is whether the edge is actually there +/// afterward. +/// +/// `remove`'s known quirk is handled below, before it ever reaches this +/// path: the forge always answers `201 Created` for a successful +/// deletion, which the generated client's endpoint spec doesn't expect +/// (it only treats 200 as success for that verb), so that specific +/// status is treated as success outright rather than routed through the +/// read-back below. /// /// Calls that errored are only re-classified as real failures if the /// read-back does NOT show the expected converged state (edge present @@ -107,7 +112,19 @@ fn apply_and_verify( .send() }; if let Err(e) = res { - call_errors.push((*dep, e)); + // `remove` always answers 201 for a successful deletion (not + // the 200 the generated client expects for that verb) — a + // deterministic, always-on mismatch, not a "something else + // went wrong after the write" anomaly, so it's not worth a + // read-back or a warning: just accept it. + let is_remove_201 = !adding + && matches!( + &e, + ForgejoError::UnexpectedStatusCode(code) if *code == reqwest::StatusCode::CREATED + ); + if !is_remove_201 { + call_errors.push((*dep, e)); + } } } if call_errors.is_empty() {