Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions bert_e/tests/unit/test_jira.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Unit tests for check_fix_versions in jira.py.
"""Unit tests for check_fix_versions and _notify_pending_hotfix_if_needed.

Rules:
- Hotfix branch PRs require the exact 4-digit fix version in Jira
Expand All @@ -11,9 +11,13 @@
"""
import pytest
from types import SimpleNamespace
from unittest.mock import MagicMock, patch

from bert_e import exceptions
from bert_e.workflow.gitwaterflow.jira import check_fix_versions
from bert_e.workflow.gitwaterflow.jira import (
check_fix_versions,
_notify_pending_hotfix_if_needed,
)


def _make_issue(*version_names):
Expand Down Expand Up @@ -143,3 +147,47 @@ def test_dev_branch_rejects_mismatch():
_make_job('4.3.19', '5.1.4'),
_make_issue('4.3.18', '5.1.4'),
)


# ---------------------------------------------------------------------------
# _notify_pending_hotfix_if_needed — dedup behaviour
# ---------------------------------------------------------------------------

def _make_notify_job(phantom_hotfix_versions=None):
"""Build a minimal job for _notify_pending_hotfix_if_needed tests."""
cascade = SimpleNamespace(
phantom_hotfix_versions=phantom_hotfix_versions or set(),
)
settings = SimpleNamespace(robot='bert-e')
return SimpleNamespace(
git=SimpleNamespace(cascade=cascade),
settings=settings,
pull_request=MagicMock(),
active_options=[],
)


@patch('bert_e.workflow.gitwaterflow.jira.notify_user')
@patch('bert_e.workflow.gitwaterflow.jira.find_comment', return_value=None)
def test_pending_hotfix_posts_when_not_yet_in_history(mock_find, mock_notify):
"""Reminder is posted when no previous comment with that title exists."""
job = _make_notify_job(phantom_hotfix_versions={'10.0.0.0'})
issue = _make_issue('9.5.3', '10.0.0.0', '10.1.0')
_notify_pending_hotfix_if_needed(job, issue)
mock_notify.assert_called_once()


@patch('bert_e.workflow.gitwaterflow.jira.notify_user')
@patch('bert_e.workflow.gitwaterflow.jira.find_comment',
return_value=MagicMock())
def test_pending_hotfix_skips_when_already_in_history(mock_find, mock_notify):
"""Reminder is NOT posted when a previous comment with that title exists.

This covers the active_options footer dedup fix: even if active_options
changed between runs (making the full text differ), the title-prefix
check prevents a second post.
"""
job = _make_notify_job(phantom_hotfix_versions={'10.0.0.0'})
issue = _make_issue('9.5.3', '10.0.0.0', '10.1.0')
_notify_pending_hotfix_if_needed(job, issue)
mock_notify.assert_not_called()
18 changes: 16 additions & 2 deletions bert_e/workflow/gitwaterflow/jira.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

from bert_e import exceptions
from bert_e.lib import jira as jira_api
from ..pr_utils import notify_user
from ..pr_utils import find_comment, notify_user
from .utils import bypass_jira_check


Expand Down Expand Up @@ -193,13 +193,23 @@ def check_fix_versions(job, issue):
)


_PENDING_HOTFIX_TITLE = '# Pending hotfix branch'


def _notify_pending_hotfix_if_needed(job, issue):
"""Post a one-time reminder when the ticket carries a pre-GA hotfix
fix version (X.Y.Z.0) so the developer knows to open a cherry-pick PR
to the corresponding hotfix branch.

This is an informational message: it is posted at most once per PR
(dont_repeat_if_in_history = NEVER_REPEAT) and never blocks the flow.
and never blocks the flow.

The standard dont_repeat_if_in_history dedup uses the full rendered
message as the match key, which includes the active_options footer.
Because active_options can change between runs (e.g. when
create_integration_branches is added), the footer-sensitive match would
miss a comment posted in an earlier run and post again. We guard with
an explicit title-prefix check first, which is stable across runs.
"""
phantom_versions = job.git.cascade.phantom_hotfix_versions
if not phantom_versions:
Expand All @@ -208,6 +218,10 @@ def _notify_pending_hotfix_if_needed(job, issue):
matching = sorted(phantom_versions & issue_versions)
if not matching:
return
# Stable dedup: any previous comment with this title means skip.
if find_comment(job.pull_request, job.settings.robot,
startswith=_PENDING_HOTFIX_TITLE):
return
reminder = exceptions.PendingHotfixVersionReminder(
issue=issue,
hotfix_versions=matching,
Expand Down
Loading