t-bug-catcher 0.6.0__tar.gz → 0.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/PKG-INFO +1 -1
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/setup.cfg +1 -1
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/setup.py +1 -1
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/__init__.py +1 -1
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/bug_catcher.py +8 -2
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/config.py +5 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/jira.py +110 -27
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/utils/common.py +14 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher.egg-info/PKG-INFO +1 -1
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/MANIFEST.in +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/README.rst +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/pyproject.toml +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/requirements.txt +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/bug_snag.py +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/exceptions.py +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/resources/whispers_config.yml +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/stack_saver.py +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/utils/__init__.py +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/utils/logger.py +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher/workitems.py +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher.egg-info/SOURCES.txt +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher.egg-info/dependency_links.txt +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher.egg-info/not-zip-safe +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher.egg-info/requires.txt +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/t_bug_catcher.egg-info/top_level.txt +0 -0
- {t_bug_catcher-0.6.0 → t_bug_catcher-0.6.2}/tests/test_t_bug_catcher.py +0 -0
|
@@ -26,7 +26,7 @@ setup(
|
|
|
26
26
|
packages=find_packages(include=["t_bug_catcher", "t_bug_catcher.*"]),
|
|
27
27
|
test_suite="tests",
|
|
28
28
|
url="https://www.thoughtful.ai/",
|
|
29
|
-
version="0.6.
|
|
29
|
+
version="0.6.2",
|
|
30
30
|
zip_safe=False,
|
|
31
31
|
install_requires=install_requirements,
|
|
32
32
|
include_package_data=True,
|
|
@@ -110,6 +110,8 @@ class BugCatcher:
|
|
|
110
110
|
metadata: Optional[dict] = None,
|
|
111
111
|
attachments: Optional[List] = None,
|
|
112
112
|
assignee: Optional[str] = None,
|
|
113
|
+
team: Optional[str] = None,
|
|
114
|
+
group_by: Optional[str] = None,
|
|
113
115
|
):
|
|
114
116
|
"""Reports an error to the Jira project.
|
|
115
117
|
|
|
@@ -119,6 +121,8 @@ class BugCatcher:
|
|
|
119
121
|
metadata (dict, optional): The metadata to be added to the Jira issue. Defaults to None.
|
|
120
122
|
attachments (List, optional): The attachments to be added to the Jira issue. Defaults to None.
|
|
121
123
|
assignee (str, optional): The assignee to be added to the Jira issue. Defaults to None.
|
|
124
|
+
team (str, optional): The team to be assigned to the Jira issue. Defaults to None.
|
|
125
|
+
group_by (str, optional): The group to be assigned to the Jira issue. Defaults to None.
|
|
122
126
|
|
|
123
127
|
Returns:
|
|
124
128
|
None
|
|
@@ -175,10 +179,12 @@ class BugCatcher:
|
|
|
175
179
|
self.__jira.report_error(
|
|
176
180
|
exception=exception,
|
|
177
181
|
assignee=assignee,
|
|
182
|
+
team=team,
|
|
178
183
|
attachments=attachments,
|
|
179
184
|
stack_trace=stack_trace,
|
|
180
185
|
additional_info=description,
|
|
181
186
|
metadata=metadata,
|
|
187
|
+
group_by=group_by,
|
|
182
188
|
)
|
|
183
189
|
|
|
184
190
|
if self.__configurator.is_bugsnag_configured:
|
|
@@ -268,7 +274,7 @@ class BugCatcher:
|
|
|
268
274
|
Args:
|
|
269
275
|
exc_type (type): The type of the exception.
|
|
270
276
|
exc_value (Exception): The value of the exception.
|
|
271
|
-
|
|
277
|
+
exc_traceback (traceback): The traceback of the exception.
|
|
272
278
|
|
|
273
279
|
Returns:
|
|
274
280
|
None
|
|
@@ -289,7 +295,7 @@ class BugCatcher:
|
|
|
289
295
|
stack_trace = self.__stack_saver.save_stack_trace(exc_value)
|
|
290
296
|
|
|
291
297
|
if self.__configurator.is_jira_configured:
|
|
292
|
-
self.__jira.report_unhandled_error(
|
|
298
|
+
self.__jira.report_unhandled_error(exc_value, stack_trace)
|
|
293
299
|
if self.__configurator.is_bugsnag_configured:
|
|
294
300
|
self.__bug_snag.report_unhandled_error(exc_type, exc_value, exc_traceback)
|
|
295
301
|
frames = get_frames(exc_value.__traceback__)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import socket
|
|
2
3
|
|
|
3
4
|
from .workitems import metadata, variables
|
|
4
5
|
|
|
@@ -16,6 +17,7 @@ class Config:
|
|
|
16
17
|
STACK_SCOPE: int = 3
|
|
17
18
|
STACK_ITEM_LENGTH: int = 100
|
|
18
19
|
STACK_TEXT_LENGTH: int = 10000
|
|
20
|
+
COMMENT_LIMIT: int = 4950
|
|
19
21
|
|
|
20
22
|
class TICKET_PRIORITIES:
|
|
21
23
|
"""Priorities class for configuring the application."""
|
|
@@ -32,6 +34,9 @@ class Config:
|
|
|
32
34
|
KEYS_TO_REMOVE = ["credential", "password"]
|
|
33
35
|
BUILD_INFO_FILE = "commit_info.json"
|
|
34
36
|
|
|
37
|
+
HOST = socket.gethostname() if os.name.lower() == "nt" else None
|
|
38
|
+
UNAME = os.getlogin() if os.name.lower() == "nt" else None
|
|
39
|
+
|
|
35
40
|
RC_RUN_LINK = (
|
|
36
41
|
f"https://cloud.robocorp.com/organizations/{os.environ.get('RC_ORGANIZATION_ID')}"
|
|
37
42
|
f"/workspaces/{os.environ.get('RC_WORKSPACE_ID')}/processes"
|
|
@@ -7,6 +7,7 @@ import os
|
|
|
7
7
|
import re
|
|
8
8
|
import sys
|
|
9
9
|
import traceback
|
|
10
|
+
import zlib
|
|
10
11
|
from datetime import datetime
|
|
11
12
|
from importlib.metadata import version
|
|
12
13
|
from pathlib import Path
|
|
@@ -21,7 +22,7 @@ from retry import retry
|
|
|
21
22
|
from .config import CONFIG
|
|
22
23
|
from .exceptions import BadRequestError
|
|
23
24
|
from .utils import logger
|
|
24
|
-
from .utils.common import Encoder, get_frames, retrieve_build_info
|
|
25
|
+
from .utils.common import Encoder, get_frames, remove_holotree_id, retrieve_build_info
|
|
25
26
|
from .workitems import variables
|
|
26
27
|
|
|
27
28
|
|
|
@@ -216,6 +217,7 @@ class Jira:
|
|
|
216
217
|
assignee: Optional[str] = None,
|
|
217
218
|
labels: Optional[list] = None,
|
|
218
219
|
priority: Optional[str] = None,
|
|
220
|
+
team: Optional[str] = None,
|
|
219
221
|
) -> str:
|
|
220
222
|
"""Generates the issue body payload for creating a new issue.
|
|
221
223
|
|
|
@@ -226,6 +228,7 @@ class Jira:
|
|
|
226
228
|
issue_type (str): The type of the issue.
|
|
227
229
|
labels (list, optional): The labels of the issue. Defaults to None.
|
|
228
230
|
priority (str, optional): The priority of the issue. Defaults to None.
|
|
231
|
+
team (str, optional): The team to be assigned to the Jira issue. Defaults to None.
|
|
229
232
|
|
|
230
233
|
Returns:
|
|
231
234
|
The JSON payload for creating a new issue.
|
|
@@ -246,6 +249,8 @@ class Jira:
|
|
|
246
249
|
fields["fields"]["customfield_10077"] = [CONFIG.ADMIN_CODE]
|
|
247
250
|
if priority:
|
|
248
251
|
fields["fields"]["priority"] = {"id": priority}
|
|
252
|
+
if team:
|
|
253
|
+
fields["fields"]["customfield_10001"] = team
|
|
249
254
|
payload = json.dumps(fields)
|
|
250
255
|
return payload
|
|
251
256
|
|
|
@@ -639,6 +644,34 @@ class Jira:
|
|
|
639
644
|
else []
|
|
640
645
|
)
|
|
641
646
|
|
|
647
|
+
@staticmethod
|
|
648
|
+
def __host_markup() -> List[dict]:
|
|
649
|
+
"""Create the host worker markup.
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
dict: The host worker markup.
|
|
653
|
+
"""
|
|
654
|
+
return (
|
|
655
|
+
[
|
|
656
|
+
{
|
|
657
|
+
"type": "paragraph",
|
|
658
|
+
"content": [
|
|
659
|
+
{
|
|
660
|
+
"type": "text",
|
|
661
|
+
"text": "Host: ",
|
|
662
|
+
"marks": [{"type": "strong"}],
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
"type": "text",
|
|
666
|
+
"text": f"{CONFIG.HOST} > {CONFIG.UNAME}",
|
|
667
|
+
},
|
|
668
|
+
],
|
|
669
|
+
}
|
|
670
|
+
]
|
|
671
|
+
if CONFIG.HOST and CONFIG.UNAME
|
|
672
|
+
else []
|
|
673
|
+
)
|
|
674
|
+
|
|
642
675
|
@staticmethod
|
|
643
676
|
def __traceback_markup(exc_traceback_info: str) -> List[dict]:
|
|
644
677
|
"""Create the traceback markup.
|
|
@@ -833,6 +866,7 @@ class Jira:
|
|
|
833
866
|
+ self.__date_markup()
|
|
834
867
|
+ self.__runlink_markup()
|
|
835
868
|
+ self.__environment_markup()
|
|
869
|
+
+ self.__host_markup()
|
|
836
870
|
+ self.__branch_info_markup(exc_traceback)
|
|
837
871
|
+ (self.__description_markup(additional_info) if additional_info else [])
|
|
838
872
|
+ self.__traceback_markup(exc_traceback_info)
|
|
@@ -1121,9 +1155,10 @@ class Jira:
|
|
|
1121
1155
|
else []
|
|
1122
1156
|
)
|
|
1123
1157
|
|
|
1124
|
-
if len(issue.get("fields", {}).get("comment", [])) >=
|
|
1158
|
+
if len(issue.get("fields", {}).get("comment", [])) >= CONFIG.LIMITS.COMMENT_LIMIT:
|
|
1125
1159
|
logger.warning(
|
|
1126
|
-
f"Comments for '{issue.get('key')}' were not posted due to exceeding JIRA comments limit
|
|
1160
|
+
f"Comments for '{issue.get('key')}' were not posted due to exceeding JIRA comments limit "
|
|
1161
|
+
f"({CONFIG.LIMITS.COMMENT_LIMIT})."
|
|
1127
1162
|
)
|
|
1128
1163
|
return
|
|
1129
1164
|
|
|
@@ -1146,6 +1181,7 @@ class Jira:
|
|
|
1146
1181
|
attachments: Optional[List] = None,
|
|
1147
1182
|
labels: Optional[list] = None,
|
|
1148
1183
|
priority: Optional[str] = None,
|
|
1184
|
+
team: Optional[str] = None,
|
|
1149
1185
|
) -> requests.Response:
|
|
1150
1186
|
"""Create a new ticket.
|
|
1151
1187
|
|
|
@@ -1156,6 +1192,7 @@ class Jira:
|
|
|
1156
1192
|
attachments (List, optional): The list of attachments. Defaults to None.
|
|
1157
1193
|
labels (List, optional): The list of labels. Defaults to None.
|
|
1158
1194
|
priority (str, optional): The priority of the ticket. Defaults to None.
|
|
1195
|
+
team (str, optional): The team to be assigned to the Jira issue. Defaults to None.
|
|
1159
1196
|
|
|
1160
1197
|
Returns:
|
|
1161
1198
|
The response from creating the ticket.
|
|
@@ -1185,6 +1222,7 @@ class Jira:
|
|
|
1185
1222
|
"project_key": project_key,
|
|
1186
1223
|
"labels": labels,
|
|
1187
1224
|
"priority": priority,
|
|
1225
|
+
"team": team,
|
|
1188
1226
|
}
|
|
1189
1227
|
|
|
1190
1228
|
issue = self.__generate_issue_body(**issue_body)
|
|
@@ -1270,20 +1308,24 @@ class Jira:
|
|
|
1270
1308
|
self,
|
|
1271
1309
|
exception: Optional[Exception] = None,
|
|
1272
1310
|
assignee: Optional[str] = None,
|
|
1311
|
+
team: Optional[str] = None,
|
|
1273
1312
|
attachments: Union[List, str, Path, None] = None,
|
|
1274
1313
|
stack_trace: Optional[str] = None,
|
|
1275
1314
|
metadata: Optional[dict] = None,
|
|
1276
1315
|
additional_info: Optional[str] = None,
|
|
1316
|
+
group_by: Optional[str] = None,
|
|
1277
1317
|
) -> dict:
|
|
1278
1318
|
"""Create a Jira issue with the given attachments.
|
|
1279
1319
|
|
|
1280
1320
|
Args:
|
|
1281
1321
|
exception (Exception, optional): The exception to be added to the Jira issue.
|
|
1282
1322
|
assignee (str, optional): The assignee to be added to the Jira issue.
|
|
1323
|
+
team (str, optional): The team to be assigned to the Jira issue. Defaults to None.
|
|
1283
1324
|
attachments (List, optional): List of attachments to be added to the Jira issue.
|
|
1284
1325
|
stack_trace (str, optional): Stack trace to be added to the Jira issue.
|
|
1285
1326
|
metadata (dict, optional): Metadata to be added to the Jira issue.
|
|
1286
1327
|
additional_info (str, optional): Additional information to be added to the Jira issue.
|
|
1328
|
+
group_by (str, optional): group_by flag to be added to the Jira issue.
|
|
1287
1329
|
|
|
1288
1330
|
Returns:
|
|
1289
1331
|
The response from creating the Jira issue.
|
|
@@ -1309,13 +1351,31 @@ class Jira:
|
|
|
1309
1351
|
logger.warning(f"Only the first {CONFIG.LIMITS.MAX_ATTACHMENTS} attachments were uploaded.")
|
|
1310
1352
|
attachments = attachments[: CONFIG.LIMITS.MAX_ATTACHMENTS]
|
|
1311
1353
|
|
|
1312
|
-
|
|
1313
|
-
|
|
1354
|
+
error_id = self.__generate_error_id(exception)
|
|
1355
|
+
group_id = self.generate_group_id(group_by)
|
|
1314
1356
|
|
|
1357
|
+
all_issues = self.get_issues()["issues"]
|
|
1315
1358
|
existing_ticket = self.filter_tickets(
|
|
1316
|
-
all_tickets=
|
|
1359
|
+
all_tickets=all_issues,
|
|
1317
1360
|
error_id=error_id,
|
|
1318
1361
|
)
|
|
1362
|
+
|
|
1363
|
+
if group_id:
|
|
1364
|
+
existing_tickets = [
|
|
1365
|
+
ticket
|
|
1366
|
+
for ticket in all_issues
|
|
1367
|
+
if ticket["fields"]["description"] and f"{error_id}-" in ticket["fields"]["description"]
|
|
1368
|
+
]
|
|
1369
|
+
summary = self.__create_summary(
|
|
1370
|
+
type(exception),
|
|
1371
|
+
exception,
|
|
1372
|
+
exception.__traceback__,
|
|
1373
|
+
len(existing_tickets) + 1 if existing_tickets else 1,
|
|
1374
|
+
)
|
|
1375
|
+
error_id = f"{error_id}-{group_id}"
|
|
1376
|
+
else:
|
|
1377
|
+
summary = self.__create_summary(type(exception), exception, exception.__traceback__)
|
|
1378
|
+
|
|
1319
1379
|
if existing_ticket:
|
|
1320
1380
|
self.__update_existing_ticket(
|
|
1321
1381
|
existing_ticket=existing_ticket,
|
|
@@ -1357,6 +1417,7 @@ class Jira:
|
|
|
1357
1417
|
attachments=attachments,
|
|
1358
1418
|
labels=["bug_catcher"],
|
|
1359
1419
|
priority=priority,
|
|
1420
|
+
team=team,
|
|
1360
1421
|
)
|
|
1361
1422
|
if stack_trace and os.path.exists(stack_trace):
|
|
1362
1423
|
os.remove(stack_trace)
|
|
@@ -1366,23 +1427,20 @@ class Jira:
|
|
|
1366
1427
|
self.report_internal_error(exception=ex, additional_info="Failed to report error.")
|
|
1367
1428
|
return False
|
|
1368
1429
|
|
|
1369
|
-
def report_unhandled_error(
|
|
1370
|
-
self, exc_type: type, exc_value: Union[Exception, str], exc_traceback: TracebackType, stack_trace: str = None
|
|
1371
|
-
):
|
|
1430
|
+
def report_unhandled_error(self, exception: Exception, stack_trace: str = None):
|
|
1372
1431
|
"""Report an unhandled error to Jira.
|
|
1373
1432
|
|
|
1374
1433
|
Args:
|
|
1375
1434
|
exc_type (type): The type of the exception.
|
|
1376
|
-
|
|
1377
|
-
exc_traceback (TracebackType): The traceback of the exception.
|
|
1435
|
+
exception (Exception, str): The value of the exception.
|
|
1378
1436
|
stack_trace (str, optional): Stack trace to be added to the Jira issue.
|
|
1379
1437
|
|
|
1380
1438
|
Returns:
|
|
1381
1439
|
The response from creating the Jira issue.
|
|
1382
1440
|
"""
|
|
1383
1441
|
try:
|
|
1384
|
-
summary = self.__create_summary(
|
|
1385
|
-
error_id = self.__generate_error_id(
|
|
1442
|
+
summary = self.__create_summary(type(exception), exception, exception.__traceback__)
|
|
1443
|
+
error_id = self.__generate_error_id(exception)
|
|
1386
1444
|
|
|
1387
1445
|
existing_ticket = self.filter_tickets(
|
|
1388
1446
|
all_tickets=self.get_issues()["issues"],
|
|
@@ -1405,9 +1463,9 @@ class Jira:
|
|
|
1405
1463
|
logger.info(f"Failed to get assignee {self._default_assignee} due to: {ex}")
|
|
1406
1464
|
|
|
1407
1465
|
description = self.__create_description_markup(
|
|
1408
|
-
exc_type=
|
|
1409
|
-
exc_value=
|
|
1410
|
-
exc_traceback=
|
|
1466
|
+
exc_type=type(exception),
|
|
1467
|
+
exc_value=exception,
|
|
1468
|
+
exc_traceback=exception.__traceback__,
|
|
1411
1469
|
error_id=error_id,
|
|
1412
1470
|
)
|
|
1413
1471
|
|
|
@@ -1434,6 +1492,8 @@ class Jira:
|
|
|
1434
1492
|
|
|
1435
1493
|
Args:
|
|
1436
1494
|
exception (Exception): The exception to be added to the Jira issue.
|
|
1495
|
+
metadata (dict, optional): The metadata to be added to the Jira issue. Defaults to None.
|
|
1496
|
+
additional_info (str, optional): Additional information to be added to the Jira issue. Defaults to None.
|
|
1437
1497
|
|
|
1438
1498
|
Returns:
|
|
1439
1499
|
The response from creating the Jira issue.
|
|
@@ -1445,7 +1505,7 @@ class Jira:
|
|
|
1445
1505
|
attachments = [str(file) for file in Path().cwd().glob("stack_details_*.json")]
|
|
1446
1506
|
|
|
1447
1507
|
summary = self.__create_summary(type(exception), exception, exception.__traceback__)
|
|
1448
|
-
error_id = self.__generate_error_id(
|
|
1508
|
+
error_id = self.__generate_error_id(exception)
|
|
1449
1509
|
|
|
1450
1510
|
existing_ticket = self.filter_tickets(
|
|
1451
1511
|
all_tickets=self.get_issues(project_key=CONFIG.BC_BOARD)["issues"],
|
|
@@ -1613,30 +1673,47 @@ class Jira:
|
|
|
1613
1673
|
for ticket in all_tickets:
|
|
1614
1674
|
if not ticket["fields"]["description"]:
|
|
1615
1675
|
continue
|
|
1616
|
-
if error_id not in ticket["fields"]["description"]:
|
|
1676
|
+
if f"{error_id}_~" not in ticket["fields"]["description"]:
|
|
1617
1677
|
continue
|
|
1618
1678
|
return ticket
|
|
1619
1679
|
|
|
1620
1680
|
else:
|
|
1621
1681
|
return None
|
|
1622
1682
|
|
|
1623
|
-
def
|
|
1683
|
+
def generate_group_id(self, group_by: Optional[str] = None) -> Optional[str]:
|
|
1684
|
+
"""Generates a group ID based on the provided group_by string.
|
|
1685
|
+
|
|
1686
|
+
Args:
|
|
1687
|
+
group_by (str): The string to use for generating the group ID.
|
|
1688
|
+
|
|
1689
|
+
Returns:
|
|
1690
|
+
str or None: The generated group ID if group_by is not None, otherwise None.
|
|
1691
|
+
"""
|
|
1692
|
+
if not group_by:
|
|
1693
|
+
return None
|
|
1694
|
+
crc_hash = zlib.crc32(group_by.encode())
|
|
1695
|
+
return format(crc_hash, "x")
|
|
1696
|
+
|
|
1697
|
+
def __generate_error_id(self, exception: Exception) -> str:
|
|
1624
1698
|
"""Generates an error string ID using the exception, function name, and error string.
|
|
1625
1699
|
|
|
1626
1700
|
Args:
|
|
1627
|
-
|
|
1628
|
-
exc_traceback (TracebackType): The traceback of the exception.
|
|
1701
|
+
exception (Exception):
|
|
1629
1702
|
|
|
1630
1703
|
Returns:
|
|
1631
|
-
str: The generated error string ID.
|
|
1704
|
+
str: The generated error string ID and the group ID.
|
|
1632
1705
|
|
|
1633
1706
|
"""
|
|
1634
|
-
frames = get_frames(
|
|
1707
|
+
frames = get_frames(exception.__traceback__)
|
|
1635
1708
|
exception_chain = "-".join([f"{frame.name}" for frame in frames])
|
|
1636
1709
|
rel_path = os.path.relpath(frames[-1].filename, os.getcwd())
|
|
1637
1710
|
path = Path(os.path.splitext(rel_path)[0]).as_posix()
|
|
1638
|
-
|
|
1639
|
-
|
|
1711
|
+
path = remove_holotree_id(path)
|
|
1712
|
+
error_id = (
|
|
1713
|
+
f"{path}-{exception_chain}-{frames[-1].line}-" f"{type(exception).__module__}-{type(exception).__name__}"
|
|
1714
|
+
)
|
|
1715
|
+
hashed_id = hashlib.md5(error_id.encode()).hexdigest()
|
|
1716
|
+
return hashed_id
|
|
1640
1717
|
|
|
1641
1718
|
@staticmethod
|
|
1642
1719
|
def __generate_warning_id(inspected_frame) -> tuple:
|
|
@@ -1689,7 +1766,9 @@ class Jira:
|
|
|
1689
1766
|
return str(message)
|
|
1690
1767
|
return re.sub(r"\'(.+)\'", "'...'", message)
|
|
1691
1768
|
|
|
1692
|
-
def __create_summary(
|
|
1769
|
+
def __create_summary(
|
|
1770
|
+
self, exc_type: type, exc_value: Union[Exception, str], exc_traceback: TracebackType, idx: Optional[int] = None
|
|
1771
|
+
) -> str:
|
|
1693
1772
|
"""Create the summary of the ticket.
|
|
1694
1773
|
|
|
1695
1774
|
Args:
|
|
@@ -1702,7 +1781,11 @@ class Jira:
|
|
|
1702
1781
|
"""
|
|
1703
1782
|
frames = get_frames(exc_traceback)
|
|
1704
1783
|
file_name, line_no, _, _ = frames[-1]
|
|
1705
|
-
|
|
1784
|
+
|
|
1785
|
+
if idx:
|
|
1786
|
+
summary = f"[{exc_type.__name__}:{os.path.basename(file_name)}:{line_no}({idx})]"
|
|
1787
|
+
else:
|
|
1788
|
+
summary = f"[{exc_type.__name__}:{os.path.basename(file_name)}:{line_no}]"
|
|
1706
1789
|
if self._project_key == CONFIG.SUPPORT_BOARD and CONFIG.ADMIN_CODE:
|
|
1707
1790
|
summary = CONFIG.ADMIN_CODE + " - " + summary
|
|
1708
1791
|
if CONFIG.LIMITS.SUMMARY_LENGTH <= len(summary):
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
+
import re
|
|
4
5
|
import traceback
|
|
5
6
|
import urllib
|
|
6
7
|
from datetime import date, datetime
|
|
@@ -101,6 +102,19 @@ def strip_path(path: str):
|
|
|
101
102
|
return path.replace(os.getcwd(), "").strip(os.sep)
|
|
102
103
|
|
|
103
104
|
|
|
105
|
+
def remove_holotree_id(path: str) -> str:
|
|
106
|
+
"""A function to remove the value after 'holotree' from the path.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
path (str): The path from which to remove the value after 'holotree'.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
str: The modified path.
|
|
113
|
+
"""
|
|
114
|
+
pattern = r"(holotree\/)[^\/]+\/"
|
|
115
|
+
return re.sub(pattern, r"\1", path)
|
|
116
|
+
|
|
117
|
+
|
|
104
118
|
def retrieve_build_info():
|
|
105
119
|
"""Logs build information."""
|
|
106
120
|
if not os.path.exists(CONFIG.BUILD_INFO_FILE):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|