Skip to content

Commit 580f6e6

Browse files
committed
[INFRA] Reconcile all PR-title components with JIRA, not just primary ones
Reconcile every PR-title tag that maps to a JIRA component, primary or not: e.g. [TEST] -> "Tests" and [SHUFFLE] -> "Shuffle" are now handled alongside primary tags like [SQL]. The full mapped set is compared against the ticket's components, and the overwrite/append/keep prompt acts on that set. This drops the earlier primary-only restriction, along with the now-unused Component.find_by_jira_name helper and the primary_only flag on jira_components_from_title_tags. Generated-by: Claude Code (Opus 4.8)
1 parent 452a8d0 commit 580f6e6

1 file changed

Lines changed: 26 additions & 65 deletions

File tree

dev/merge_spark_pr.py

Lines changed: 26 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -665,88 +665,71 @@ def print_jira_issue_summary(issue):
665665
)
666666

667667

668-
def jira_components_from_title_tags(tags, primary_only=False):
668+
def jira_components_from_title_tags(tags):
669669
"""Canonical SPARK JIRA component names implied by PR-title component tags.
670670
671-
Each tag is resolved through the component registry; tags that are not JIRA
671+
Each tag is resolved through the component registry; a tag that maps to a
672+
JIRA component contributes that component's canonical name, whether primary
673+
or not (e.g. [SQL] -> "SQL", [TEST] -> "Tests"). Tags that are not JIRA
672674
components (status markers like [FOLLOWUP]/[MINOR], version tags like [4.X],
673-
or unknown tags) contribute nothing. Aliases normalize to the canonical JIRA
674-
name. With ``primary_only`` set, non-primary components (e.g. [TEST],
675-
[SHUFFLE]) are dropped too, leaving only primary tags. The result preserves
676-
input order and is de-duplicated.
675+
or unknown tags) contribute nothing. Aliases normalize to the canonical
676+
name. The result preserves input order and is de-duplicated.
677677
678678
>>> jira_components_from_title_tags(["SQL", "CORE"])
679679
['SQL', 'Spark Core']
680680
>>> jira_components_from_title_tags(["PYSPARK", "DOCS"])
681681
['PySpark', 'Documentation']
682+
>>> jira_components_from_title_tags(["SQL", "TEST"])
683+
['SQL', 'Tests']
682684
>>> jira_components_from_title_tags(["SQL", "FOLLOWUP", "4.X", "BOGUS"])
683685
['SQL']
684686
>>> jira_components_from_title_tags(["SQL", "SQL"])
685687
['SQL']
686-
>>> jira_components_from_title_tags(["SQL", "TEST"], primary_only=True)
687-
['SQL']
688-
>>> jira_components_from_title_tags(["TEST", "SHUFFLE"], primary_only=True)
689-
[]
690688
"""
691689
names = []
692690
for tag in tags:
693691
c = Component.find(tag)
694-
if c is not None and c.jira_name and (c.primary or not primary_only):
692+
if c is not None and c.jira_name:
695693
names.append(c.jira_name)
696694
return list(dict.fromkeys(names))
697695

698696

