From 90d5bf77cbfaa1b1273af5e1f45455ec4db80dda Mon Sep 17 00:00:00 2001 From: donbarbos Date: Thu, 27 Aug 2026 02:08:15 +0400 Subject: [PATCH 1/4] [stubsabot] Add remote_branch_exists --- scripts/stubsabot.py | 47 ++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/scripts/stubsabot.py b/scripts/stubsabot.py index 6e8742ff4908..36e6aa222f94 100755 --- a/scripts/stubsabot.py +++ b/scripts/stubsabot.py @@ -772,36 +772,41 @@ async def update_pull_request_label(*, pr_number: int, session: aiohttp.ClientSe response.raise_for_status() +def remote_branch_exists(branch: str) -> bool: + return ( + subprocess.run(["git", "show-ref", "--verify", "--quiet", f"refs/remotes/origin/{branch}"], check=False).returncode == 0 + ) + + def has_non_stubsabot_commits(branch: str) -> bool: assert not branch.startswith("origin/") - try: - # commits on origin/branch that are not on branch or are - # patch equivalent to a commit on branch - output = subprocess.check_output( - ["git", "log", "--right-only", "--pretty=%an", "--cherry-pick", f"{branch}...origin/{branch}"], - stderr=subprocess.DEVNULL, - ) - return bool(set(output.splitlines()) - {b"stubsabot"}) - except subprocess.CalledProcessError: - # origin/branch does not exist + + if not remote_branch_exists(branch): return False + # commits on origin/branch that are not on branch or are + # patch equivalent to a commit on branch + output = subprocess.check_output( + ["git", "log", "--right-only", "--pretty=%an", "--cherry-pick", f"{branch}...origin/{branch}"], stderr=subprocess.DEVNULL + ) + return bool(set(output.splitlines()) - {b"stubsabot"}) + def latest_commit_is_different_to_last_commit_on_origin(branch: str) -> bool: assert not branch.startswith("origin/") - try: - # https://www.git-scm.com/docs/git-range-diff - # If the number of lines is >1, - # it indicates that something about our commit is different to the last commit - # (Could be the commit "content", or the commit message). - commit_comparison = subprocess.run( - ["git", "range-diff", f"origin/{branch}~1..origin/{branch}", "HEAD~1..HEAD"], check=True, capture_output=True - ) - return len(commit_comparison.stdout.splitlines()) > 1 - except subprocess.CalledProcessError: - # origin/branch does not exist + + if not remote_branch_exists(branch): return True + # https://www.git-scm.com/docs/git-range-diff + # If the number of lines is >1, + # it indicates that something about our commit is different to the last commit + # (Could be the commit "content", or the commit message). + commit_comparison = subprocess.run( + ["git", "range-diff", f"origin/{branch}~1..origin/{branch}", "HEAD~1..HEAD"], check=True, capture_output=True + ) + return len(commit_comparison.stdout.splitlines()) > 1 + class RemoteConflictError(Exception): pass From 520936c398d307da96ac6dbd19a01ab008d2ffa9 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Thu, 27 Aug 2026 10:31:23 +0400 Subject: [PATCH 2/4] add debug info --- scripts/stubsabot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/stubsabot.py b/scripts/stubsabot.py index 36e6aa222f94..ccc6283a7b20 100755 --- a/scripts/stubsabot.py +++ b/scripts/stubsabot.py @@ -773,6 +773,7 @@ async def update_pull_request_label(*, pr_number: int, session: aiohttp.ClientSe def remote_branch_exists(branch: str) -> bool: + subprocess.run(["git", "show-ref"], check=False) return ( subprocess.run(["git", "show-ref", "--verify", "--quiet", f"refs/remotes/origin/{branch}"], check=False).returncode == 0 ) From 66cbdbdac85d9778bb38eb2eb4ae372bb75a7202 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Thu, 27 Aug 2026 10:36:11 +0400 Subject: [PATCH 3/4] update debug --- scripts/stubsabot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/stubsabot.py b/scripts/stubsabot.py index ccc6283a7b20..0bdf2a5fcded 100755 --- a/scripts/stubsabot.py +++ b/scripts/stubsabot.py @@ -773,7 +773,6 @@ async def update_pull_request_label(*, pr_number: int, session: aiohttp.ClientSe def remote_branch_exists(branch: str) -> bool: - subprocess.run(["git", "show-ref"], check=False) return ( subprocess.run(["git", "show-ref", "--verify", "--quiet", f"refs/remotes/origin/{branch}"], check=False).returncode == 0 ) @@ -882,6 +881,8 @@ async def suggest_typeshed_update(update: Update, session: aiohttp.ClientSession meta = update_metadata(update.distribution, version=update.new_version) body = get_update_pr_body(update, meta) subprocess.check_call(["git", "commit", "--all", "-m", f"{title}\n\n{body}"]) + print("[DEBUG]") + subprocess.run(["git", "show-ref"], check=False) if action_level <= ActionLevel.local: return if not latest_commit_is_different_to_last_commit_on_origin(branch_name): From 81abbf06ede3bd541fd0adfddecb9253d270bbdc Mon Sep 17 00:00:00 2001 From: donbarbos Date: Thu, 27 Aug 2026 10:40:17 +0400 Subject: [PATCH 4/4] remove debug info --- scripts/stubsabot.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/stubsabot.py b/scripts/stubsabot.py index 0bdf2a5fcded..36e6aa222f94 100755 --- a/scripts/stubsabot.py +++ b/scripts/stubsabot.py @@ -881,8 +881,6 @@ async def suggest_typeshed_update(update: Update, session: aiohttp.ClientSession meta = update_metadata(update.distribution, version=update.new_version) body = get_update_pr_body(update, meta) subprocess.check_call(["git", "commit", "--all", "-m", f"{title}\n\n{body}"]) - print("[DEBUG]") - subprocess.run(["git", "show-ref"], check=False) if action_level <= ActionLevel.local: return if not latest_commit_is_different_to_last_commit_on_origin(branch_name):