sync: a cloud session's revision to a reviewed PR gets the heartbeat to review again
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017K4vyY3yUD3GsvoZaAtKkD
This commit is contained in:
1 parent
99a9230d27
commit
520dd56787
1 file changed
+40
-2
+40
-2
@@ -158,6 +158,37 @@ def hand_back(repo: str, card: int, pr: int) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
REVIEWING = ("pr", "needs-human", "no-checks", "checks-failed") # a card whose PR is being or has been reviewed
|
||||
|
||||
|
||||
def revised(repo: str, branch: str, before: str | None) -> list[int]:
|
||||
"""The copy pushed new commits to a branch whose PR is open and already reviewed (a cloud session answering the
|
||||
review): each card the PR closes gets a `dispatched` beat marked `revised`, so the heartbeat reviews the new head
|
||||
and a verdict from before the push no longer counts, and the PR loses `needs-human`. A card not yet reviewed (the
|
||||
heartbeat hasn't adopted the PR) gets nothing: its first review sees the new head anyway. `before` is the home's
|
||||
head of the branch before this import; a branch new to the home is never a revision."""
|
||||
if repo != tm.REPO or not before:
|
||||
return []
|
||||
pr = next((p for p in tm.gh("GET", f"/repos/{repo}/pulls?state=open&limit=50") or []
|
||||
if (p.get("head") or {}).get("ref") == branch), None)
|
||||
if not pr:
|
||||
return []
|
||||
cards = {card_of(branch)} | {int(x) for x in re.findall(r"\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)\b", pr.get("body") or "", re.I)}
|
||||
done = []
|
||||
for c in sorted(x for x in cards if x):
|
||||
beats = [b for b in tm.beats_of(tm.gh("GET", f"/repos/{repo}/issues/{c}/comments?limit=100") or [])
|
||||
if b["beat"] not in ("blocked", "capped")]
|
||||
if not beats or beats[-1]["beat"] not in REVIEWING:
|
||||
continue
|
||||
tm.comment(c, f"☁️ The cloud session pushed a revision to PR #{pr['number']}. The heartbeat reviews it again; "
|
||||
f"a verdict from before the push no longer counts.",
|
||||
{"beat": "dispatched", "pr": pr["number"], "revised": True, "cloud": True})
|
||||
done.append(c)
|
||||
if done and tm.has_label(pr, "needs-human"):
|
||||
tm.unlabel(pr["number"], "needs-human")
|
||||
return done
|
||||
|
||||
|
||||
def ensure_pr(repo: str, work: str, branch: str, base: str, copy: str, where: str) -> int | None:
|
||||
"""A PR on the home for an imported branch, unless one is open for it, it is already in the base, or a PR for it
|
||||
was closed at this same commit (a human or the council said no; a new push brings it back)."""
|
||||
@@ -225,12 +256,18 @@ def sync_repo(entry: dict, home_url: str, force: bool = False) -> dict:
|
||||
if branch in out or not any(fnmatch.fnmatch(branch, p) for p in pats):
|
||||
continue
|
||||
git("fetch", "-q", url, f"+refs/heads/{branch}:refs/copy/{branch}", cwd=work)
|
||||
if mine.get(branch) != sha: # the copy writes this branch: the home takes it as it is
|
||||
moved = mine.get(branch) != sha
|
||||
if moved: # the copy writes this branch: the home takes it as it is
|
||||
git("push", "-q", "--force", home_url, f"refs/copy/{branch}:refs/heads/{branch}", cwd=work)
|
||||
r["imported"].append(branch)
|
||||
n = ensure_pr(repo, work, branch, base, name, where)
|
||||
if n:
|
||||
r["prs"].append(n)
|
||||
elif moved:
|
||||
try:
|
||||
r.setdefault("revised", []).extend(revised(repo, branch, mine.get(branch)))
|
||||
except Exception as e: # noqa: BLE001 the commits are home either way; the next review sees them
|
||||
print(f"revised {branch}: {scrub(str(e))[:200]}")
|
||||
ENV.clear()
|
||||
return report
|
||||
|
||||
@@ -258,7 +295,8 @@ def main() -> int:
|
||||
repo = e.get("repo") or tm.REPO
|
||||
rep = sync_repo(e, authed(f"{tm.SERVER}/{repo}.git", token), force)
|
||||
for c in rep["copies"]:
|
||||
print(f"sync {repo} -> {c['copy']}: out {c['out']} imported {c['imported']} prs {c['prs']} {c['note']}".rstrip())
|
||||
print(f"sync {repo} -> {c['copy']}: out {c['out']} imported {c['imported']} prs {c['prs']} "
|
||||
f"revised {c.get('revised', [])} {c['note']}".rstrip())
|
||||
for b, state in c["out"].items():
|
||||
if state == "diverged" and repo == tm.REPO:
|
||||
flag(repo, c["copy"], b)
|
||||
|
||||
Reference in new issue
Block a user