nisse-review: later reviews, replies, rounds, stop and review (M7.5)
Back on a PR it reviewed: a new head gets a later review of the commits since (each one's diff, through the API) and of its earlier points; what was said since gets replies, answered where it was said or skipped with a reason. It signs off once and stays quiet while still happy. Past tuning.review.max_rounds it sums up for the operator and goes quiet, until a push or someone other than the PR's author joins in. An operator's `stop` quiets it; `review` asks for a fresh review. Reviews carry numbered markers and replies their point's key, so recovery posts nothing twice. 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:
1 parent
7e73b8fb37
commit
37bbac7e72
14 files changed
+1268
-157
No files matched your search
@@ -1,11 +1,13 @@
|
||||
"""nisse-review against the real services (Part R, M7.3): a PR in a fresh
|
||||
test repository gets one COMMENT review from the review account, by the
|
||||
local model; an account that could write to a repository is refused.
|
||||
local model, and after a push and a question, a later review at the new
|
||||
head (M7.5); an account that could write to a repository is refused.
|
||||
|
||||
Needs NISSE_REVIEW_GITEA_TOKEN, the review account's token (CI secret; .env
|
||||
locally), besides what every live test needs.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
import uuid
|
||||
@@ -21,10 +23,14 @@ from nisse_review.build import StartupError, build
|
||||
from nisse_review.config import ReviewConfig
|
||||
from nisse_review.review import marker
|
||||
|
||||
# Smoke: every PR runs it (about a minute on the local model), the only
|
||||
# Smoke: every PR runs it (two reviews on the local model), the only
|
||||
# check that the review account, its token and its read-only refusal work.
|
||||
pytestmark = [pytest.mark.integration, pytest.mark.e2e, pytest.mark.smoke]
|
||||
|
||||
TEST_SHOUT = (
|
||||
"from shout import shout\n\n\ndef test_shout():\n assert shout('hi') == 'HI!'\n"
|
||||
)
|
||||
|
||||
|
||||
def review_gitea(url: str) -> GiteaClient:
|
||||
token = os.environ.get("NISSE_REVIEW_GITEA_TOKEN", "")
|
||||
@@ -87,12 +93,32 @@ def test_a_ready_pr_gets_one_comment_review(
|
||||
try:
|
||||
assert built.scheduler.round() is True
|
||||
assert built.scheduler.round() is False # reviewed once, not again
|
||||
first = operator.pull_request(repo.name, pr.number).head_sha
|
||||
mine = [
|
||||
r for r in operator.reviews(repo.name, pr.number) if r.author == account
|
||||
]
|
||||
assert len(mine) == 1
|
||||
assert mine[0].state == "COMMENT" and mine[0].commit == first
|
||||
assert marker(first) in mine[0].body
|
||||
# M7.5: a push and a question get a later review of what changed.
|
||||
operator._request(
|
||||
"POST",
|
||||
f"/repos/{repo.name}/contents/sandbox/test_shout.py",
|
||||
json={
|
||||
"content": base64.b64encode(TEST_SHOUT.encode()).decode(),
|
||||
"message": "Test shout",
|
||||
"branch": "shout",
|
||||
},
|
||||
)
|
||||
operator.post_comment(repo.name, pr.number, "I added a test. Is it enough?")
|
||||
assert built.scheduler.round() is True
|
||||
finally:
|
||||
built.store.close()
|
||||
head = operator.pull_request(repo.name, pr.number).head_sha
|
||||
mine = [
|
||||
r for r in operator.reviews(repo.name, pr.number) if r.author == account
|
||||
second = operator.pull_request(repo.name, pr.number).head_sha
|
||||
assert second != first
|
||||
later = [
|
||||
r
|
||||
for r in operator.reviews(repo.name, pr.number)
|
||||
if r.author == account and marker(second, 2) in r.body
|
||||
]
|
||||
assert len(mine) == 1
|
||||
assert mine[0].state == "COMMENT" and mine[0].commit == head
|
||||
assert marker(head) in mine[0].body
|
||||
assert len(later) == 1 and later[0].commit == second
|
||||
Reference in new issue
Block a user