From e44dbe8caea98d522f53f7c3b4e6f8e5470f2902 Mon Sep 17 00:00:00 2001 From: Benedikt Fuchs Date: Mon, 1 May 2023 00:10:21 +0200 Subject: [PATCH 1/5] add parsing of multiline errors --- .../plugin.py | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/pytest_github_actions_annotate_failures/plugin.py b/pytest_github_actions_annotate_failures/plugin.py index 8cf1e62..f085993 100644 --- a/pytest_github_actions_annotate_failures/plugin.py +++ b/pytest_github_actions_annotate_failures/plugin.py @@ -2,6 +2,7 @@ from __future__ import annotations import os +import re import sys from collections import OrderedDict from typing import TYPE_CHECKING @@ -43,7 +44,7 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001 filesystempath = os.path.join(runpath, filesystempath) # try to convert to absolute path in GitHub Actions - workspace = os.environ.get("GITHUB_WORKSPACE") + workspace = os.environ.get("GITHUB_WORKSPACE", "") if workspace: full_path = os.path.abspath(filesystempath) try: @@ -77,13 +78,33 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001 _, lineno, message = report.longrepr longrepr += "\n\n" + message elif isinstance(report.longrepr, str): - longrepr += "\n\n" + report.longrepr - + parsed_errors = _try_parse_multi_error_string_message(workspace, filesystempath, report.longrepr) + if parsed_errors is not None: + for _lineno, _message in parsed_errors: + print( + _error_workflow_command(filesystempath, lineno, _lineno + "\n\n" + _message), file=sys.stderr + ) + return + else: + longrepr += "\n\n" + report.longrepr print( _error_workflow_command(filesystempath, lineno, longrepr), file=sys.stderr ) +def _try_parse_multi_error_string_message(workspace, filesystempath, longrepr): + pathspec_regex = re.compile( + rf"(?:(?:{re.escape(workspace)}/)?{re.escape(filesystempath)}:)?(\d+):(?:\d+:)?\s*(.+)") + matches = [ + pathspec_regex.match(line) + for line in longrepr.strip().split("\n") + ] + if not all(matches): + return None + + return [(int(match.group(1)), match.group(2)) for match in matches] + + def _error_workflow_command(filesystempath, lineno, longrepr): # Build collection of arguments. Ordering is strict for easy testing details_dict = OrderedDict() From 0c202c4ddf9b56c5a6c2a551d7dddd1adff9e498 Mon Sep 17 00:00:00 2001 From: Benedikt Fuchs Date: Mon, 1 May 2023 01:16:26 +0200 Subject: [PATCH 2/5] fix wrong parameterization --- pytest_github_actions_annotate_failures/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytest_github_actions_annotate_failures/plugin.py b/pytest_github_actions_annotate_failures/plugin.py index f085993..0b28855 100644 --- a/pytest_github_actions_annotate_failures/plugin.py +++ b/pytest_github_actions_annotate_failures/plugin.py @@ -82,7 +82,7 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001 if parsed_errors is not None: for _lineno, _message in parsed_errors: print( - _error_workflow_command(filesystempath, lineno, _lineno + "\n\n" + _message), file=sys.stderr + _error_workflow_command(filesystempath, _lineno, longrepr + "\n\n" + _message), file=sys.stderr ) return else: From 79cceea5b331b7f5aa841a19721860eafcee5678 Mon Sep 17 00:00:00 2001 From: Benedikt Fuchs Date: Mon, 1 May 2023 01:23:17 +0200 Subject: [PATCH 3/5] group errors on same line --- pytest_github_actions_annotate_failures/plugin.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pytest_github_actions_annotate_failures/plugin.py b/pytest_github_actions_annotate_failures/plugin.py index 0b28855..0f71cc2 100644 --- a/pytest_github_actions_annotate_failures/plugin.py +++ b/pytest_github_actions_annotate_failures/plugin.py @@ -102,7 +102,17 @@ def _try_parse_multi_error_string_message(workspace, filesystempath, longrepr): if not all(matches): return None - return [(int(match.group(1)), match.group(2)) for match in matches] + errors_per_line = {} + + for match in matches: + line_no = int(match.group(1)) + message = match.group(2) + if line_no not in errors_per_line: + errors_per_line[line_no] = message + else: + errors_per_line[line_no] += "\n" + message + + return errors_per_line.items() def _error_workflow_command(filesystempath, lineno, longrepr): From 1749131dca4df2500e857bfdc020f466bd6b93de Mon Sep 17 00:00:00 2001 From: Benedikt Fuchs Date: Fri, 19 May 2023 23:12:37 +0200 Subject: [PATCH 4/5] fix ruff formatting --- pytest_github_actions_annotate_failures/plugin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pytest_github_actions_annotate_failures/plugin.py b/pytest_github_actions_annotate_failures/plugin.py index 0f71cc2..c788e18 100644 --- a/pytest_github_actions_annotate_failures/plugin.py +++ b/pytest_github_actions_annotate_failures/plugin.py @@ -85,8 +85,7 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001 _error_workflow_command(filesystempath, _lineno, longrepr + "\n\n" + _message), file=sys.stderr ) return - else: - longrepr += "\n\n" + report.longrepr + longrepr += "\n\n" + report.longrepr print( _error_workflow_command(filesystempath, lineno, longrepr), file=sys.stderr ) From 334d625d3518da01e9febf0333f9a070d3c47215 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Wed, 15 May 2024 03:35:09 -0400 Subject: [PATCH 5/5] tests: include PyTest 7.4 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 4eb5c52..7514ae7 100644 --- a/tox.ini +++ b/tox.ini @@ -30,7 +30,7 @@ deps = pytest4: pytest>=4.0.0,<5.0.0 pytest5: pytest>=5.0.0,<6.0.0 pytest6: pytest>=6.0.0,<7.0.0 - pytest7: pytest>=7.0.0,<7.4.0 + pytest7: pytest>=7.0.0,<8.0.0 commands = {envpython} -m pytest