Skip to content

Commit 97fe328

Browse files
authored
Fix #969: force message on HTTPError when empty (#970)
* Fix #969: force message on HTTPError when empty * Assert that only one item * Remove superfluous condition
1 parent 9c685d5 commit 97fe328

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

jbi/jira/client.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import logging
23
from typing import Collection, Iterable, Optional
34

@@ -54,6 +55,7 @@ def raise_for_status(self, *args, **kwargs):
5455
except requests.HTTPError as exc:
5556
request = exc.request
5657
response = exc.response
58+
assert response is not None, f"HTTPError {exc} has no attached response"
5759
atlassian_logger.error(
5860
"HTTP: %s %s -> %s %s",
5961
request.method,
@@ -62,6 +64,18 @@ def raise_for_status(self, *args, **kwargs):
6264
response.reason,
6365
extra={"body": response.text},
6466
)
67+
if str(exc) == "":
68+
# Some Jira errors are raised as `HTTPError('')`.
69+
# We are trying to turn them into insightful errors here.
70+
try:
71+
content = exc.response.json()
72+
errors = content.get("errors", {})
73+
response_details = ",".join(f"{k}: {v}" for k, v in errors.items())
74+
except json.JSONDecodeError:
75+
response_details = exc.response.text
76+
# Set the exception message so that its str version contains details.
77+
msg = f"HTTP {exc.response.status_code}: {response_details}"
78+
exc.args = (msg,) + exc.args[1:]
6579
raise
6680

6781
get_server_info = instrumented_method(Jira.get_server_info)

tests/unit/jira/test_queue.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ async def test_backend_get_invalid_json(backend: QueueBackend, queue_item_factor
178178
with pytest.raises(QueueItemRetrievalError):
179179
await anext(items)
180180

181-
181+
182182
async def test_get_missing_timezone(backend: QueueBackend, queue_item_factory):
183183
item = queue_item_factory.build(payload__bug__id=666)
184184
dump = item.model_dump()

tests/unit/test_runner.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,55 @@ async def test_execute_or_queue_exception(
304304
mock_queue.track_failed.assert_called_once()
305305

306306

307+
@pytest.mark.asyncio
308+
@pytest.mark.no_mocked_bugzilla
309+
@pytest.mark.no_mocked_jira
310+
async def test_execute_or_queue_http_error_details(
311+
actions,
312+
dl_queue,
313+
bugzilla_webhook_request,
314+
context_comment_example,
315+
mocked_responses,
316+
):
317+
bug = bugzilla_webhook_request.bug
318+
settings = get_settings()
319+
mocked_responses.add(
320+
responses.GET,
321+
f"{settings.bugzilla_base_url}/rest/bug/{bug.id}",
322+
json={"bugs": [bug.model_dump()]},
323+
)
324+
mocked_responses.add(
325+
responses.GET,
326+
f"{settings.bugzilla_base_url}/rest/bug/{bug.id}/comment",
327+
json={"bugs": {str(bug.id): {"comments": []}}},
328+
)
329+
mocked_responses.add(
330+
responses.POST,
331+
f"{settings.jira_base_url}rest/api/2/issue",
332+
json={"key": "TEST-1"},
333+
)
334+
mocked_responses.add(
335+
responses.POST,
336+
f"{settings.jira_base_url}rest/api/2/issue/TEST-1/remotelink",
337+
status=400,
338+
json={
339+
"errorMessages": [],
340+
"errors": {"resolution": "Field 'resolution' cannot be set."},
341+
},
342+
)
343+
344+
await execute_or_queue(
345+
request=bugzilla_webhook_request, queue=dl_queue, actions=actions
346+
)
347+
348+
items = (await dl_queue.retrieve())[bug.id]
349+
[item] = [i async for i in items]
350+
assert (
351+
item.error.description
352+
== "HTTP 400: resolution: Field 'resolution' cannot be set."
353+
)
354+
355+
307356
def test_default_invalid_init():
308357
with pytest.raises(TypeError):
309358
Executor()

0 commit comments

Comments
 (0)