Skip to content

Commit

Permalink
Merge branch 'main' into henryiii-patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
henryiii authored Jan 17, 2025
2 parents dbcab5a + fd623c1 commit 2bdc8cd
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 43 deletions.
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ repos:
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.7.0"
rev: "v0.9.2"
hooks:
- id: ruff
args: ["--fix", "--show-fixes"]
- id: ruff-format
6 changes: 4 additions & 2 deletions plugin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ def test_error():
result = testdir.runpytest_subprocess()

result.stderr.re_match_lines(
[r"::error file=test_annotation_pytest_error\.py,line=8::test_error.*",]
[
r"::error file=test_annotation_pytest_error\.py,line=8::test_error.*",
]
)


Expand Down Expand Up @@ -221,7 +223,7 @@ def test_fail():
result = testdir.runpytest_subprocess("--rootdir=foo")
result.stderr.fnmatch_lines(
[
"::error file=test_annotation_fail_cwd.py,line=5::test_fail*assert 0*",
"::error file=test_annotation_fail_cwd0/test_annotation_fail_cwd.py,line=5::test_fail*assert 0*",
]
)

Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ extend-select = [
]
ignore = [
"PLR", # Design related pylint codes
"PT004", # Use underscore for non-returning fixture (use usefixture instead)
]
isort.required-imports = ["from __future__ import annotations"]

Expand Down
80 changes: 42 additions & 38 deletions pytest_github_actions_annotate_failures/plugin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

from __future__ import annotations

import contextlib
Expand All @@ -7,7 +6,7 @@
from typing import TYPE_CHECKING

import pytest
from _pytest._code.code import ExceptionRepr
from _pytest._code.code import ExceptionRepr, ReprEntry
from packaging import version

if TYPE_CHECKING:
Expand Down Expand Up @@ -39,59 +38,65 @@ def pytest_runtest_makereport(item: Item, call): # noqa: ARG001
return

if report.when == "call" and report.failed:
# collect information to be annotated
filesystempath, lineno, _ = report.location

runpath = os.environ.get("PYTEST_RUN_PATH")
if runpath:
filesystempath = os.path.join(runpath, filesystempath)

# try to convert to absolute path in GitHub Actions
workspace = os.environ.get("GITHUB_WORKSPACE")
if workspace:
full_path = os.path.abspath(filesystempath)
try:
rel_path = os.path.relpath(full_path, workspace)
except ValueError:
# os.path.relpath() will raise ValueError on Windows
# when full_path and workspace have different mount points.
# https://github.com/utgwkk/pytest-github-actions-annotate-failures/issues/20
rel_path = filesystempath
if not rel_path.startswith(".."):
filesystempath = rel_path

if lineno is not None:
# 0-index to 1-index
lineno += 1

# get the name of the current failed test, with parametrize info
longrepr = report.head_line or item.name

# get the error message and line number from the actual error
if isinstance(report.longrepr, ExceptionRepr):
if report.longrepr.reprcrash is not None:
longrepr += "\n\n" + report.longrepr.reprcrash.message
tb_entries = report.longrepr.reprtraceback.reprentries
if len(tb_entries) > 1 and tb_entries[0].reprfileloc is not None:
if tb_entries:
entry = tb_entries[0]
# Handle third-party exceptions
lineno = tb_entries[0].reprfileloc.lineno
if isinstance(entry, ReprEntry) and entry.reprfileloc is not None:
lineno = entry.reprfileloc.lineno
filesystempath = entry.reprfileloc.path

elif report.longrepr.reprcrash is not None:
lineno = report.longrepr.reprcrash.lineno
elif isinstance(report.longrepr, tuple):
_, lineno, message = report.longrepr
filesystempath, lineno, message = report.longrepr
longrepr += "\n\n" + message
elif isinstance(report.longrepr, str):
longrepr += "\n\n" + report.longrepr

workflow_command = _build_workflow_command(
"error",
filesystempath,
compute_path(filesystempath),
lineno,
message=longrepr,
)
print(workflow_command, file=sys.stderr)


def compute_path(filesystempath: str) -> str:
"""Extract and process location information from the report."""
runpath = os.environ.get("PYTEST_RUN_PATH")
if runpath:
filesystempath = os.path.join(runpath, filesystempath)

# try to convert to absolute path in GitHub Actions
workspace = os.environ.get("GITHUB_WORKSPACE")
if workspace:
full_path = os.path.abspath(filesystempath)
try:
rel_path = os.path.relpath(full_path, workspace)
except ValueError:
# os.path.relpath() will raise ValueError on Windows
# when full_path and workspace have different mount points.
rel_path = filesystempath
if not rel_path.startswith(".."):
filesystempath = rel_path

return filesystempath


class _AnnotateWarnings:
def pytest_warning_recorded(self, warning_message, when, nodeid, location): # noqa: ARG002
# enable only in a workflow of GitHub Actions
Expand Down Expand Up @@ -133,20 +138,21 @@ def pytest_addoption(parser):
help="Annotate failures in GitHub Actions.",
)


def pytest_configure(config):
if not config.option.exclude_warning_annotations:
config.pluginmanager.register(_AnnotateWarnings(), "annotate_warnings")


def _build_workflow_command(
command_name,
file,
line,
end_line=None,
column=None,
end_column=None,
title=None,
message=None,
command_name: str,
file: str,
line: int,
end_line: int | None = None,
column: int | None = None,
end_column: int | None = None,
title: str | None = None,
message: str | None = None,
):
"""Build a command to annotate a workflow."""
result = f"::{command_name} "
Expand All @@ -160,15 +166,13 @@ def _build_workflow_command(
("title", title),
]

result = result + ",".join(
f"{k}={v}" for k, v in entries if v is not None
)
result = result + ",".join(f"{k}={v}" for k, v in entries if v is not None)

if message is not None:
result = result + "::" + _escape(message)

return result


def _escape(s):
def _escape(s: str) -> str:
return s.replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A")
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ PYTEST_MAJOR_VERSION =
extras = test
deps =
pytest6: pytest>=6.0.0,<7.0.0
pytest7: pytest>=7.0.0,<7.4.0
pytest7: pytest>=7.0.0,<8.0.0
pytest8: pytest>=8.0.0,<9.0.0

commands = {envpython} -m pytest {posargs}

0 comments on commit 2bdc8cd

Please sign in to comment.