From 31626921cad02680737272ccef43f8def7993e33 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 9 Aug 2026 09:25:59 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20=EC=BD=94=EB=93=9C=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EA=B0=9C=EC=84=A0:=20=EB=B3=B5=EC=9E=A1=EB=8F=84?= =?UTF-8?q?=EB=A5=BC=20=EC=A4=84=EC=9D=B4=EA=B8=B0=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?run=5Fhandoff=20=EB=A6=AC=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/ci/noema_review_handoff.py | 92 +++++++++++++++++------------- 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/scripts/ci/noema_review_handoff.py b/scripts/ci/noema_review_handoff.py index f1b3d6697..39d530785 100644 --- a/scripts/ci/noema_review_handoff.py +++ b/scripts/ci/noema_review_handoff.py @@ -138,6 +138,37 @@ def transient_backoff_seconds(consecutive_failures: int, interval_seconds: float return interval_seconds * multiplier +def _handle_transient_failure( + exc: Exception, + consecutive_failures: int, + attempt: int, + attempts: int, + interval_seconds: float, + context: str, + exhausted_context: str, + log: TextIO, + sleeper: Callable[[float], None], +) -> int: + """Handle a transient GitHub API failure and sleep with backoff.""" + consecutive_failures += 1 + detail = redact_text(str(exc)).strip() or "GitHub API call failed" + if attempt < attempts: + delay = transient_backoff_seconds(consecutive_failures, interval_seconds) + print( + f"Transient GitHub API failure {context} " + f"poll {attempt}/{attempts}: {detail}; retrying in {delay:g}s.", + file=log, + ) + sleeper(delay) + else: + print( + f"{exhausted_context} exhausted its bounded polls after a transient " + f"GitHub API failure: {detail}.", + file=log, + ) + return consecutive_failures + + def run_handoff( repo: str, number: int, @@ -159,25 +190,17 @@ def run_handoff( live_head = fetch_head(repo, number, runner=runner) reviews = fetch_reviews(repo, number, runner=runner) except RuntimeError as exc: - consecutive_failures += 1 - detail = redact_text(str(exc)).strip() or "GitHub API call failed" - if attempt < attempts: - delay = transient_backoff_seconds( - consecutive_failures, - interval_seconds, - ) - print( - "Transient GitHub API failure during Noema handoff " - f"poll {attempt}/{attempts}: {detail}; retrying in {delay:g}s.", - file=log, - ) - sleeper(delay) - else: - print( - "Noema handoff exhausted its bounded polls after a transient " - f"GitHub API failure: {detail}.", - file=log, - ) + consecutive_failures = _handle_transient_failure( + exc, + consecutive_failures, + attempt, + attempts, + interval_seconds, + "during Noema handoff", + "Noema handoff", + log, + sleeper, + ) continue if live_head.lower() != head_sha.lower(): @@ -215,26 +238,17 @@ def run_handoff( try: dispatch_noema(repo, number, head_sha, runner=runner) except RuntimeError as exc: - consecutive_failures += 1 - detail = redact_text(str(exc)).strip() or "GitHub API call failed" - if attempt < attempts: - delay = transient_backoff_seconds( - consecutive_failures, - interval_seconds, - ) - print( - "Transient GitHub API failure while dispatching Noema " - f"on poll {attempt}/{attempts}: {detail}; " - f"retrying in {delay:g}s.", - file=log, - ) - sleeper(delay) - else: - print( - "Noema dispatch exhausted its bounded polls after a " - f"transient GitHub API failure: {detail}.", - file=log, - ) + consecutive_failures = _handle_transient_failure( + exc, + consecutive_failures, + attempt, + attempts, + interval_seconds, + "while dispatching Noema on", + "Noema dispatch", + log, + sleeper, + ) continue dispatched = True print(