Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

# 3.4.0
- Add issue type and status category metadata to issue output, and issue type metadata to
linked issue output.

# 3.3.0
- Added new ``search_users`` action. Addresses [#90](https://github.com/StackStorm-Exchange/stackstorm-jira/issues/90)

Expand Down
24 changes: 17 additions & 7 deletions actions/lib/formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ def to_issue_dict(issue, include_comments=False, include_attachments=False,
else:
assignee = None

issue_type = getattr(issue.fields, 'issuetype', None)
status_category = getattr(issue.fields.status, 'statusCategory', None)

result = {
'id': issue.id,
'key': issue.key,
'url': url,
'summary': issue.fields.summary,
'description': issue.fields.description if hasattr(issue.fields, 'description') else None,
'status': issue.fields.status.name,
'issue_type': issue_type.name if issue_type else None,
'status_category': status_category.name if status_category else None,
'priority': issue.fields.priority.name if hasattr(issue.fields, 'priority') else None,
'resolution': resolution,
'labels': issue.fields.labels if hasattr(issue.fields, 'labels') else [],
Expand Down Expand Up @@ -129,15 +134,20 @@ def to_links_dict(issue):
"""
:rtype: ``dict``
"""
outward_issue = issue.raw.get('outwardIssue')
linked_issue = outward_issue or issue.raw.get('inwardIssue') or {}
fields = linked_issue.get('fields') or {}
status = fields.get('status') or {}
issue_type = fields.get('issuetype') or {}
link_type = issue.raw.get('type') or {}

result = {
'id': issue.raw.get('id'),
'key': issue.raw.get('outwardIssue', issue.raw.get('inwardIssue')).get('key'),
'summary': issue.raw.get('outwardIssue', issue.raw.get('inwardIssue'))
.get('fields').get('summary'),
'status': issue.raw.get('outwardIssue', issue.raw.get('inwardIssue')).get('fields')
.get('status').get('name'),
'type': issue.raw.get('type').get('outward') if issue.raw.get('outwardIssue')
else issue.raw.get('type').get('inward'),
'key': linked_issue.get('key'),
'summary': fields.get('summary'),
'status': status.get('name'),
'type': link_type.get('outward') if outward_issue else link_type.get('inward'),
'issue_type': issue_type.get('name'),
}
return result

Expand Down
2 changes: 1 addition & 1 deletion pack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ keywords:
- issues
- ticket management
- project management
version: 3.3.0
version: 3.4.0
python_versions:
- "3"
author: StackStorm, Inc.
Expand Down
146 changes: 146 additions & 0 deletions tests/test_formatters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
from functools import partial
from types import SimpleNamespace

from lib.formatters import to_issue_dict, to_links_dict


def test_to_issue_dict_includes_metadata() -> None:
fields = SimpleNamespace(
assignee=SimpleNamespace(displayName="Assignee"),
created="2026-07-29T10:00:00.000+0000",
description="Description",
issuetype=SimpleNamespace(name="Task"),
labels=["example"],
priority=SimpleNamespace(name="High"),
reporter=SimpleNamespace(displayName="Reporter"),
resolution=SimpleNamespace(name="Done"),
resolutiondate="2026-07-30T10:00:00.000+0000",
status=SimpleNamespace(
name="Completed",
statusCategory=SimpleNamespace(name="Done"),
),
summary="Example issue",
updated="2026-07-30T10:00:00.000+0000",
)
issue = SimpleNamespace(
fields=fields,
id="10001",
key="TEST-1",
permalink=partial(str, "https://jira.example.com/browse/TEST-1 - Example issue"),
)

assert to_issue_dict(issue) == {
"id": "10001",
"key": "TEST-1",
"url": "https://jira.example.com/browse/TEST-1",
"summary": "Example issue",
"description": "Description",
"status": "Completed",
"issue_type": "Task",
"status_category": "Done",
"priority": "High",
"resolution": "Done",
"labels": ["example"],
"reporter": "Reporter",
"assignee": "Assignee",
"created_at": "2026-07-29T10:00:00.000+0000",
"updated_at": "2026-07-30T10:00:00.000+0000",
"resolved_at": "2026-07-30T10:00:00.000+0000",
}


def test_to_issue_dict_handles_missing_optional_metadata() -> None:
fields = SimpleNamespace(
assignee=None,
created="2026-07-29T10:00:00.000+0000",
description=None,
labels=[],
reporter=None,
resolution=None,
resolutiondate=None,
status=SimpleNamespace(name="Open"),
summary="Partial issue",
updated="2026-07-30T10:00:00.000+0000",
)
issue = SimpleNamespace(
fields=fields,
id="10002",
key="TEST-2",
permalink=partial(str, "https://jira.example.com/browse/TEST-2 - Partial issue"),
)

result = to_issue_dict(issue)

assert result["issue_type"] is None
assert result["status_category"] is None


def test_to_links_dict_includes_outward_issue_type() -> None:
link = SimpleNamespace(
raw={
"id": "20001",
"outwardIssue": {
"key": "TEST-3",
"fields": {
"issuetype": {"name": "Task"},
"status": {"name": "To Do"},
"summary": "Linked issue",
},
},
"type": {"inward": "is caused by", "outward": "causes"},
}
)

assert to_links_dict(link) == {
"id": "20001",
"key": "TEST-3",
"summary": "Linked issue",
"status": "To Do",
"type": "causes",
"issue_type": "Task",
}


def test_to_links_dict_includes_inward_issue_type() -> None:
link = SimpleNamespace(
raw={
"id": "20002",
"inwardIssue": {
"key": "TEST-4",
"fields": {
"issuetype": {"name": "Bug"},
"status": {"name": "Done"},
"summary": "Related issue",
},
},
"type": {"inward": "is caused by", "outward": "causes"},
}
)

assert to_links_dict(link) == {
"id": "20002",
"key": "TEST-4",
"summary": "Related issue",
"status": "Done",
"type": "is caused by",
"issue_type": "Bug",
}


def test_to_links_dict_handles_missing_optional_fields() -> None:
link = SimpleNamespace(
raw={
"id": "20003",
"outwardIssue": {"key": "TEST-5", "fields": {}},
"type": {"outward": "relates to"},
}
)

assert to_links_dict(link) == {
"id": "20003",
"key": "TEST-5",
"summary": None,
"status": None,
"type": "relates to",
"issue_type": None,
}
Loading