From 592cdbad187fde650c6d95a9b7580d5330b38bb9 Mon Sep 17 00:00:00 2001 From: Mathieu Leplatre Date: Tue, 5 Mar 2024 19:12:33 +0100 Subject: [PATCH] Fix #501: add 'maybe_update_issue_milestone' step --- jbi/bugzilla/models.py | 1 + jbi/steps.py | 51 ++++++++++++++++++++++++++++++++++++++++ tests/unit/test_steps.py | 35 +++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/jbi/bugzilla/models.py b/jbi/bugzilla/models.py index 28a7150b..ce072f10 100644 --- a/jbi/bugzilla/models.py +++ b/jbi/bugzilla/models.py @@ -74,6 +74,7 @@ class Bug(BaseModel, frozen=True): creator: Optional[str] = None assigned_to: Optional[str] = None comment: Optional[WebhookComment] = None + milestone: Optional[str] = None # Custom field Firefox for story points cf_fx_points: Optional[str] = None diff --git a/jbi/steps.py b/jbi/steps.py index 8e787f83..e77b20ef 100644 --- a/jbi/steps.py +++ b/jbi/steps.py @@ -11,6 +11,7 @@ from __future__ import annotations import logging +import re from enum import Enum, auto from typing import TYPE_CHECKING, Iterable, Optional @@ -200,6 +201,56 @@ def maybe_assign_jira_user( return (StepStatus.NOOP, context) +def maybe_update_issue_milestone( + context: ActionContext, *, parameters: ActionParams, jira_service: JiraService +) -> StepResult: + """ + Update the Jira issue 'Fix Version' field. + """ + # Do not bother update the field if empty on create or if another field is updated. + if (context.operation == Operation.CREATE and not context.bug.milestone) or ( + context.operation == Operation.UPDATE + and "milestone" not in context.event.changed_fields() + ): + return (StepStatus.NOOP, context) + + if context.bug.milestone: + m = re.match(r"Branch (\d+)", context.bug.milestone) + if m is None: + # Milestone not supported (eg. "Future") + return (StepStatus.NOOP, context) + + milestone_version = m.group(1) + jira_project_versions = { + v["name"] + for v in jira_service.client.get_project_versions(context.jira.project) + } + potential_fix_versions = { + f"Fx{milestone_version}", + f"Release {milestone_version}", + } + jira_fix_versions = list( + jira_project_versions.intersection(potential_fix_versions) + ) + if not jira_fix_versions: + logger.info( + "Bug %s milestone %r has no matching version in project.", + context.bug.id, + context.bug.milestone, + extra=context.update( + operation=Operation.IGNORE, + ).model_dump(), + ) + return (StepStatus.INCOMPLETE, context) + + else: + jira_fix_versions = [] + + resp = jira_service.update_issue_field(context, "fixVersions", jira_fix_versions) + context.append_responses(resp) + return (StepStatus.SUCCESS, context) + + def _maybe_update_issue_mapped_field( source_field: str, context: ActionContext, diff --git a/tests/unit/test_steps.py b/tests/unit/test_steps.py index bd5b61e4..968a9427 100644 --- a/tests/unit/test_steps.py +++ b/tests/unit/test_steps.py @@ -728,6 +728,41 @@ def test_change_to_unknown_resolution_with_resolution_map( ] +def test_maybe_update_issue_milestone_empty_create(): + # NOOP when not set on create event + pass + + +def test_maybe_update_issue_milestone_unsupported_milestone(): + # NOOP when milestone is "Future" + pass + + +def test_maybe_update_issue_milestone_unknown_create(): + # Test log message when milestone unknown in project + pass + + +def test_maybe_update_issue_milestone_set_create(): + # Test both fix versions are known. + pass + + +def test_maybe_update_issue_milestone_empty_update(): + # Test set to empty list when empty on update. + pass + + +def test_maybe_update_issue_milestone_unknown_update(): + # Test log message when milestone unknown in project + pass + + +def test_maybe_update_issue_milestone_set_update(): + # Test both fix versions are known. + pass + + def test_update_issue_priority( action_context_factory, mocked_jira,