[llvm] [Github] Account for cross-repo PRs in prune-unused-branches (PR #181232)
Aiden Grossman via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 13 12:00:11 PST 2026
https://github.com/boomanaiden154 updated https://github.com/llvm/llvm-project/pull/181232
>From 43405b90c7d0124a2eaab78e7df5fc6d227c1a0f Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Thu, 12 Feb 2026 20:31:23 +0000
Subject: [PATCH 1/4] [Github] Account for cross-repo PRs in
prune-unused-branches
Some users (as reported in the discourse thread) use user branches
purely as a diff base for cross repo pull requests. This patch makes it
so that we do not delete branches that are used in this way.
---
.github/workflows/prune-unused-branches.py | 23 ++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/prune-unused-branches.py b/.github/workflows/prune-unused-branches.py
index ac8d87f4241e0..bd4ae90f7382d 100644
--- a/.github/workflows/prune-unused-branches.py
+++ b/.github/workflows/prune-unused-branches.py
@@ -22,11 +22,11 @@ def branch_filter(branch_name):
return [branch.replace("remotes/origin/", "") for branch in filtered_branches]
-def get_branches_from_open_prs(github_token) -> list[str]:
+def query_prs(github_token, extra_query_criteria):
gh = github.Github(auth=github.Auth.Token(github_token))
- query = """
+ query_template = """
query ($after: String) {
- search(query: "is:pr repo:llvm/llvm-project is:open head:users/", type: ISSUE, first: 100, after: $after) {
+ search(query: "is:pr repo:llvm/llvm-project is:open {extra_query_criteria}", type: ISSUE, first: 100, after: $after) {
nodes {
... on PullRequest {
baseRefName
@@ -41,6 +41,7 @@ def get_branches_from_open_prs(github_token) -> list[str]:
}
}
}"""
+ query = query_template.format(extra_query_criteria=extra_query_criteria)
pr_data = []
has_next_page = True
variables = {"after": None}
@@ -54,13 +55,27 @@ def get_branches_from_open_prs(github_token) -> list[str]:
pr_data.extend(prs)
print(f"Processed {len(prs)} PRs")
+ return pr_data
+
+
+def get_branches_from_open_prs(github_token) -> list[str]:
+ pr_data = []
+ pr_data.extend(query_prs(github_token, "head:users/"))
+ # We need to explicitly check cases where the base is a user branch to
+ # ensure we capture branches that are used as a diff base for cross-repo
+ # PRs.
+ pr_data.extend(query_prs(github_token, "base:users/"))
+
user_branches = []
for pr in pr_data:
if not pr["isCrossRepository"]:
if pr["baseRefName"] != "main":
user_branches.append(pr["baseRefName"])
user_branches.append(pr["headRefName"])
- return user_branches
+ else:
+ assert pr["baseRefName"].startswith("users/")
+ user_branches.append(pr["baseRefName"])
+ return list(set(user_branches))
def get_user_branches_to_remove(
>From 7ba412c98dded869367a1b6d23c6000b92951afc Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Thu, 12 Feb 2026 20:57:19 +0000
Subject: [PATCH 2/4] add comment
---
.github/workflows/prune-unused-branches.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/prune-unused-branches.py b/.github/workflows/prune-unused-branches.py
index bd4ae90f7382d..60198b6512225 100644
--- a/.github/workflows/prune-unused-branches.py
+++ b/.github/workflows/prune-unused-branches.py
@@ -75,6 +75,7 @@ def get_branches_from_open_prs(github_token) -> list[str]:
else:
assert pr["baseRefName"].startswith("users/")
user_branches.append(pr["baseRefName"])
+ # Convert to a set to ensure we have no duplicates.
return list(set(user_branches))
>From af2ce97a12f5ae0e37edd0781e4ca9114554e93d Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Fri, 13 Feb 2026 19:01:24 +0000
Subject: [PATCH 3/4] feedback
---
.github/workflows/prune-unused-branches.py | 36 +++++++++++-----------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/prune-unused-branches.py b/.github/workflows/prune-unused-branches.py
index 60198b6512225..79b4b11ebff4b 100644
--- a/.github/workflows/prune-unused-branches.py
+++ b/.github/workflows/prune-unused-branches.py
@@ -22,26 +22,26 @@ def branch_filter(branch_name):
return [branch.replace("remotes/origin/", "") for branch in filtered_branches]
-def query_prs(github_token, extra_query_criteria):
+def query_prs(github_token, extra_query_criteria) -> list[str]:
gh = github.Github(auth=github.Auth.Token(github_token))
query_template = """
- query ($after: String) {
- search(query: "is:pr repo:llvm/llvm-project is:open {extra_query_criteria}", type: ISSUE, first: 100, after: $after) {
- nodes {
- ... on PullRequest {
- baseRefName
- headRefName
- isCrossRepository
- number
- }
- }
- pageInfo {
- hasNextPage
- endCursor
- }
- }
- }"""
- query = query_template.format(extra_query_criteria=extra_query_criteria)
+ query ($after: String) {{
+ search(query: "is:pr repo:llvm/llvm-project is:open {query_param}", type: ISSUE, first: 100, after: $after) {{
+ nodes {{
+ ... on PullRequest {{
+ baseRefName
+ headRefName
+ isCrossRepository
+ number
+ }}
+ }}
+ pageInfo {{
+ hasNextPage
+ endCursor
+ }}
+ }}
+ }}"""
+ query = query_template.format(query_param=extra_query_criteria)
pr_data = []
has_next_page = True
variables = {"after": None}
>From fe29738039c067c0104bec03cb2769253ca8b385 Mon Sep 17 00:00:00 2001
From: Aiden Grossman <aidengrossman at google.com>
Date: Fri, 13 Feb 2026 19:59:55 +0000
Subject: [PATCH 4/4] fix
---
.github/workflows/prune-unused-branches.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/prune-unused-branches.py b/.github/workflows/prune-unused-branches.py
index 79b4b11ebff4b..2e5d04ccdb256 100644
--- a/.github/workflows/prune-unused-branches.py
+++ b/.github/workflows/prune-unused-branches.py
@@ -73,7 +73,10 @@ def get_branches_from_open_prs(github_token) -> list[str]:
user_branches.append(pr["baseRefName"])
user_branches.append(pr["headRefName"])
else:
- assert pr["baseRefName"].startswith("users/")
+ # We want to skip cross-repo PRs where someone has simply used a
+ # users/ branch naming scheme for a branch in their fork.
+ if pr["baseRefName"] == "main":
+ continue
user_branches.append(pr["baseRefName"])
# Convert to a set to ensure we have no duplicates.
return list(set(user_branches))
More information about the llvm-commits
mailing list