Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accumulate Time Lost from comments sent through LOVE #275

Merged
merged 11 commits into from
Aug 23, 2024
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
Loading