Skip to content

Fix #501: add maybe_update_issue_milestone step #896

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions jbi/bugzilla/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
51 changes: 51 additions & 0 deletions jbi/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from __future__ import annotations

import logging
import re
from enum import Enum, auto
from typing import TYPE_CHECKING, Iterable, Optional

Expand Down Expand Up @@ -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.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where will the "Bug %s milestone %r has no matching version in project." errors be logged when a Bugzilla Milestone name doesn't match the Jira Release? Is that information only available to JBI admins?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are application/server logs that end-up in Google Cloud console. We currently don't have any way to send alerts to users (we could consider adding a comment on the bug or on the Jira issue)

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)
Copy link
Contributor

@cpeterso cpeterso Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this update work with field name fixVersions? I think fixVersions (plural) should be fixVersion (singular). The field is displayed as "Fix versions" in the Jira issue UI, but it is called fixVersion (singular) in JQL queries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird. fixVersions is a system field (does not seem custom), and I don't see why it would be singular in JQL.

These are the fields with version in their name on our Jira instance:

[
   {
      "id":"customfield_10747",
      "key":"customfield_10747",
      "name":"App Version",
      "untranslatedName":"App Version",
      "custom":true,
      "orderable":true,
      "navigable":true,
      "searchable":true,
      "clauseNames":[
         "App Version",
         "App Version[Paragraph]",
         "cf[10747]"
      ],
      "schema":{
         "type":"string",
         "custom":"com.atlassian.jira.plugin.system.customfieldtypes:textarea",
         "customId":10747
      }
   },
   {
      "id":"customfield_10463",
      "key":"customfield_10463",
      "name":"Version",
      "untranslatedName":"Version",
      "custom":true,
      "orderable":true,
      "navigable":true,
      "searchable":true,
      "clauseNames":[
         "cf[10463]",
         "Version",
         "Version[Short text]"
      ],
      "schema":{
         "type":"string",
         "custom":"com.atlassian.jira.plugin.system.customfieldtypes:textfield",
         "customId":10463
      }
   },
   {
      "id":"customfield_10315",
      "key":"customfield_10315",
      "name":"Changed Fix Versions",
      "untranslatedName":"Changed Fix Versions",
      "custom":true,
      "orderable":true,
      "navigable":true,
      "searchable":true,
      "clauseNames":[
         "cf[10315]",
         "Changed Fix Versions",
         "Changed Fix Versions[Paragraph]"
      ],
      "schema":{
         "type":"string",
         "custom":"com.atlassian.jira.plugin.system.customfieldtypes:textarea",
         "customId":10315
      }
   },
   {
      "id":"customfield_10184",
      "key":"customfield_10184",
      "name":"Targeted version and channel",
      "untranslatedName":"Targeted version and channel",
      "custom":true,
      "orderable":true,
      "navigable":true,
      "searchable":true,
      "clauseNames":[
         "cf[10184]",
         "Targeted version and channel",
         "Targeted version and channel[Dropdown]"
      ],
      "schema":{
         "type":"option",
         "custom":"com.atlassian.jira.plugin.system.customfieldtypes:select",
         "customId":10184
      }
   },
   {
      "id":"customfield_10185",
      "key":"customfield_10185",
      "name":"Rollout will become default in version:",
      "untranslatedName":"Rollout will become default in version:",
      "custom":true,
      "orderable":true,
      "navigable":true,
      "searchable":true,
      "clauseNames":[
         "cf[10185]",
         "Rollout will become default in version:",
         "Rollout will become default in version:[Dropdown]"
      ],
      "schema":{
         "type":"option",
         "custom":"com.atlassian.jira.plugin.system.customfieldtypes:select",
         "customId":10185
      }
   },
   {
      "id":"fixVersions",
      "key":"fixVersions",
      "name":"Fix versions",
      "custom":false,
      "orderable":true,
      "navigable":true,
      "searchable":true,
      "clauseNames":[
         "fixVersion"
      ],
      "schema":{
         "type":"array",
         "items":"version",
         "system":"fixVersions"
      }
   },
   {
      "id":"versions",
      "key":"versions",
      "name":"Affects versions",
      "custom":false,
      "orderable":true,
      "navigable":true,
      "searchable":true,
      "clauseNames":[
         "affectedVersion"
      ],
      "schema":{
         "type":"array",
         "items":"version",
         "system":"versions"
      }
   }
]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird. fixVersions is a system field (does not seem custom), and I don't see why it would be singular in JQL.

I haven't used Jira's API, but when I search with JQL fixVersions = Fx124, Jira returns an error:

Field 'fixVersions' does not exist or you do not have permission to view it.

https://mozilla-hub.atlassian.net/issues/?jql=fixVersions%20%3D%20Fx124

When I search with fixVersion = Fx124, Jira returns a list of 162 issues:

https://mozilla-hub.atlassian.net/issues/?jql=fixVersion%20%3D%20Fx124

context.append_responses(resp)
return (StepStatus.SUCCESS, context)


def _maybe_update_issue_mapped_field(
source_field: str,
context: ActionContext,
Expand Down
35 changes: 35 additions & 0 deletions tests/unit/test_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down