fix(delivery): keep the TAIL of a push error — git prints its reason last

A failed push recorded two identical auth lines, a URL, and a branch name cut off
mid-word. The reject reason was on the next line and the 500-char head clamp ate
it, so the artifact preserved the noise and dropped the answer. That is what left
#55 unresolvable: the evidence needed to distinguish "no credentials" from
"non-fast-forward" had been truncated away.

`evaluator_tools::clamp_output` already existed for exactly this — head AND tail
with a byte count of what it dropped, on char boundaries so multi-byte output
cannot panic. Reused rather than reinvented.

Investigation notes recorded on #55. Two hypotheses were disproved by measurement:
push credentials are rebuilt per push from GITEA_TOKEN + repos.clone_url and never
live on disk (the clone-time scrub guarantees it, and every checkout on the host —
including ones that pushed — has an identical credential-free origin), and neither
of the two ways `with_ambient_auth` can silently return an unauthenticated URL
applies here: the clone_url matches its required prefix and the token is non-empty
in a container that predates the failure.

489 tests pass, clippy clean.
This commit is contained in:
Omar Sobh
2026-08-06 11:59:57 -07:00
parent 66f730ad16
commit e31688bac5
+8 -1
View File
@@ -371,7 +371,14 @@ pub async fn capture_phase_diff_at(
could not publish {}: {e}",
c.branch
);
publish_error = Some(e.chars().take(500).collect());
// Both ends, not the first 500 chars. Git prints its
// REASON last — "non-fast-forward", "fetch first",
// "protected branch" — so a head-only clamp keeps the
// noise and drops the answer. A real push failure was
// recorded as two auth lines plus a branch name cut
// off mid-word, with the reject reason gone.
publish_error =
Some(crate::evaluator_tools::clamp_output(&e));
}
}
}