699697
def reconcile_jira_components(issue, title_components):
700-
"""Prompt to sync primary JIRA components when they differ from the PR title.
698+
"""Prompt to sync JIRA components when they differ from the PR title.
701699
702700
``title_components`` is the list of normalized PR-title component tags (e.g.
703-
["SQL", "TEST"]). Only primary components are reconciled: the PR title's
704-
primary tags, mapped to canonical JIRA names, are compared as a set against
705-
the issue's current primary components. Non-primary tags (e.g. [TEST]) and
706-
non-primary JIRA components (e.g. "Optimizer") are ignored by the comparison
707-
and preserved by both updates. When the primary sets differ, offer to
708-
overwrite JIRA's primary components with the PR title's, append the PR title's
709-
primary components, or keep JIRA unchanged (the default). Titles with no
710-
primary component (e.g. [MINOR]) are skipped.
701+
["SQL", "TEST"]). Every tag that maps to a JIRA component -- primary or not,
702+
e.g. [SQL] -> "SQL" and [TEST] -> "Tests" -- is reconciled; tags with no JIRA
703+
component ([MINOR], [FOLLOWUP], version tags, unknown tags) are dropped. The
704+
mapped names are compared, as a set, against the issue's current components.
705+
On a mismatch, offer to overwrite JIRA with the PR title's components, append
706+
them to the existing ones, or keep JIRA unchanged (the default).
711707
"""
712-
pr_primary = jira_components_from_title_tags(title_components, primary_only=True)
713-
if not pr_primary:
708+
title_jira_components = jira_components_from_title_tags(title_components)
709+
if not title_jira_components:
714710
return
715-
716711
current = [c.name for c in issue.fields.components]
717-
current_primary = []
718-
current_nonprimary = []
719-
for n in current:
720-
comp = Component.find_by_jira_name(n)
721-
if comp is not None and comp.primary:
722-
current_primary.append(n)
723-
else:
724-
current_nonprimary.append(n)
725-
726-
if set(current_primary) == set(pr_primary):
712+
if set(current) == set(title_jira_components):
727713
return
728714

729715
print()
730716
print("=" * 80)
731-
print("PR title primary components differ from JIRA %s:" % issue.key)
732-
print(" PR title: %s" % ", ".join(pr_primary))
733-
print(" JIRA: %s" % (", ".join(current_primary) if current_primary else "(none)"))
734-
if current_nonprimary:
735-
print(" (non-primary JIRA components, preserved: %s)" % ", ".join(current_nonprimary))
717+
print("PR title components differ from JIRA %s:" % issue.key)
718+
print(" PR title: %s" % ", ".join(title_jira_components))
719+
print(" JIRA: %s" % (", ".join(current) if current else "(none)"))
736720
print("=" * 80)
737721
choice = get_input(
738-
"[o]verwrite JIRA primaries with PR title / [a]ppend PR title / [k]eep JIRA as is "
722+
"[o]verwrite JIRA with PR title / [a]ppend PR title to JIRA / [k]eep JIRA as is "
739723
"(default: keep): ",
740724
{"o": ["o", "overwrite"], "a": ["a", "append"], "k": ["k", "keep", ""]},
741725
)
742726
if choice == "k":
743727
print("Keeping JIRA %s components unchanged." % issue.key)
744728
return
745729
if choice == "o":
746-
# Replace the primary components; keep any non-primary ones already on the issue.
747-
new_names = list(dict.fromkeys(pr_primary + current_nonprimary))
748-
else: # "a": append the PR title's primary components, keeping everything else.
749-
new_names = list(dict.fromkeys(current + pr_primary))
730+
new_names = list(title_jira_components)
731+
else: # "a": append the PR title's components, keeping the existing ones first.
732+
new_names = list(dict.fromkeys(current + title_jira_components))
750733

751734
try:
752735
issue.update(fields={"components": [{"name": n} for n in new_names]})
@@ -975,28 +958,6 @@ def find(cls, token):
975958
return c
976959
return None
977960

978-
@classmethod
979-
def find_by_jira_name(cls, name):
980-
"""Return the Component whose canonical JIRA name is ``name``, or None.
981-
982-
>>> Component.find_by_jira_name("Spark Core").tag
983-
'CORE'
984-
>>> Component.find_by_jira_name("SQL").primary
985-
True
986-
>>> Component.find_by_jira_name("Tests").primary
987-
False
988-
>>> Component.find_by_jira_name("Not A Component") is None
989-
True
990-
>>> Component.find_by_jira_name("") is None
991-
True
992-
"""
993-
if not name:
994-
return None
995-
for c in COMPONENTS:
996-
if c.jira_name == name:
997-
return c
998-
return None
999-
1000961

1001962
# Full SPARK JIRA component list (sorted alphabetically by tag), followed
1002963
# by status markers. Keep in sync with the components in JIRA — fetch the

0 commit comments

Comments
 (0)