Skip to content

Commit

Permalink
Improve PR Jira issue matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
webbnh authored and ralphbean committed Feb 4, 2025
1 parent 8b8702b commit cea4b16
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 27 deletions.
41 changes: 23 additions & 18 deletions sync2jira/intermediary.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#
# Authors: Ralph Bean <[email protected]>
import re
from typing import Optional


class Issue(object):
Expand Down Expand Up @@ -277,33 +278,37 @@ def map_fixVersion(mapping, issue):
issue["milestone"] = fixVersion_map.replace("XXX", issue["milestone"])


def matcher(content, comments):
JIRA_REFERENCE = re.compile(r"Relates +to +JIRA:\s*(\w+-\d+)")


def matcher(content: Optional[str], comments: list[dict[str, str]]) -> str:
"""
Helper function to match to a JIRA
Extract the Jira ticket reference from the first instance of the magic
cookie (e.g., "Relates to JIRA: FACTORY-1234") found when searching
through the comments in reverse order. If no reference is found in the
comments, then look in the PR description. This ordering allows later
comments to override earlier ones as well as any reference in the
description.
:param String content: PR description
:param List comments: Comments
:return: JIRA match or None
:rtype: Bool
"""
# Build out a string with all comments and initial_comment
all_data = " "

def find_it(input_str: str) -> str:
match = JIRA_REFERENCE.search(input_str)
return match.group(1) if match else None

for comment in reversed(comments):
all_data += f" {comment['body']}"
if content:
all_data += content
if all_data:
# Parse to extract the JIRA information. 2 types of matches:
# 1 - To match to JIRA issue (i.e. Relates to JIRA: FACTORY-1234)
# 2 - To match to upstream issue (i.e. Relates to Issue: !5)
match_jira = re.findall(r"Relates to JIRA: ([\w]*-[\d]*)", all_data)
if match_jira:
for match in match_jira:
# Assert that the match was correct
if re.match(r"[\w]*-[\d]*", match):
return match
else:
return None
match_str = find_it(comment["body"])
if match_str:
break
else:
match_str = find_it(content)
return match_str


def trim_string(content):
Expand Down
84 changes: 75 additions & 9 deletions tests/test_intermediary.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,18 +229,84 @@ def test_from_github_pr_reopen(self, mock_matcher):

def test_matcher(self):
"""This tests the matcher function"""
# Positive case
content = "Relates to JIRA: XYZ-5678"
comments = [{"body": "Relates to JIRA: ABC-1234"}]
expected = True
actual = bool(i.matcher(content, comments))
assert expected == actual
# Found in content, no comments
expected = "XYZ-5678"
content = f"Relates to JIRA: {expected}"
comments = []
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Found in comment, no content
expected = "XYZ-5678"
content = None
comments = [{"body": f"Relates to JIRA: {expected}"}]
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Found in content, not spanning comments
expected = "XYZ-5678"
content = f"Relates to JIRA: {expected}"
comments = [
{"body": "ABC-1234"},
{"body": "JIRA:"},
{"body": "to"},
{"body": "Relates"},
]
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Found in comment, not contents
expected = "XYZ-5678"
content = "Nothing here"
comments = [
{"body": "Relates"},
{"body": f"Relates to JIRA: {expected}"},
{"body": "stuff"},
]
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Overridden in comment
expected = "XYZ-5678"
content = "Relates to JIRA: ABC-1234"
comments = [
{"body": "Relates"},
{"body": f"Relates to JIRA: {expected}"},
{"body": "stuff"},
]
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Overridden twice in comments
expected = "XYZ-5678"
content = "Relates to JIRA: ABC-1234"
comments = [
{"body": "Relates to JIRA: ABC-1235"},
{"body": f"Relates to JIRA: {expected}"},
{"body": "stuff"},
]
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Funky spacing
expected = "XYZ-5678"
content = f"Relates to JIRA: {expected}"
comments = []
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Funkier spacing
expected = "XYZ-5678"
content = f"Relates to JIRA:{expected}"
comments = []
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# Negative case
content = "No JIRAs here..."
comments = [{"body": "... nor here"}]
expected = False
actual = bool(i.matcher(content, comments))
assert expected == actual
expected = None
actual = i.matcher(content, comments)
self.assertEqual(expected, actual)

# TODO: Add new tests from PR

0 comments on commit cea4b16

Please sign in to comment.