Skip to content

Commit 78cede5

Browse files
committed
Emit detailed pytest failure annotations in CI
1 parent ab256dd commit 78cede5

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

.github/workflows/python-ci.yml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,37 @@ jobs:
6767
6868
- name: Enforce pytest pass
6969
if: steps.pytest.outcome == 'failure'
70-
run: exit 1
70+
run: |
71+
python - <<'PY'
72+
from pathlib import Path
73+
import xml.etree.ElementTree as ET
74+
75+
xml_path = Path("python/reports/pytest.xml")
76+
log_path = Path("python/reports/pytest.log")
77+
78+
if xml_path.exists():
79+
root = ET.parse(xml_path).getroot()
80+
emitted = False
81+
for testcase in root.iter("testcase"):
82+
failures = list(testcase.findall("failure")) + list(testcase.findall("error"))
83+
if not failures:
84+
continue
85+
emitted = True
86+
case_id = f"{testcase.attrib.get('classname', '')}.{testcase.attrib.get('name', '')}".strip(".")
87+
for fail in failures:
88+
msg = (fail.attrib.get("message", "") or "pytest failure").replace("\n", " ").strip()
89+
print(f"::error title={case_id}::{msg}")
90+
text = (fail.text or "").strip()
91+
if text:
92+
print(text[:3000])
93+
if not emitted:
94+
print("::error title=pytest::Pytest failed without testcase-level failures in junit XML")
95+
else:
96+
print("::error title=pytest::Missing python/reports/pytest.xml")
97+
98+
if log_path.exists():
99+
tail = log_path.read_text(encoding="utf-8", errors="ignore")[-4000:]
100+
print("---- pytest.log tail ----")
101+
print(tail)
102+
PY
103+
exit 1

0 commit comments

Comments
 (0)