Watch
0
0
Fork
You've already forked hyperhive
0

swarm-controller: fall back to the forge diff when a file read fails, and stop rendering at the cap

A failure reading the changed files (a forge error on a tree or blob, a
truncated tree, a non-base64 blob) or joining the diff task made the PR
read fail, so the review posted no verdict. It now falls back to the
forge's 3-line .diff with "reading the files failed: …" as the note.

render wrote each file's whole diff before wide compared it with
MAX_BYTES. It now writes through a writer that refuses once past the cap,
which stops similar's formatter mid-file, so one huge file costs about
MAX_BYTES of output, not its full diff.
This commit is contained in:
atlas 2026-10-15 07:54:08 +02:00 • committed by mara
commit f4b5e1445b
3 changed files with 82 additions and 31 deletions

View file

@ -1248,7 +1248,8 @@ impl Client {
/// What the review classifier reads of `owner/repo`'s PR `number`: its
/// head commit, its commits oldest first with their full messages, and
/// its unified diff from the merge base: [`pull_diff::wide`]'s, or the
/// forge's `.diff` when the wide one is not read or is too large.
/// forge's `.diff` when the wide one is not read, cannot be read, or is
/// too large.
///
/// # Errors
/// A forge failure, with the [`ForgejoError`] underneath; a 404 on the
@ -1299,12 +1300,15 @@ impl Client {
(Some(reason), _) => Err(reason),
(None, None) => Err("the forge names no merge base".to_owned()),
(None, Some(base)) => {
let files = self
match self
.changed_files(owner, repo, number, &base, &head_sha)
.await?;
tokio::task::spawn_blocking(move || pull_diff::wide(&files))
.await
.context("building the PR's wide diff")?
{
Ok(files) => tokio::task::spawn_blocking(move || pull_diff::wide(&files))
.await
.unwrap_or_else(|e| Err(format!("building the wide diff failed: {e}"))),
Err(e) => Err(format!("reading the files failed: {e:#}")),
}
}
};
let (diff, narrowed) = match wide {
@ -2622,6 +2626,16 @@ mod tests {
read.narrowed.as_deref(),
Some("the forge names no merge base")
);
let unreadable = r#"{"number":7,"requested_reviewers":[],"head":{"sha":"h2"},"merge_base":"mb","changed_files":1}"#;
let (client, _) = pull_forge(unreadable, old, new).await;
let read = client.pull_for_review("o", "r", 7).await.unwrap();
assert_eq!(read.diff, "forge diff\n");
let reason = read.narrowed.expect("a failed file read falls back");
assert!(
reason.starts_with("reading the files failed: read tree h2 of o/r"),
"{reason}"
);
}
/// A root tree with the `.hyperhive` tree and a blob beside it.