This is an automated email from the ASF dual-hosted git repository.
zhengruifeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new 4988ef161a80 [SPARK-56963][INFRA] Auto-close non-default-branch PRs in
merge_spark_pr.py
4988ef161a80 is described below
commit 4988ef161a809cdf85bea1f143cc0be26a9dd68c
Author: Ruifeng Zheng <[email protected]>
AuthorDate: Wed May 20 18:45:48 2026 +0800
[SPARK-56963][INFRA] Auto-close non-default-branch PRs in merge_spark_pr.py
### What changes were proposed in this pull request?
When `dev/merge_spark_pr.py` merges a PR whose target branch is not the
repository's default (e.g. backport PRs against `branch-X.Y`), explicitly close
the PR through the GitHub REST API after the push. Specifically:
- Add a small `close_pr(pr_num)` helper that issues an authenticated `PATCH
/pulls/{n}` with `{"state": "closed"}`.
- After a successful `git push` in `merge_pr()`, fetch the PR via `GET
/pulls/{n}` and, if the state is still `"open"`, call `close_pr(pr_num)`.
### Why are the changes needed?
The squash-merge commit message already contains `Closes #N from ...`,
which GitHub treats as a closing keyword. However, GitHub honors closing
keywords **only when the commit lands on the repository's default branch**.
Backport PRs that target `branch-X.Y` therefore got merged successfully but
stayed open on GitHub, and the committer had to close them manually. #56004 was
a recent example.
Checking the PR state after the push (instead of comparing `target_ref` to
the default branch up front) keeps the change small and self-correcting: it
does the right thing whenever GitHub's auto-close did not fire, without having
to encode the default-branch rule in the script.
### Does this PR introduce _any_ user-facing change?
No.
### How was this patch tested?
Compile-checked with `python3 -m py_compile dev/merge_spark_pr.py` and the
existing doctests still pass via `python3 -m doctest dev/merge_spark_pr.py`.
End-to-end merge behavior will be validated the next time a committer runs the
script on a backport PR.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 4.7)
Closes #56007 from zhengruifeng/merge-script-close-backport-pr.
Authored-by: Ruifeng Zheng <[email protected]>
Signed-off-by: Ruifeng Zheng <[email protected]>
---
dev/merge_spark_pr.py | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/dev/merge_spark_pr.py b/dev/merge_spark_pr.py
index 795fde6d176e..b630e13b968c 100755
--- a/dev/merge_spark_pr.py
+++ b/dev/merge_spark_pr.py
@@ -345,6 +345,21 @@ def get_json(url):
sys.exit(-1)
+def close_pr(pr_num):
+ url = "%s/pulls/%s" % (GITHUB_API_BASE, pr_num)
+ data = json.dumps({"state": "closed"}).encode("utf-8")
+ request = Request(url, data=data, method="PATCH")
+ request.add_header("Content-Type", "application/json")
+ request.add_header("Accept", "application/vnd.github+json")
+ if GITHUB_OAUTH_KEY:
+ request.add_header("Authorization", "token %s" % GITHUB_OAUTH_KEY)
+ try:
+ return json.load(urlopen(request))
+ except HTTPError as e:
+ print_error("Failed to close PR #%s: HTTP %s %s" % (pr_num, e.code,
e.reason))
+ return None
+
+
def fail(msg):
print_error(msg)
clean_up()
@@ -953,6 +968,14 @@ def main():
merge_hash = merge_pr(pr_num, target_ref, title, body, pr_repo_desc,
pr_author, co_authors)
+ # The "Closes #N" keyword in the commit message only auto-closes the PR
when the commit
+ # lands on the default branch. For merges into other branches (e.g.
branch-X.Y backport
+ # PRs), GitHub leaves the PR open, so close it explicitly through the API.
+ pr_state = get_json("%s/pulls/%s" % (GITHUB_API_BASE, pr_num)).get("state")
+ if pr_state != "closed":
+ print("PR #%s is still open after push; closing it explicitly." %
pr_num)
+ close_pr(pr_num)
+
pick_prompt = "Would you like to pick %s into another branch?" % merge_hash
while bold_input("\n%s (y/N): " % pick_prompt).lower() == "y":
merged_refs = merged_refs + [
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]