Skip to content
Merged
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
14 changes: 14 additions & 0 deletions jbi/jira/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import logging
from typing import Collection, Iterable, Optional

Expand Down Expand Up @@ -54,6 +55,7 @@ def raise_for_status(self, *args, **kwargs):
except requests.HTTPError as exc:
request = exc.request
response = exc.response
assert response is not None, f"HTTPError {exc} has no attached response"
atlassian_logger.error(
"HTTP: %s %s -> %s %s",
request.method,
Expand All @@ -62,6 +64,18 @@ def raise_for_status(self, *args, **kwargs):
response.reason,
extra={"body": response.text},
)
if str(exc) == "":
# Some Jira errors are raised as `HTTPError('')`.
# We are trying to turn them into insightful errors here.
try:
content = exc.response.json()
errors = content.get("errors", {})
response_details = ",".join(f"{k}: {v}" for k, v in errors.items())
except json.JSONDecodeError:
response_details = exc.response.text
# Set the exception message so that its str version contains details.
msg = f"HTTP {exc.response.status_code}: {response_details}"
exc.args = (msg,) + exc.args[1:]
raise

get_server_info = instrumented_method(Jira.get_server_info)
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/jira/test_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ async def test_backend_get_invalid_json(backend: QueueBackend, queue_item_factor
with pytest.raises(QueueItemRetrievalError):
await anext(items)


async def test_get_missing_timezone(backend: QueueBackend, queue_item_factory):
item = queue_item_factory.build(payload__bug__id=666)
dump = item.model_dump()
Expand Down
49 changes: 49 additions & 0 deletions tests/unit/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,55 @@ async def test_execute_or_queue_exception(
mock_queue.track_failed.assert_called_once()


@pytest.mark.asyncio
@pytest.mark.no_mocked_bugzilla
@pytest.mark.no_mocked_jira
async def test_execute_or_queue_http_error_details(
actions,
dl_queue,
bugzilla_webhook_request,
context_comment_example,
mocked_responses,
):
bug = bugzilla_webhook_request.bug
settings = get_settings()
mocked_responses.add(
responses.GET,
f"{settings.bugzilla_base_url}/rest/bug/{bug.id}",
json={"bugs": [bug.model_dump()]},
)
mocked_responses.add(
responses.GET,
f"{settings.bugzilla_base_url}/rest/bug/{bug.id}/comment",
json={"bugs": {str(bug.id): {"comments": []}}},
)
mocked_responses.add(
responses.POST,
f"{settings.jira_base_url}rest/api/2/issue",
json={"key": "TEST-1"},
)
mocked_responses.add(
responses.POST,
f"{settings.jira_base_url}rest/api/2/issue/TEST-1/remotelink",
status=400,
json={
"errorMessages": [],
"errors": {"resolution": "Field 'resolution' cannot be set."},
},
)

await execute_or_queue(
request=bugzilla_webhook_request, queue=dl_queue, actions=actions
)

items = (await dl_queue.retrieve())[bug.id]
[item] = [i async for i in items]
assert (
item.error.description
== "HTTP 400: resolution: Field 'resolution' cannot be set."
)


def test_default_invalid_init():
with pytest.raises(TypeError):
Executor()
Expand Down