Skip to content

Commit 3bfa4cb

Browse files
authored
fix: Do not return see_also values not in the same project as whiteboard tag (#1242)
* feature: Add step to allow auto creating of components that do not yet exist in Jira for a project
1 parent 882f2d0 commit 3bfa4cb

File tree

4 files changed

+54
-18
lines changed

4 files changed

+54
-18
lines changed

jbi/bugzilla/models.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,15 @@ def is_assigned(self) -> bool:
173173
return self.assigned_to != "[email protected]"
174174

175175
def extract_from_see_also(self, project_key):
176-
"""Extract Jira Issue Key from see_also if jira url present"""
176+
"""Extract Jira Issue Key from see_also if jira url present for the specified project.
177+
178+
Returns the Jira issue key only if it matches the specified project_key.
179+
If a see_also link points to a different Jira project, it will not be returned,
180+
allowing a new ticket to be created for the specified project.
181+
"""
177182
if not self.see_also or len(self.see_also) == 0:
178183
return None
179184

180-
candidates = []
181185
for url in self.see_also:
182186
try:
183187
parsed_url: ParseResult = urlparse(url=url)
@@ -199,12 +203,11 @@ def extract_from_see_also(self, project_key):
199203
parsed_jira_key = parsed_url.path.rstrip("/").split("/")[-1]
200204
if parsed_jira_key: # URL ending with /
201205
# Issue keys are like `{project_key}-{number}`
206+
# Only return if the key matches the specified project
202207
if parsed_jira_key.startswith(f"{project_key}-"):
203208
return parsed_jira_key
204-
# If not obvious, then keep this link as candidate.
205-
candidates.append(parsed_jira_key)
206209

207-
return candidates[0] if candidates else None
210+
return None
208211

209212

210213
class WebhookRequest(BaseModel, frozen=True):

tests/unit/test_models.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,34 +64,67 @@ def test_override_step_configuration_for_single_action_type():
6464
([], None),
6565
(["foo"], None),
6666
(["fail:/format"], None),
67-
(["foo", "http://jira.net/123"], "123"),
67+
# Non-matching project keys should return None
68+
(["foo", "http://jira.net/123"], None),
6869
(["http://org/123"], None),
6970
(["http://jira.com"], None),
7071
(["http://mozilla.jira.com/"], None),
71-
(["http://mozilla.jira.com/123"], "123"),
72-
(["http://mozilla.jira.com/123/"], "123"),
73-
(["http://mozilla.jira.com/ticket/123"], "123"),
74-
(["http://atlassian.com/ticket/123"], "123"),
75-
(["http://mozilla.jira.com/123", "http://mozilla.jira.com/456"], "123"),
72+
(["http://mozilla.jira.com/123"], None),
73+
(["http://mozilla.jira.com/123/"], None),
74+
(["http://mozilla.jira.com/ticket/123"], None),
75+
(["http://atlassian.com/ticket/123"], None),
76+
(["http://mozilla.jira.com/123", "http://mozilla.jira.com/456"], None),
77+
# Multiple Jira issues from different projects should return None if none match
7678
(
7779
["http://mozilla.jira.com/FOO-123", "http://mozilla.jira.com/BAR-456"],
78-
"FOO-123",
80+
None,
7981
),
82+
# Issue keys that don't match the project format should return None
8083
(
8184
["http://mozilla.jira.com/FOO-123", "http://mozilla.jira.com/JBI456"],
82-
"FOO-123",
85+
None,
8386
),
87+
# Only return issue key if it matches the specified project
8488
(
8589
["http://mozilla.jira.com/FOO-123", "http://mozilla.jira.com/JBI-456"],
8690
"JBI-456",
8791
),
92+
# Test the specific scenario: BZFFX issue shouldn't prevent GENAI creation
93+
(
94+
["http://mozilla.jira.com/BZFFX-123"],
95+
None,
96+
),
8897
],
8998
)
9099
def test_extract_see_also(see_also, expected, bug_factory):
91100
bug = bug_factory(see_also=see_also)
92101
assert bug.extract_from_see_also("JBI") == expected
93102

94103

104+
def test_extract_see_also_different_projects(bug_factory):
105+
"""Test that a bug with a BZFFX issue can still match GENAI project."""
106+
bug = bug_factory(see_also=["http://mozilla.jira.com/browse/BZFFX-123"])
107+
# When looking for GENAI project, should return None (allowing new ticket creation)
108+
assert bug.extract_from_see_also("GENAI") is None
109+
# When looking for BZFFX project, should return the issue key
110+
assert bug.extract_from_see_also("BZFFX") == "BZFFX-123"
111+
112+
113+
def test_extract_see_also_multiple_projects(bug_factory):
114+
"""Test that extract_from_see_also correctly handles bugs linked to multiple projects."""
115+
bug = bug_factory(
116+
see_also=[
117+
"http://mozilla.jira.com/browse/BZFFX-123",
118+
"http://mozilla.jira.com/browse/GENAI-456",
119+
]
120+
)
121+
# Each project should only match its own issue
122+
assert bug.extract_from_see_also("BZFFX") == "BZFFX-123"
123+
assert bug.extract_from_see_also("GENAI") == "GENAI-456"
124+
# Non-matching project should return None
125+
assert bug.extract_from_see_also("FOOBAR") is None
126+
127+
95128
@pytest.mark.parametrize(
96129
"product,component,expected",
97130
[

tests/unit/test_runner.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ def test_runner_ignores_request_if_jira_is_linked_but_without_whiteboard(
276276
)
277277
mocked_bugzilla.get_bug.return_value = webhook.bug
278278

279-
assert webhook.bug.extract_from_see_also(project_key="foo") is not None
279+
# Verify that the bug has a JBI link (matching project), but not for other projects
280+
assert webhook.bug.extract_from_see_also(project_key="JBI") == "JBI-234"
281+
assert webhook.bug.extract_from_see_also(project_key="foo") is None
280282

281283
with pytest.raises(IgnoreInvalidRequestError) as exc_info:
282284
execute_action(request=webhook, actions=actions)

tests/unit/test_steps.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,8 +1378,7 @@ def test_maybe_update_components_create_components_normal_component(
13781378
)
13791379

13801380
mocked_jira.create_component.assert_called_once_with(
1381-
project=action_context.jira.project,
1382-
name="NewComponent",
1381+
{"project": action_context.jira.project, "name": "NewComponent"}
13831382
)
13841383
mocked_jira.update_issue_field.assert_called_with(
13851384
key="JBI-234",
@@ -1419,8 +1418,7 @@ def test_maybe_update_components_create_components_prefix_component(
14191418
)
14201419

14211420
mocked_jira.create_component.assert_called_once_with(
1422-
project=action_context.jira.project,
1423-
name="Firefox::NewComponent",
1421+
{"project": action_context.jira.project, "name": "Firefox::NewComponent"}
14241422
)
14251423
mocked_jira.update_issue_field.assert_called_with(
14261424
key="JBI-234",

0 commit comments

Comments
 (0)