Skip to content

Commit

Permalink
Ref mozilla#984: Simple comment when attachment is added to bug (mozi…
Browse files Browse the repository at this point in the history
…lla#1018)

* Add attachment operation

* Call 'create_comment' by default on attachment events

* Add comment by default when an attachment is created

* Improve past verb in comment
  • Loading branch information
leplatrem authored and davehunt committed Jan 29, 2025
1 parent cb88a1c commit b9a3c26
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 20 deletions.
1 change: 1 addition & 0 deletions jbi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Operation(str, Enum):
UPDATE = "update"
DELETE = "delete"
COMMENT = "comment"
ATTACHMENT = "attachment"
LINK = "link"


Expand Down
21 changes: 15 additions & 6 deletions jbi/jira/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,23 @@ def add_jira_comment(self, context: ActionContext):
"""Publish a comment on the specified Jira issue"""
context = context.update(operation=Operation.COMMENT)
commenter = context.event.user.login if context.event.user else "unknown"
comment = context.bug.comment
assert comment # See jbi.steps.create_comment()
assert comment.body # Also see jbi.steps.create_comment()

if context.event.target == "attachment":
routing_key = (
context.event.routing_key or ".modify" # only to please type checking.
)
_, verb = routing_key.rsplit(".", 1)
past_verb = {"modify": "modified"}.get(verb, f"{verb}d")
formatted_comment = f"*{commenter}* {past_verb} an attachment"
else:
comment = context.bug.comment
assert comment # See jbi.steps.create_comment()
assert comment.body # Also see jbi.steps.create_comment()
formatted_comment = (
f"*{commenter}* commented: \n{markdown_to_jira(comment.body)}"
)

issue_key = context.jira.issue
formatted_comment = (
f"*{commenter}* commented: \n{markdown_to_jira(comment.body)}"
)
jira_response = self.client.issue_add_comment(
issue_key=issue_key,
comment=formatted_comment,
Expand Down
3 changes: 3 additions & 0 deletions jbi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class ActionSteps(BaseModel, frozen=True):
comment: list[str] = [
"create_comment",
]
attachment: list[str] = [
"create_comment",
]

@field_validator("*")
@classmethod
Expand Down
4 changes: 4 additions & 0 deletions jbi/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"new": Operation.CREATE,
"existing": Operation.UPDATE,
"comment": Operation.COMMENT,
"attachment": Operation.ATTACHMENT,
}


Expand Down Expand Up @@ -288,6 +289,9 @@ def execute_action(
elif event.target == "comment":
action_context = action_context.update(operation=Operation.COMMENT)

elif event.target == "attachment":
action_context = action_context.update(operation=Operation.ATTACHMENT)

if action_context.operation == Operation.IGNORE:
raise IgnoreInvalidRequestError(
f"ignore event target {action_context.event.target!r}"
Expand Down
25 changes: 13 additions & 12 deletions jbi/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,20 @@ def create_comment(context: ActionContext, *, jira_service: JiraService) -> Step
"""Create a Jira comment using `context.bug.comment`"""
bug = context.bug

if bug.comment is None:
logger.info(
"No matching comment found in payload",
extra=context.model_dump(),
)
return (StepStatus.NOOP, context)
if context.event.target == "comment":
if bug.comment is None:
logger.info(
"No matching comment found in payload",
extra=context.model_dump(),
)
return (StepStatus.NOOP, context)

if not bug.comment.body:
logger.info(
"Comment message is empty",
extra=context.model_dump(),
)
return (StepStatus.NOOP, context)
if not bug.comment.body:
logger.info(
"Comment message is empty",
extra=context.model_dump(),
)
return (StepStatus.NOOP, context)

jira_response = jira_service.add_jira_comment(context)
context = context.append_responses(jira_response)
Expand Down
12 changes: 12 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ def context_comment_example(action_context_factory) -> ActionContext:
)


@pytest.fixture
def context_attachment_example(action_context_factory) -> ActionContext:
return action_context_factory(
operation=Operation.ATTACHMENT,
bug__see_also=["https://mozilla.atlassian.net/browse/JBI-234"],
event__target="attachment",
event__routed_key="attachment.create",
event__user__login="[email protected]",
jira__issue="JBI-234",
)


@pytest.fixture(autouse=True)
def sleepless(monkeypatch):
# https://stackoverflow.com/a/54829577
Expand Down
17 changes: 15 additions & 2 deletions tests/unit/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,7 @@ def test_default_invalid_init():
def test_unspecified_groups_come_from_default_steps(action_params_factory):
action = Executor(action_params_factory(steps={"comment": ["create_comment"]}))

assert len(action.steps) == 3
assert action.steps
assert len(action.steps) == 4


def test_default_returns_callable_without_data(action_params):
Expand Down Expand Up @@ -589,6 +588,20 @@ def test_counter_is_incremented_for_comment(
mocked.incr.assert_any_call("jbi.operation.comment.count")


def test_counter_is_incremented_for_attachment(
actions, webhook_request_factory, mocked_bugzilla, mocked_jira
):
webhook_payload = webhook_request_factory(
event__target="attachment",
bug__see_also=["https://mozilla.atlassian.net/browse/JBI-234"],
)
mocked_bugzilla.get_bug.return_value = webhook_payload.bug
mocked_jira.get_issue.return_value = {"fields": {"project": {"key": "JBI"}}}
with mock.patch("jbi.runner.statsd") as mocked:
execute_action(request=webhook_payload, actions=actions)
mocked.incr.assert_any_call("jbi.operation.attachment.count")


@pytest.mark.parametrize(
"whiteboard",
[
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/test_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,21 @@ def test_added_comment(
)


def test_added_attachment(
context_attachment_example: ActionContext, mocked_jira, action_params_factory
):
callable_object = Executor(
action_params_factory(jira_project_key=context_attachment_example.jira.project)
)

callable_object(context=context_attachment_example)

mocked_jira.issue_add_comment.assert_called_once_with(
issue_key="JBI-234",
comment="*[email protected]* created an attachment",
)


def test_empty_comment_not_added(
action_context_factory, mocked_jira, action_params_factory
):
Expand Down

0 comments on commit b9a3c26

Please sign in to comment.