Skip to content

Commit f955646

Browse files
authored
Merge pull request #265 from scality/fix/pending-hotfix-reminder-dedup
Fix PendingHotfixVersionReminder posting on every run
2 parents 1c4f76c + 8bbb73d commit f955646

2 files changed

Lines changed: 66 additions & 4 deletions

File tree

bert_e/tests/unit/test_jira.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Unit tests for check_fix_versions in jira.py.
1+
"""Unit tests for check_fix_versions and _notify_pending_hotfix_if_needed.
22
33
Rules:
44
- Hotfix branch PRs require the exact 4-digit fix version in Jira
@@ -11,9 +11,13 @@
1111
"""
1212
import pytest
1313
from types import SimpleNamespace
14+
from unittest.mock import MagicMock, patch
1415

1516
from bert_e import exceptions
16-
from bert_e.workflow.gitwaterflow.jira import check_fix_versions
17+
from bert_e.workflow.gitwaterflow.jira import (
18+
check_fix_versions,
19+
_notify_pending_hotfix_if_needed,
20+
)
1721

1822

1923
def _make_issue(*version_names):
@@ -143,3 +147,47 @@ def test_dev_branch_rejects_mismatch():
143147
_make_job('4.3.19', '5.1.4'),
144148
_make_issue('4.3.18', '5.1.4'),
145149
)
150+
151+
152+
# ---------------------------------------------------------------------------
153+
# _notify_pending_hotfix_if_needed — dedup behaviour
154+
# ---------------------------------------------------------------------------
155+
156+
def _make_notify_job(phantom_hotfix_versions=None):
157+
"""Build a minimal job for _notify_pending_hotfix_if_needed tests."""
158+
cascade = SimpleNamespace(
159+
phantom_hotfix_versions=phantom_hotfix_versions or set(),
160+
)
161+
settings = SimpleNamespace(robot='bert-e')
162+
return SimpleNamespace(
163+
git=SimpleNamespace(cascade=cascade),
164+
settings=settings,
165+
pull_request=MagicMock(),
166+
active_options=[],
167+
)
168+
169+
170+
@patch('bert_e.workflow.gitwaterflow.jira.notify_user')
171+
@patch('bert_e.workflow.gitwaterflow.jira.find_comment', return_value=None)
172+
def test_pending_hotfix_posts_when_not_yet_in_history(mock_find, mock_notify):
173+
"""Reminder is posted when no previous comment with that title exists."""
174+
job = _make_notify_job(phantom_hotfix_versions={'10.0.0.0'})
175+
issue = _make_issue('9.5.3', '10.0.0.0', '10.1.0')
176+
_notify_pending_hotfix_if_needed(job, issue)
177+
mock_notify.assert_called_once()
178+
179+
180+
@patch('bert_e.workflow.gitwaterflow.jira.notify_user')
181+
@patch('bert_e.workflow.gitwaterflow.jira.find_comment',
182+
return_value=MagicMock())
183+
def test_pending_hotfix_skips_when_already_in_history(mock_find, mock_notify):
184+
"""Reminder is NOT posted when a previous comment with that title exists.
185+
186+
This covers the active_options footer dedup fix: even if active_options
187+
changed between runs (making the full text differ), the title-prefix
188+
check prevents a second post.
189+
"""
190+
job = _make_notify_job(phantom_hotfix_versions={'10.0.0.0'})
191+
issue = _make_issue('9.5.3', '10.0.0.0', '10.1.0')
192+
_notify_pending_hotfix_if_needed(job, issue)
193+
mock_notify.assert_not_called()

bert_e/workflow/gitwaterflow/jira.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
from bert_e import exceptions
2727
from bert_e.lib import jira as jira_api
28-
from ..pr_utils import notify_user
28+
from ..pr_utils import find_comment, notify_user
2929
from .utils import bypass_jira_check
3030

3131

@@ -193,13 +193,23 @@ def check_fix_versions(job, issue):
193193
)
194194

195195

196+
_PENDING_HOTFIX_TITLE = '# Pending hotfix branch'
197+
198+
196199
def _notify_pending_hotfix_if_needed(job, issue):
197200
"""Post a one-time reminder when the ticket carries a pre-GA hotfix
198201
fix version (X.Y.Z.0) so the developer knows to open a cherry-pick PR
199202
to the corresponding hotfix branch.
200203
201204
This is an informational message: it is posted at most once per PR
202-
(dont_repeat_if_in_history = NEVER_REPEAT) and never blocks the flow.
205+
and never blocks the flow.
206+
207+
The standard dont_repeat_if_in_history dedup uses the full rendered
208+
message as the match key, which includes the active_options footer.
209+
Because active_options can change between runs (e.g. when
210+
create_integration_branches is added), the footer-sensitive match would
211+
miss a comment posted in an earlier run and post again. We guard with
212+
an explicit title-prefix check first, which is stable across runs.
203213
"""
204214
phantom_versions = job.git.cascade.phantom_hotfix_versions
205215
if not phantom_versions:
@@ -208,6 +218,10 @@ def _notify_pending_hotfix_if_needed(job, issue):
208218
matching = sorted(phantom_versions & issue_versions)
209219
if not matching:
210220
return
221+
# Stable dedup: any previous comment with this title means skip.
222+
if find_comment(job.pull_request, job.settings.robot,
223+
startswith=_PENDING_HOTFIX_TITLE):
224+
return
211225
reminder = exceptions.PendingHotfixVersionReminder(
212226
issue=issue,
213227
hotfix_versions=matching,

0 commit comments

Comments
 (0)