From 80ecdb711d01cf1f205f9c41010608c715cbfd02 Mon Sep 17 00:00:00 2001 From: joachim-danswer Date: Tue, 3 Jun 2025 13:12:56 -0700 Subject: [PATCH] New metadata for Jira for KG (#4785) * new metadata components * nits & tests --- backend/onyx/connectors/models.py | 3 ++ .../onyx/connectors/onyx_jira/connector.py | 35 +++++++++++++++++++ .../daily/connectors/jira/test_jira_basic.py | 15 +++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/backend/onyx/connectors/models.py b/backend/onyx/connectors/models.py index b334d6ff8e1..08ff5776ed9 100644 --- a/backend/onyx/connectors/models.py +++ b/backend/onyx/connectors/models.py @@ -87,6 +87,9 @@ class BasicExpertInfo(BaseModel): return "Unknown" + def get_email(self) -> str | None: + return self.email or None + def __eq__(self, other: Any) -> bool: if not isinstance(other, BasicExpertInfo): return False diff --git a/backend/onyx/connectors/onyx_jira/connector.py b/backend/onyx/connectors/onyx_jira/connector.py index 16bb271463e..09500e37ffc 100644 --- a/backend/onyx/connectors/onyx_jira/connector.py +++ b/backend/onyx/connectors/onyx_jira/connector.py @@ -60,6 +60,14 @@ _FIELD_KEY = "key" _FIELD_CREATED = "created" _FIELD_DUEDATE = "duedate" _FIELD_ISSUETYPE = "issuetype" +_FIELD_PARENT = "parent" +_FIELD_ASSIGNEE_EMAIL = "assignee_email" +_FIELD_REPORTER_EMAIL = "reporter_email" +_FIELD_PROJECT = "project" +_FIELD_PROJECT_NAME = "project_name" +_FIELD_UPDATED = "updated" +_FIELD_RESOLUTION_DATE = "resolutiondate" +_FIELD_RESOLUTION_DATE_KEY = "resolution_date" def _perform_jql_search( @@ -131,6 +139,9 @@ def process_jira_issue( if basic_expert_info := best_effort_basic_expert_info(creator): people.add(basic_expert_info) metadata_dict[_FIELD_REPORTER] = basic_expert_info.get_semantic_name() + if email := basic_expert_info.get_email(): + metadata_dict[_FIELD_REPORTER_EMAIL] = email + except Exception: # Author should exist but if not, doesn't matter pass @@ -140,6 +151,8 @@ def process_jira_issue( if basic_expert_info := best_effort_basic_expert_info(assignee): people.add(basic_expert_info) metadata_dict[_FIELD_ASSIGNEE] = basic_expert_info.get_semantic_name() + if email := basic_expert_info.get_email(): + metadata_dict[_FIELD_ASSIGNEE_EMAIL] = email except Exception: # Author should exist but if not, doesn't matter pass @@ -154,10 +167,32 @@ def process_jira_issue( metadata_dict[_FIELD_LABELS] = labels if created := best_effort_get_field_from_issue(issue, _FIELD_CREATED): metadata_dict[_FIELD_CREATED] = created + if updated := best_effort_get_field_from_issue(issue, _FIELD_UPDATED): + metadata_dict[_FIELD_UPDATED] = updated if duedate := best_effort_get_field_from_issue(issue, _FIELD_DUEDATE): metadata_dict[_FIELD_DUEDATE] = duedate if issuetype := best_effort_get_field_from_issue(issue, _FIELD_ISSUETYPE): metadata_dict[_FIELD_ISSUETYPE] = issuetype.name + if resolutiondate := best_effort_get_field_from_issue( + issue, _FIELD_RESOLUTION_DATE + ): + metadata_dict[_FIELD_RESOLUTION_DATE_KEY] = resolutiondate + + try: + parent = best_effort_get_field_from_issue(issue, _FIELD_PARENT) + if parent: + metadata_dict[_FIELD_PARENT] = parent.key + except Exception: + # Parent should exist but if not, doesn't matter + pass + try: + project = best_effort_get_field_from_issue(issue, _FIELD_PROJECT) + if project: + metadata_dict[_FIELD_PROJECT_NAME] = project.name + metadata_dict[_FIELD_PROJECT] = project.key + except Exception: + # Project should exist. + logger.error(f"Project should exist but does not for {issue.key}") return Document( id=page_url, diff --git a/backend/tests/daily/connectors/jira/test_jira_basic.py b/backend/tests/daily/connectors/jira/test_jira_basic.py index f4cb25a7948..d0b7f1b0b54 100644 --- a/backend/tests/daily/connectors/jira/test_jira_basic.py +++ b/backend/tests/daily/connectors/jira/test_jira_basic.py @@ -59,11 +59,19 @@ def test_jira_connector_basic( assert story.source == DocumentSource.JIRA assert story.metadata == { "priority": "Medium", - "status": "Backlog", + "status": "Done", + "resolution": "Done", + "resolution_date": "2025-05-29T15:33:31.031-0700", "reporter": "Chris Weaver", "assignee": "Chris Weaver", "issuetype": "Story", "created": "2025-04-16T16:44:06.716-0700", + "reporter_email": "chris@onyx.app", + "assignee_email": "chris@onyx.app", + "project_name": "DailyConnectorTestProject", + "project": "AS", + "parent": "AS-4", + "updated": "2025-05-29T15:33:31.085-0700", } assert story.secondary_owners is None assert story.title == "AS-3 test123small" @@ -86,6 +94,11 @@ def test_jira_connector_basic( "assignee": "Chris Weaver", "issuetype": "Epic", "created": "2025-04-16T16:55:53.068-0700", + "reporter_email": "founders@onyx.app", + "assignee_email": "chris@onyx.app", + "project_name": "DailyConnectorTestProject", + "project": "AS", + "updated": "2025-05-29T14:43:05.312-0700", } assert epic.secondary_owners is None assert epic.title == "AS-4 EPIC"