nisse-review: a retried or recovered review keeps its head's CI wait
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m41s
CI / e2e (pull_request) Successful in 7m41s

From nisse-review's own review of #155: a failed run, a posted one and
crash recovery rebuilt the item without seen_at, so a retry skipped the
CI wait. seen_at now carries through, renewed when the head moved during
the review. Also: a test for checks Gitea can't report, and the example
config lists ci_wait_s and ci_grace_s.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J5Utyfzw7gF7UhjRDEtjTk
This commit is contained in:
dongarandClaude Opus 5.5 committed 2026-10-17 04:35:05 +00:00
1 parent 59fba3bb76
commit 637761ba5a
3 files changed
+68 -3

No files matched your search

+41
View File
@@ -394,6 +394,47 @@ def test_a_pr_waiting_on_ci_holds_up_no_other(tmp_path: Path) -> None:
assert (item(w, 7).position, item(w, 8).position) == (READY, REVIEWED)
def test_a_failed_review_keeps_its_heads_wait(tmp_path: Path) -> None:
# nisse-review on #155: a retry lost seen_at and skipped the wait.
clock = Clock()
gitea = FakeGitea(repos={REPO: [pr()]})
prose = [AssistantText(text="I think it's fine.", model="m")]
w = world(tmp_path, Scripted(prose, prose), gitea, clock=clock, attempts=2)
w["scheduler"].round()
assert (item(w).position, pr_of(item(w)).seen_at) == (READY, 1000.0)
def test_a_head_pushed_during_a_failed_review_waits_for_its_ci(
tmp_path: Path,
) -> None:
clock = Clock()
class Pushed(FakeGitea):
def post_review(self, *args: Any, **kwargs: Any) -> int:
clock.now += 50
self.repos[REPO] = [pr(head_sha="fff000")]
self.ci["fff000"] = "pending"
raise GiteaError("422: the head moved")
gitea = Pushed(repos={REPO: [pr()]})
w = world(tmp_path, Scripted(*REVIEW), gitea, clock=clock)
w["scheduler"].round()
assert w["scheduler"].round() is False # the new head's CI is pending
def test_checks_gitea_cannot_report_wait_a_round(tmp_path: Path) -> None:
class NoChecks(FakeGitea):
def checks(self, repo: str, sha: str) -> str:
raise GiteaError("502: bad gateway")
out = io.StringIO()
w = world(tmp_path, Scripted(*REVIEW), NoChecks(repos={REPO: [pr()]}))
w["scheduler"]._oplog = OpLog("t", out)
assert w["scheduler"].round() is False
assert item(w).position == READY
assert '"review.checks_unknown"' in out.getvalue()
def test_a_configured_repository_it_cannot_read_is_left_out() -> None:
gitea = FakeGitea(repos={REPO: []})
out = io.StringIO()