From dd8ed718ae90ee1c81dc7b2558aeb5597084d037 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 27 Sep 2025 16:14:06 +0400 Subject: [PATCH 1/3] [stubsabot] Make sure old branches are removed --- scripts/stubsabot.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/scripts/stubsabot.py b/scripts/stubsabot.py index 60b905fbfb2b..222c1242e348 100755 --- a/scripts/stubsabot.py +++ b/scripts/stubsabot.py @@ -881,6 +881,33 @@ def remove_stubs(distribution: str) -> None: f.writelines(lines) +async def delete_closed_stubsabot_branches(session: aiohttp.ClientSession) -> None: + """Delete `stubsabot/*` branch if the PR is already closed.""" + fork_owner = get_origin_owner() + + branches = subprocess.run(["git", "ls-remote", "--heads", "origin"], capture_output=True, text=True, check=True) + for line in branches.stdout.splitlines(): + _, ref = line.split() + if not ref.startswith(f"refs/heads/{BRANCH_PREFIX}/"): + continue + branch = ref.removeprefix("refs/heads/") + + # Fetch all open PRs for an existing branch: + async with session.get( + f"{TYPESHED_API_URL}/pulls", + params={"state": "open", "head": f"{fork_owner}:{branch}", "base": "main"}, + headers=get_github_api_headers(), + ) as response: + response.raise_for_status() + open_prs = await response.json() + + # If we don't have an open PR for an existing branch, + # it means PR was closed and branch was forgotten to be deleted: + if not open_prs: + print(colored(f"Deleting branch {branch} on origin...", "red")) + subprocess.check_call(["git", "push", "origin", "--delete", branch]) + + async def suggest_typeshed_update(update: Update, session: aiohttp.ClientSession, action_level: ActionLevel) -> None: if action_level <= ActionLevel.nothing: return @@ -1002,6 +1029,9 @@ async def main() -> int: try: conn = aiohttp.TCPConnector(limit_per_host=10) async with aiohttp.ClientSession(connector=conn) as session: + # First we clean the old branches: + await delete_closed_stubsabot_branches(session) + tasks = [ asyncio.create_task(determine_action(distribution, session)) for distribution in dists_to_update From 0d8a472121401335ac3c9dd3ded8b38e97990a35 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 27 Sep 2025 19:12:25 +0400 Subject: [PATCH 2/3] Add debug lines --- scripts/stubsabot.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/stubsabot.py b/scripts/stubsabot.py index 222c1242e348..6eb7d92bf590 100755 --- a/scripts/stubsabot.py +++ b/scripts/stubsabot.py @@ -892,6 +892,7 @@ async def delete_closed_stubsabot_branches(session: aiohttp.ClientSession) -> No continue branch = ref.removeprefix("refs/heads/") + print(f"{branch=}") # Fetch all open PRs for an existing branch: async with session.get( f"{TYPESHED_API_URL}/pulls", @@ -901,11 +902,15 @@ async def delete_closed_stubsabot_branches(session: aiohttp.ClientSession) -> No response.raise_for_status() open_prs = await response.json() + print(len(open_prs)) + """ # If we don't have an open PR for an existing branch, # it means PR was closed and branch was forgotten to be deleted: if not open_prs: print(colored(f"Deleting branch {branch} on origin...", "red")) subprocess.check_call(["git", "push", "origin", "--delete", branch]) + """ + subprocess.check_call(["git", "push", "origin", "--delete", f"refs/heads/{BRANCH_PREFIX}/braintree"]) async def suggest_typeshed_update(update: Update, session: aiohttp.ClientSession, action_level: ActionLevel) -> None: From 5297055ffd2999d701d1766381d6e33321c36b6f Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 27 Sep 2025 19:22:38 +0400 Subject: [PATCH 3/3] Comment delete branch command --- scripts/stubsabot.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/scripts/stubsabot.py b/scripts/stubsabot.py index 6eb7d92bf590..d7cd7b66451c 100755 --- a/scripts/stubsabot.py +++ b/scripts/stubsabot.py @@ -892,7 +892,6 @@ async def delete_closed_stubsabot_branches(session: aiohttp.ClientSession) -> No continue branch = ref.removeprefix("refs/heads/") - print(f"{branch=}") # Fetch all open PRs for an existing branch: async with session.get( f"{TYPESHED_API_URL}/pulls", @@ -902,15 +901,13 @@ async def delete_closed_stubsabot_branches(session: aiohttp.ClientSession) -> No response.raise_for_status() open_prs = await response.json() - print(len(open_prs)) - """ # If we don't have an open PR for an existing branch, # it means PR was closed and branch was forgotten to be deleted: if not open_prs: - print(colored(f"Deleting branch {branch} on origin...", "red")) - subprocess.check_call(["git", "push", "origin", "--delete", branch]) - """ - subprocess.check_call(["git", "push", "origin", "--delete", f"refs/heads/{BRANCH_PREFIX}/braintree"]) + # TODO: Configure permissions to use next code + # print(colored(f"Deleting branch {branch} on origin...", "red")) + # subprocess.check_call(["git", "push", "origin", "--delete", branch]) + print(colored(f"Branch {branch} on origin should be deleted.", "red")) async def suggest_typeshed_update(update: Update, session: aiohttp.ClientSession, action_level: ActionLevel) -> None: