Skip to content

Commit ab7bee7

Browse files
committed
Fix PR matching on cleanup
GithubSync.close_existing_prs_for_series() is supposed to close all *other* PRs associated with a series being processed. So far it only looked at the *branch* name (`series/<id>=><base>`), when deciding whether two PRs match. This worked due to a bug, fixed in 88cb274, which caused the oldest series id (branch name) to always be associated with the series name (PR title). Now that the bug is fixed, we have to match by name during clean up, which is what happens in this change. Differential Revision: D79763361 Reviewed-by: Amery Hung <[email protected]> Signed-off-by: Ihor Solodrai <[email protected]>
1 parent 04a966b commit ab7bee7

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

kernel_patches_daemon/branch_worker.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,12 @@ def same_series_different_target(ref: str, other_ref: str) -> bool:
436436
return ref1["series"] == ref2["series"] and ref1["target"] != ref2["target"]
437437

438438

439+
def prs_for_the_same_series(pr1: PullRequest, pr2: PullRequest) -> bool:
440+
return pr1.title == pr2.title or same_series_different_target(
441+
pr1.head.ref, pr2.head.ref
442+
)
443+
444+
439445
def _reset_repo(repo, branch: str) -> None:
440446
"""
441447
Reset the repository into a known good state, with `branch` checked out.

kernel_patches_daemon/github_sync.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
parse_pr_ref,
2121
parsed_pr_ref_ok,
2222
pr_has_label,
23-
same_series_different_target,
23+
prs_for_the_same_series,
2424
)
2525
from kernel_patches_daemon.config import BranchConfig, KPDConfig
2626
from kernel_patches_daemon.github_logs import (
@@ -156,12 +156,19 @@ def close_existing_prs_for_series(
156156
the same series name, but different remote branch and close them.
157157
"""
158158

159-
prs_to_close = [
159+
existing_prs = [
160160
existing_pr
161161
for worker in workers
162162
for existing_pr in worker.prs.values()
163-
if same_series_different_target(pr.head.ref, existing_pr.head.ref)
163+
if existing_pr.number != pr.number
164+
]
165+
166+
prs_to_close = [
167+
existing_pr
168+
for existing_pr in existing_prs
169+
if prs_for_the_same_series(pr, existing_pr)
164170
]
171+
165172
# Remove matching PRs from other workers
166173
for pr_to_close in prs_to_close:
167174
logging.info(

tests/test_branch_worker.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66

77
# pyre-unsafe
88

9-
import os
109
import random
1110
import re
1211
import shutil
1312
import tempfile
1413
import unittest
1514
from dataclasses import dataclass, field
1615
from datetime import datetime
17-
from typing import Any, Dict, List
16+
from typing import Any, Dict, List, Optional
1817
from unittest.mock import MagicMock, patch
1918

2019
import git
@@ -35,6 +34,7 @@
3534
EmailBodyContext,
3635
furnish_ci_email_body,
3736
parse_pr_ref,
37+
prs_for_the_same_series,
3838
same_series_different_target,
3939
temporary_patch_file,
4040
UPSTREAM_REMOTE_NAME,
@@ -892,6 +892,43 @@ def test_same_series_different_target(self) -> None:
892892
)
893893
)
894894

895+
def test_prs_for_the_same_series(self) -> None:
896+
def create_mock_pr(title: Optional[str], head_ref: str) -> MagicMock:
897+
pr = MagicMock()
898+
pr.title = title
899+
pr.head.ref = head_ref
900+
return pr
901+
902+
with self.subTest("same_title_different_series"):
903+
# Title match should return True regardless of series
904+
pr1 = create_mock_pr("Fix memory leak", "series/123=>main")
905+
pr2 = create_mock_pr("Fix memory leak", "series/456=>bpf-next")
906+
self.assertTrue(prs_for_the_same_series(pr1, pr2))
907+
908+
with self.subTest("different_title_same_series_different_target"):
909+
# Same series, different target should return True regardless of title
910+
pr1 = create_mock_pr("Fix memory leak", "series/123=>main")
911+
pr2 = create_mock_pr("Different title", "series/123=>bpf-next")
912+
self.assertTrue(prs_for_the_same_series(pr1, pr2))
913+
914+
with self.subTest("different_title_different_series"):
915+
# No match
916+
pr1 = create_mock_pr("Fix memory leak", "series/123=>main")
917+
pr2 = create_mock_pr("Different title", "series/456=>main")
918+
self.assertFalse(prs_for_the_same_series(pr1, pr2))
919+
920+
with self.subTest("none_vs_string_title"):
921+
# None vs string title should not match
922+
pr1 = create_mock_pr(None, "series/123=>main")
923+
pr2 = create_mock_pr("Fix memory leak", "series/456=>bpf-next")
924+
self.assertFalse(prs_for_the_same_series(pr1, pr2))
925+
926+
with self.subTest("malformed_refs_no_match"):
927+
# Malformed refs with different titles should return False
928+
pr1 = create_mock_pr("Fix memory leak", "invalid-ref-format")
929+
pr2 = create_mock_pr("Different title", "also-invalid")
930+
self.assertFalse(prs_for_the_same_series(pr1, pr2))
931+
895932

896933
class TestGitSeriesAlreadyApplied(unittest.IsolatedAsyncioTestCase):
897934
def setUp(self):

0 commit comments

Comments
 (0)