Skip to content

Commit

Permalink
Merge pull request #275 from lsst-ts/tickets/DM-45776
Browse files Browse the repository at this point in the history
Accumulate Time Lost from comments sent through LOVE
  • Loading branch information
Vebop authored Aug 23, 2024
2 parents 2f4688b + 00a639d commit ee8cac7
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Version History
===============

v7.0.2
------

* Add accumulation of time lost in Jira comments

v7.0.1
------

Expand Down
76 changes: 75 additions & 1 deletion manager/api/tests/test_jira.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@
from unittest.mock import patch

import requests
import rest_framework
from django.test import TestCase, override_settings

from manager.utils import handle_jira_payload, jira_comment, jira_ticket
from manager.utils import (
TIME_LOST_FIELD,
handle_jira_payload,
jira_comment,
jira_ticket,
update_time_lost,
)

OLE_JIRA_OBS_COMPONENTS_FIELDS = [
"AuxTel",
Expand Down Expand Up @@ -311,6 +318,36 @@ def test_needed_parameters(self):

mock_jira_patcher.stop()

def test_update_time_lost(self):
"""Test call to update_time_lost and verify field was updated"""
mock_jira_patcher = patch("requests.get")
mock_jira_get = mock_jira_patcher.start()
response = requests.Response()
response.status_code = 200
response.json = lambda: {TIME_LOST_FIELD: 13.6}
mock_jira_get.return_value = response

put_patcher = patch("requests.put")
mock_jira_put = put_patcher.start()
response.status_code = 204
mock_jira_put.return_value = response

# call update time lost
jira_response = update_time_lost(1, 3.4)
assert jira_response.status_code == 200
assert jira_response.data["ack"] == "Jira time_lost field updated"

jira_response = update_time_lost(93827, 1.23)
assert jira_response.status_code == 200
assert jira_response.data["ack"] == "Jira time_lost field updated"

response.status_code = 400
mock_jira_put.return_value = response

jira_response = update_time_lost(12, 97.01)
assert jira_response.status_code == 400
assert jira_response.data["ack"] == "Jira time_lost field could not be updated"

def test_add_comment(self):
"""Test call to jira_comment function with all needed parameters"""
mock_jira_patcher = patch("requests.post")
Expand All @@ -323,10 +360,41 @@ def test_add_comment(self):
assert jira_response.status_code == 200
assert jira_response.data["ack"] == "Jira comment created"

mock_time_lost_patcher = patch("manager.utils.update_time_lost")
mock_time_lost_client = mock_time_lost_patcher.start()
time_lost_response = rest_framework.response.Response()
time_lost_response.status_code = 200
time_lost_response.data = {
"ack": "Jira time_lost field updated",
}
mock_time_lost_client.return_value = time_lost_response

jira_response = jira_comment(self.jira_request_narrative_full_jira_comment.data)
assert jira_response.status_code == 200
assert jira_response.data["ack"] == "Jira comment created"

def test_add_comment_fail(self):
"""Test jira_comment() return value when update_time_lost()
fails during jira_comment()"""
mock_jira_patcher = patch("requests.post")
mock_jira_client = mock_jira_patcher.start()
response = requests.Response()
response.status_code = 201
mock_jira_client.return_value = response

mock_time_lost_patcher = patch("manager.utils.update_time_lost")
mock_time_lost_client = mock_time_lost_patcher.start()
time_lost_response = rest_framework.response.Response()
time_lost_response.status_code = 400
time_lost_response.data = {
"ack": "Jira time_lost field could not be updated",
}
mock_time_lost_client.return_value = time_lost_response

resp = jira_comment(self.jira_request_narrative_full_jira_comment.data)
assert resp.status_code == 400
assert resp.data["ack"] == "Jira time_lost field could not be updated"

@patch.dict(os.environ, {"JIRA_API_HOSTNAME": "jira.lsstcorp.org"})
def test_handle_narrative_jira_payload(self):
"""Test call to function handle_jira_payload with all needed parameters
Expand All @@ -339,6 +407,12 @@ def test_handle_narrative_jira_payload(self):
response.json = lambda: {"key": "LOVE-XX"}
mock_jira_client.return_value = response

mock_time_lost_patcher = patch("manager.utils.update_time_lost")
mock_time_lost_client = mock_time_lost_patcher.start()
time_response = requests.Response()
time_response.status_code = 200
mock_time_lost_client.return_value = time_response

jira_response = handle_jira_payload(self.jira_request_narrative_full_jira_new)
assert jira_response.status_code == 200
assert jira_response.data["ack"] == "Jira ticket created"
Expand Down
71 changes: 66 additions & 5 deletions manager/manager/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
# Constants
JSON_RESPONSE_LOCAL_STORAGE_NOT_ALLOWED = {"error": "Local storage not allowed."}
JSON_RESPONSE_ERROR_NOT_VALID_JSON = {"error": "Not a valid JSON response."}
TIME_LOST_FIELD = "customfield_10106"
PRIMARY_SOFTWARE_COMPONENTS_IDS = "customfield_10107"
PRIMARY_HARDWARE_COMPONENTS_IDS = "customfield_10196"


class LocationPermission(BasePermission):
Expand Down Expand Up @@ -449,16 +452,16 @@ def jira_ticket(request_data):
# "on" if int(request_data.get("level", 0)) >= 100
# else "off"
# ),
"customfield_10106": float(request_data.get("time_lost", 0)),
TIME_LOST_FIELD: float(request_data.get("time_lost", 0)),
# Default values of the following fields are set to -1
"customfield_10107": {
PRIMARY_SOFTWARE_COMPONENTS_IDS: {
"id": (
str(primary_software_components_ids[0])
if primary_software_components_ids
else "-1"
)
},
"customfield_10196": {
PRIMARY_HARDWARE_COMPONENTS_IDS: {
"id": (
str(primary_hardware_components_ids[0])
if primary_hardware_components_ids
Expand Down Expand Up @@ -505,6 +508,57 @@ def jira_ticket(request_data):
)


def update_time_lost(jira_id: int, add_time_lost: float = 0.0) -> Response:
"""Connect to the Rubin Observatory JIRA Cloud REST API to
update time_lost field in a given jira ticket
Params
------
jira_id: int
Jira ID
add_time_lost: float
time value given from comment
Returns
-------
Response
The response and status code of the request to the JIRA API
200 if the time_lost field was successfully updated
400 if the time_lost field was not updated
"""
headers = {
"Authorization": f"Basic {os.environ.get('JIRA_API_TOKEN')}",
"content-type": "application/json",
}
url = f"https://{os.environ.get('JIRA_API_HOSTNAME')}/rest/api/latest/issue/{jira_id}/"
response = requests.get(url, headers=headers)
existent_time_lost = (
response.json().get(TIME_LOST_FIELD, 0.0)
if response.status_code == 200
else 0.0
)
jira_payload = {
"fields": {
TIME_LOST_FIELD: float(existent_time_lost + add_time_lost),
},
}
response = requests.put(url, json=jira_payload, headers=headers)
if response.status_code == 204:
return Response(
{
"ack": "Jira time_lost field updated",
"url": f"https://{os.environ.get('JIRA_API_HOSTNAME')}/browse/{jira_id}",
},
status=200,
)
return Response(
{
"ack": "Jira time_lost field could not be updated",
},
status=400,
)


def jira_comment(request_data):
"""Connect to the Rubin Observatory JIRA Cloud REST API to
make a comment on a previously created ticket.
Expand Down Expand Up @@ -547,6 +601,13 @@ def jira_comment(request_data):
}
url = f"https://{os.environ.get('JIRA_API_HOSTNAME')}/rest/api/latest/issue/{jira_id}/comment"
response = requests.post(url, json=jira_payload, headers=headers)
if "time_lost" in request_data:
timelost_response = update_time_lost(
jira_id=jira_id, add_time_lost=request_data.get("time_lost", 0.0)
)
if timelost_response.status_code != 200:
return timelost_response

if response.status_code == 201:
return Response(
{
Expand Down Expand Up @@ -618,8 +679,8 @@ def get_jira_obs_report(request_data):
"key": issue["key"],
"summary": issue["fields"]["summary"],
"time_lost": (
issue["fields"]["customfield_10106"]
if issue["fields"]["customfield_10106"] is not None
issue["fields"][TIME_LOST_FIELD]
if issue["fields"][TIME_LOST_FIELD] is not None
else 0.0
),
"reporter": issue["fields"]["creator"]["displayName"],
Expand Down

0 comments on commit ee8cac7

Please sign in to comment.