Skip to content

Commit

Permalink
feat: support update ticket jira and jira on-prem (#1588)
Browse files Browse the repository at this point in the history
Signed-off-by: Ezhil Shanmugham <[email protected]>
Signed-off-by: Tal <[email protected]>
Co-authored-by: Tal <[email protected]>
Co-authored-by: Tal <[email protected]>
Co-authored-by: Shahar Glazner <[email protected]>
  • Loading branch information
4 people authored Sep 1, 2024
1 parent 8a8d554 commit f65e85b
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 13 deletions.
1 change: 1 addition & 0 deletions docs/providers/documentation/jira-provider.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The `notify` function take following parameters as inputs:
- `summary` (required): Incident/issue name or short description.
- `description` (optional): Additional details related to the incident/issue.
- `issue_type` (optional): Issue type name. For example: `Story`, `Bug` etc
- `issue_id` (optional): When you want to update an existing issue, provide the issue id.

## Outputs

Expand Down
15 changes: 15 additions & 0 deletions examples/workflows/update_jira_ticket.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
workflow:
id: update-jira-ticket
triggers:
- type: manual
actions:
- name: jira-action
provider:
config: '{{ providers.Jira }}'
type: jira
with:
board_name: ''
description: Update description of an issue
issue_id: 10023
project_key: ''
summary: Update summary of an issue
108 changes: 101 additions & 7 deletions keep/providers/jira_provider/jira_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,67 @@ def __create_issue(
return {"issue": response.json()}
except Exception as e:
raise ProviderException(f"Failed to create an issue: {e}")

def __update_issue(
self,
issue_id: str,
summary: str,
description: str = "",
labels: List[str] = None,
components: List[str] = None,
custom_fields: dict = None,
**kwargs: dict,
):
"""
Helper method to update an issue in jira.
"""
try:
self.logger.info("Updating an issue...")

url = self.__get_url(paths=["issue", issue_id])

update = { }

if summary:
update["summary"] = [{"set": summary}]

if description:
update["description"] = [{"set": description}]

if components:
update["components"] = [{"set": component} for component in components]

if labels:
update["labels"] = [{"set": label} for label in labels]

if custom_fields:
update.update(custom_fields)

request_body = { "update": update }

response = requests.put(
url=url, json=request_body, auth=self.__get_auth(), verify=False
)

try:
if response.status_code != 204:
response.raise_for_status()
except Exception:
self.logger.exception(
"Failed to update an issue", extra=response.text
)
raise ProviderException("Failed to update an issue")
self.logger.info("Updated an issue!")
return {
"issue": {
"id": issue_id,
"key": self._extract_issue_key_from_issue_id(issue_id),
"self": self.__get_url(paths=["issue", issue_id]),
}
}

except Exception as e:
raise ProviderException(f"Failed to update an issue: {e}")

def _extract_project_key_from_board_name(self, board_name: str):
boards_response = requests.get(
Expand All @@ -328,6 +389,19 @@ def _extract_project_key_from_board_name(self, board_name: str):
)
else:
raise Exception("Could not fetch boards: " + boards_response.text)

def _extract_issue_key_from_issue_id(self, issue_id: str):
issue_key = requests.get(
f"{self.jira_host}/rest/api/2/issue/{issue_id}",
auth=self.__get_auth(),
headers={"Accept": "application/json"},
verify=False,
)

if issue_key.status_code == 200:
return issue_key.json()["key"]
else:
raise Exception("Could not fetch issue key: " + issue_key.text)

def _notify(
self,
Expand All @@ -336,6 +410,7 @@ def _notify(
issue_type: str = "",
project_key: str = "",
board_name: str = "",
issue_id: str = None,
labels: List[str] = None,
components: List[str] = None,
custom_fields: dict = None,
Expand All @@ -344,18 +419,37 @@ def _notify(
"""
Notify jira by creating an issue.
"""
# if the user didn't provider a project_key, try to extract it from the board name
if not project_key:
project_key = self._extract_project_key_from_board_name(board_name)
issue_type = issue_type if issue_type else kwargs.get("issuetype", "Task")
if not project_key or not summary or not issue_type or not description:
raise ProviderException(
f"Project key and summary are required! - {project_key}, {summary}, {issue_type}, {description}"
)
if labels and isinstance(labels, str):
labels = json.loads(labels.replace("'", '"'))
try:
self.logger.info("Notifying jira...")

if issue_id:
result = self.__update_issue(
issue_id=issue_id,
summary=summary,
description=description,
labels=labels,
components=components,
custom_fields=custom_fields,
**kwargs,
)

issue_key = self._extract_issue_key_from_issue_id(issue_id)

result["ticket_url"] = f"{self.jira_host}/browse/{issue_key}"

self.logger.info("Updated a jira issue: " + str(result))
return result

if not project_key:
project_key = self._extract_project_key_from_board_name(board_name)
if not project_key or not summary or not issue_type or not description:
raise ProviderException(
f"Project key and summary are required! - {project_key}, {summary}, {issue_type}, {description}"
)

result = self.__create_issue(
project_key=project_key,
summary=summary,
Expand Down
124 changes: 118 additions & 6 deletions keep/providers/jiraonprem_provider/jiraonprem_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,78 @@ def __create_issue(
return {"issue": response.json()}
except Exception as e:
raise ProviderException(f"Failed to create an issue: {e}")

def __update_issue(
self,
issue_id: str,
summary: str = "",
description: str = "",
priority: str = "Medium",
labels: List[str] = None,
components: List[str] = None,
custom_fields: dict = None,
**kwargs: dict,
):
"""
Helper method to update an issue in jira.
"""
try:
self.logger.info("Updating an issue...")

url = self.__get_url(paths=["issue", issue_id])

update = { }

if summary:
update["summary"] = [{"set": summary}]

if description:
update["description"] = [{"set": description}]

if priority:
update["priority"] = [{"set": {"name": priority}}]

if components:
update["components"] = [{"set": [{"name": component} for component in components]}]

if labels:
update["labels"] = [{"set": label} for label in labels]

if custom_fields:
update.update(custom_fields)

request_body = {"update": update}

response = requests.put(
url=url,
json=request_body,
headers=self.__get_auth_header(),
verify=False,
timeout=10,
)

try:
if response.status_code != 204:
response.raise_for_status()
except Exception:
self.logger.exception(
"Failed to update an issue", extra=response.text
)
raise ProviderException("Failed to update an issue")

result = {
"issue": {
"id": issue_id,
"key": self._extract_issue_key_from_issue_id(issue_id),
"self": self.__get_url(paths=["issue", issue_id]),
}
}

self.logger.info("Updated an issue!")
return result

except Exception as e:
raise ProviderException(f"Failed to update an issue: {e}")

def _extract_project_key_from_board_name(self, board_name: str):
headers = {
Expand Down Expand Up @@ -385,6 +457,24 @@ def _extract_project_key_from_board_name(self, board_name: str):
)
else:
raise Exception("Could not fetch boards: " + boards_response.text)

def _extract_issue_key_from_issue_id(self, issue_id: str):
headers = {
"Accept": "application/json",
}
headers.update(self.__get_auth_header())

issue_key = requests.get(
f"{self.jira_host}/rest/api/2/issue/{issue_id}",
headers=headers,
verify=False,
timeout=10,
)

if issue_key.status_code == 200:
return issue_key.json()["key"]
else:
raise Exception("Could not fetch issue key: " + issue_key.text)

def _notify(
self,
Expand All @@ -393,6 +483,7 @@ def _notify(
issue_type: str = "",
project_key: str = "",
board_name: str = "",
issue_id: str = None,
labels: List[str] = None,
components: List[str] = None,
custom_fields: dict = None,
Expand All @@ -403,17 +494,38 @@ def _notify(
Notify jira by creating an issue.
"""
# if the user didn't provider a project_key, try to extract it from the board name
if not project_key:
project_key = self._extract_project_key_from_board_name(board_name)
issue_type = issue_type if issue_type else kwargs.get("issuetype", "Task")
if not project_key or not summary or not issue_type or not description:
raise ProviderException(
f"Project key and summary are required! - {project_key}, {summary}, {issue_type}, {description}"
)
if labels and isinstance(labels, str):
labels = json.loads(labels.replace("'", '"'))
try:
self.logger.info("Notifying jira...")

if issue_id:
result = self.__update_issue(
issue_id=issue_id,
summary=summary,
description=description,
labels=labels,
components=components,
custom_fields=custom_fields,
priority=priority,
**kwargs,
)

issue_key = self._extract_issue_key_from_issue_id(issue_id)

result["ticket_url"] = f"{self.jira_host}/browse/{issue_key}"

self.logger.info("Updated a jira issue: " + str(result))
return result

if not project_key:
project_key = self._extract_project_key_from_board_name(board_name)
if not project_key or not summary or not issue_type or not description:
raise ProviderException(
f"Project key and summary are required! - {project_key}, {summary}, {issue_type}, {description}"
)

result = self.__create_issue(
project_key=project_key,
summary=summary,
Expand Down

0 comments on commit f65e85b

Please sign in to comment.