landing: verdict window from PR creation; worker test runs become commit statuses
GitHub skips pull_request workflows for commits made with the Actions token, so a Venice worker's own test run is recorded as a commit status and counted as the PR's check. A verdict posted in the same beat as the pr beat now counts. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UpT7eWzeLhRwuYmsSQnbRb
This commit is contained in:
1 parent
c5b20a8654
commit
adae855675
2 files changed
+28
-7
No files matched your search
@@ -80,6 +80,9 @@ class World:
|
||||
return d["pr"]
|
||||
if "/check-runs" in path:
|
||||
return {"check_runs": next(d.get("checks", []) for d in self.gh_pr.values() if d["pr"]["head"]["sha"] in path)}
|
||||
if path.endswith("/status"):
|
||||
return {"statuses": next(d.get("statuses", []) for d in self.gh_pr.values() if d["pr"]["head"]["sha"] in path)}
|
||||
if "/statuses/" in path and method == "POST": self.statuses = getattr(self, "statuses", []) + [body]; return {}
|
||||
if "/issues?state=open" in path:
|
||||
lab = path.split("labels=")[1].split("&")[0]
|
||||
return [{"number": i["number"], "title": i.get("title", ""), "body": i.get("body", ""), "state": "open"}
|
||||
@@ -199,7 +202,7 @@ assert "couldn't find cards" in w.posted[0][1] and w.issues[1]["labels"] == []
|
||||
|
||||
# 13 landing: Approve from a trusted reviewer + green checks -> squash merge, card closed, next card dispatched
|
||||
def pr_world(verdict_body="**Approve** looks right", assoc="NONE", bot=True, checks=None, files=None, extra=None):
|
||||
prd = {"number": 7, "state": "open", "merged_at": None, "head": {"sha": "abc"}, "html_url": "u"}
|
||||
prd = {"number": 7, "state": "open", "merged_at": None, "head": {"sha": "abc"}, "html_url": "u", "created_at": iso(2)}
|
||||
issues = {2: {"number": 2, "title": "next", "body": "Depends on #1\n\nDONE: d", "state": "open", "labels": ["queued"]}}
|
||||
cm = {1: [beat("pr", 1, pr=7)],
|
||||
7: [{"created_at": iso(), "author_association": assoc, "user": {"type": "Bot" if bot else "User"}, "body": verdict_body}]}
|
||||
@@ -249,3 +252,13 @@ assert "PR #42" in w2.posted[0][1]
|
||||
w3 = run(World([card(1, D)], {1: [beat("would-dispatch")]}), {"TIME_MODE": "live", "TIME_WORKER": "venice:kimi"})
|
||||
assert "VENICE_API_KEY" in w3.posted[-1][1]
|
||||
print("ALL OK 4")
|
||||
|
||||
# 15 a commit status from the worker's own test run counts as the check
|
||||
w = pr_world(checks=[]); w.gh_pr[7]["statuses"] = [{"state": "success", "context": "time/worker-run"}]
|
||||
w = run(w, {**K, "TIME_AUTOMERGE": "on"}); assert any(c[0] == "PUT" for c in w.calls), "status should count as a green check"
|
||||
w = pr_world(checks=[]); w.gh_pr[7]["statuses"] = [{"state": "failure", "context": "time/worker-run"}]
|
||||
w = run(w, {**K, "TIME_AUTOMERGE": "on"}); assert not any(c[0] == "PUT" for c in w.calls)
|
||||
# a verdict posted in the same run as the `pr` beat still counts (window starts at PR creation)
|
||||
w = pr_world(); w.comments[1] = [beat("pr", 0, pr=7)]
|
||||
w = run(w, {**K, "TIME_AUTOMERGE": "on"}); assert any(c[0] == "PUT" for c in w.calls)
|
||||
print("ALL OK 5")
|
||||
+14
-6
@@ -309,16 +309,19 @@ def touches_protected(pr_number: int) -> list[str]:
|
||||
def checks(sha: str) -> str:
|
||||
"""pass | pending | fail | none, over every check run on the PR head."""
|
||||
runs = gh("GET", f"/repos/{REPO}/commits/{sha}/check-runs?per_page=100").get("check_runs", [])
|
||||
if not runs:
|
||||
states = gh("GET", f"/repos/{REPO}/commits/{sha}/status").get("statuses", []) # commit statuses count too
|
||||
if not runs and not states:
|
||||
return "none"
|
||||
if any(r["status"] != "completed" for r in runs):
|
||||
if any(r["status"] != "completed" for r in runs) or any(st["state"] == "pending" for st in states):
|
||||
return "pending"
|
||||
return "pass" if all(r["conclusion"] in ("success", "neutral", "skipped") for r in runs) else "fail"
|
||||
ok = all(r["conclusion"] in ("success", "neutral", "skipped") for r in runs) and all(st["state"] == "success" for st in states)
|
||||
return "pass" if ok else "fail"
|
||||
|
||||
|
||||
def land(card: dict, last: dict) -> None:
|
||||
"""Move a card whose PR is up toward merged. Silent while nothing has changed."""
|
||||
n, pr = card["number"], gh("GET", f"/repos/{REPO}/pulls/{last['pr']}")
|
||||
since = pr["created_at"] # any verdict after the PR exists counts; a stale beat time would hide same-run reviews
|
||||
if pr.get("merged_at"):
|
||||
if card.get("state", "open") == "open":
|
||||
gh("PATCH", f"/repos/{REPO}/issues/{n}", {"state": "closed"})
|
||||
@@ -326,7 +329,7 @@ def land(card: dict, last: dict) -> None:
|
||||
return
|
||||
if pr["state"] == "closed" or (os.environ.get("TIME_AUTOMERGE") or "off").strip() != "on":
|
||||
return
|
||||
v = verdict(pr, last["at"])
|
||||
v = verdict(pr, since)
|
||||
if v is None:
|
||||
return
|
||||
if v == "object":
|
||||
@@ -393,7 +396,7 @@ WORKER_RULES = """You are the worker for card #{n} in {repo}: "{title}".
|
||||
|
||||
You have hands: list_files, read_file, write_file (one file per call, full content), run (shell on a checkout of your
|
||||
branch), open_pr. Work on the branch `{branch}`; everything you write lands there. Keep the change small and focused.
|
||||
Read before you write. Run the project's tests or checks if any exist. When it is done and checked, call open_pr once
|
||||
Read before you write. Always `run` the project's tests or checks before opening the PR (that run is the PR's check). When it is done and checked, call open_pr once
|
||||
with a short summary; the PR must close the card, and Time adds that line for you. Do not touch .github/workflows.
|
||||
The card's finish line is: DONE: {done}"""
|
||||
|
||||
@@ -441,8 +444,13 @@ class Hands:
|
||||
self.checkout = None
|
||||
return f"wrote {a['path']}"
|
||||
if name == "run":
|
||||
self.checkout = self.checkout or self._checkout()
|
||||
self.checkout = self._checkout() # fresh: see the latest writes
|
||||
p = subprocess.run(["bash", "-lc", a["command"]], cwd=self.checkout, capture_output=True, text=True, timeout=600)
|
||||
sha = subprocess.run(["git", "rev-parse", "HEAD"], cwd=self.checkout, capture_output=True, text=True).stdout.strip()
|
||||
# GitHub does not run pull_request workflows for commits made with the Actions token, so the worker's own
|
||||
# test run is recorded as a commit status; land() counts statuses as checks.
|
||||
gh("POST", f"/repos/{REPO}/statuses/{sha}", {"state": "success" if p.returncode == 0 else "failure",
|
||||
"context": "time/worker-run", "description": a["command"][:100]})
|
||||
return f"exit {p.returncode}\n{(p.stdout + p.stderr)[-6000:]}"
|
||||
if name == "open_pr":
|
||||
pr = gh("POST", f"/repos/{REPO}/pulls", {"title": a["title"][:200], "head": self.branch, "base": default_branch(),
|
||||
|
||||
Reference in new issue
Block a user