dongjoon-hyun commented on code in PR #59708:
URL: https://github.com/apache/spark/pull/59708#discussion_r4371925624


##########
dev/merge_spark_pr.py:
##########
@@ -2853,6 +2949,26 @@ def main():
     ...     resolver.assert_not_called()
     ...     confirm.assert_not_called()
 
+    Reapply titles are unwrapped too, so their skip tags apply as well.
+
+    >>> for title in ('Reapply "[MINOR][SQL] Fix"', 'Reapply 
"[SPARK-1234][SQL][FOLLOWUP] Fix"'):
+    ...     update(title, ["master"])
+    ...     reverter.assert_not_called()
+    ...     resolver.assert_not_called()
+    ...     confirm.assert_not_called()
+
+    Nested wrappers are unwrapped before the skip-tag and id checks, so an 
inner
+    skip tag is still honored and an inner id still reaches the revert path. A
+    revert of a reapply is used here because it is a revert both by its 
outermost
+    wrapper, which is how main() sets is_revert today, and by wrapper nesting.
+
+    >>> update('Revert "Reapply "[MINOR][SQL] Fix""', ["master"], 
is_revert=True)
+    >>> reverter.assert_not_called()
+    >>> resolver.assert_not_called()
+    >>> confirm.assert_not_called()
+    >>> update('Revert "Reapply "[SPARK-1234][SQL] Fix""', ["master"], 
is_revert=True)
+    >>> reverter.assert_called_once_with(["master"], "SPARK-1234")
+
     Ordinary merges and reapplies still resolve the issue or add fix versions.
 
     >>> for title in ('[SPARK-1234][SQL] Fix', 'Reapply "[SPARK-1234][SQL] 
Fix"'):

Review Comment:
   Minor: no doctest now checks the id that `resolve_jira_issues` extracts 
(L1871), which is where my item 1 regressed. This loop mocks 
`resolve_jira_issues` as a whole (L2922-L2923), so it only checks that the 
wrapped title is passed on. The `leading_jira_ids('Reapply "[SPARK-1234][SQL] 
Fix"')` doctest added for my item 5 was dropped in 205a17f with the examples 
that repeat `_unwrap_title` inputs. And since my item 15, L1894 passes the 
already-unwrapped `jira_title`, so the `update_jira_for_revert` cases no longer 
reach the unwrap in `leading_jira_ids` with a wrapper either. As a result, if 
L2241 unwrapped only `Revert "..."` (or only one layer), every doctest would 
still pass, while a `Reapply "[SPARK-1234][SQL] Fix"` PR would again skip the 
Epic/Umbrella blocker and the match prompt in `main()` and get `Enter a JIRA id 
[]:` on merge. The #59587 case, a body id on an ordinary merge, is not checked 
on this path either. Could you patch `resolve_jira_issue` instead of 
`resolve_jira_is
 sues` in `update()`, and assert for both titles here that `"SPARK-1234"` 
reaches it, e.g. `resolver.assert_called_once_with(["master"], "Issue resolved 
by pull request 123\\n[https://github.com/apache/spark/pull/123]";, 
"SPARK-1234", title_components=[])`? A body reference such as `Fix mentions 
SPARK-9999` in the first title would cover #59587 as well. Restoring the 
dropped example would be the minimal alternative.



##########
dev/merge_spark_pr.py:
##########
@@ -1888,7 +1888,10 @@ def resolve_jira_issues(title, merge_branches, comment, 
title_components=()):
 def update_jira_for_pr(pr_num, title, merge_branches, title_components, 
is_revert=False):
     skip_jira_title_tags = ("MINOR", "TRIVIAL", "FOLLOWUP")
     tags = set(title_components)
-    jira_title = title[len('Revert "') : -1] if is_revert else title
+    # Revert/Reapply PRs keep their title verbatim, so unwrap before parsing 
to see the
+    # wrapped id, markers, and components.
+    jira_title = _unwrap_title(title)
+    jira_ids = leading_jira_ids(jira_title)
     try:
         parsed = Title.parse(jira_title)
         tags.update(parsed.leading)

Review Comment:
   **A wrapped `[FOLLOW-UP]` is not skipped.** `[FOLLOW-UP]` is a registered 
alias of FOLLOWUP (`Component("FOLLOWUP", ("FOLLOW-UP",))`, L2018), and 
`main()` maps it to FOLLOWUP for ordinary titles (L2487-L2491). A 
Revert/Reapply title keeps `title_components == []`, though, and the components 
added on L1898 are compared raw against `skip_jira_title_tags` (L1901). With 
this code, #54151's title, `Revert "[SPARK-55313][PYTHON][FOLLOW-UP] Only add 
condabin to PATH for pip tests"`, would not be skipped: the script asks to 
update JIRA and calls `revert_jira_issue(..., "SPARK-55313")`, which offers to 
remove the parent ticket's fix versions and to reopen it, although only the 
follow-up was reverted. The same title with `[FOLLOWUP]` is skipped, and so is 
a direct merge of the `[FOLLOW-UP]` title. For `Revert` this predates this PR 
(SPARK-59808). But this PR extends the skip to `Reapply` and nested titles, and 
the description says that a `Reapply` or a revert of a revert of a `[FOLLOWUP]` 
c
 hange now skips the JIRA update, while `Reapply "...[FOLLOW-UP]..."` still 
offers to add fix versions to the parent ticket. Titles have been normalized at 
merge time since SPARK-56979, but 17 of the 617 wrapped subjects in master's 
history use `[FOLLOW-UP]` (22 use `[FOLLOWUP]`), and about 1,200 older commits 
carry it. Could you normalize the components on L1898 as `main()` does, e.g. 
`tags.update(c.tag if (c := Component.find(t)) else t for t in 
parsed.components)`, and add `'Revert "[SPARK-1234][SQL][FOLLOW-UP] Fix"'` to 
the skip-tag loop? A follow-up would also be fine, since `Revert` titles 
already behave this way on master.



##########
dev/merge_spark_pr.py:
##########
@@ -2023,6 +2025,28 @@ def find(cls, token):
 _SPARK_ID_RE = re.compile(r"^SPARK-\d+$", re.IGNORECASE)
 _VERSION_TAG_RE = re.compile(r"^\d+\.(\d+|X)$")
 _LEADING_TAGS = frozenset({"MINOR", "TRIVIAL"})
+# A SPARK id that opens a title without brackets, e.g. the old subject 
"SPARK-49004".
+_BARE_SPARK_ID_RE = re.compile(r"SPARK-[0-9]+\b", re.IGNORECASE | re.ASCII)
+# A Revert "..." / Reapply "..." wrapper, which main() keeps verbatim in the 
PR title.
+_WRAPPER_RE = re.compile(r'(?:Revert|Reapply) "(.*)"', re.DOTALL)
+
+
+def _iter_bracket_tags(raw: str) -> Iterator[Tuple[str, int]]:

Review Comment:
   Nit: `Tuple` is used only here. `Iterator[tuple[str, int]]` would match 
`parse_version`'s `Optional[tuple[int, int, int]]` (L140), the file's only 
other tuple annotation, and keep the import on L47 as `from typing import 
Iterator, List, Optional`.



##########
dev/merge_spark_pr.py:
##########
@@ -2843,6 +2937,8 @@ def main():
     >>> reverter.assert_called_once_with(["branch-4.2"], "SPARK-1234")
     >>> update('Revert "Fix"', ["master"], is_revert=True)
     >>> reverter.assert_called_once_with(["master"], "")
+    >>> update('Revert "SPARK-49004"', ["master"], is_revert=True)

Review Comment:
   Nit: this case runs on `master` and finds its id, so neither sentence of the 
paragraph above it (L2934, "Backport-only runs use the same revert path. A 
missing JIRA id is entered interactively.") describes it. Could you add a 
sentence for it, e.g. "A bare leading id, as in the old subject SPARK-49004, 
still reaches the revert path."? While here, the opening sentence on L2911, 
"Reverts update each referenced JIRA once ...", no longer fits the first case, 
where the referenced SPARK-9999 is deliberately skipped; "each leading JIRA id" 
would.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to