Fix ATVM mochawesome failure extraction

This commit is contained in:
2026-03-31 08:43:11 -04:00
parent 7ab5daeca8
commit da56c2668e
2 changed files with 60 additions and 12 deletions

View File

@@ -540,6 +540,20 @@ def extract_first_json_string(block: str, key: str) -> Optional[str]:
return decode_json_string_fragment(match.group(1))
def extract_step_number(text: str) -> Optional[int]:
match = re.search(r"\b(\d+)\.\s", text)
if not match:
return None
return int(match.group(1))
def extract_testcase_from_host_detail(detail: str) -> Optional[str]:
match = re.match(r"^\d+ tests, \d+ failures(?:, \d+ pending)? - (.+?)(?: - .+)?$", detail)
if not match:
return None
return match.group(1).strip()
def extract_failure_from_mochawesome(
reporter_root: Path,
build_name: str,
@@ -565,15 +579,28 @@ def extract_failure_from_mochawesome(
full_title = decode_json_string_fragment(match.group(1))
if host not in full_title:
continue
block_start = max(0, match.start() - 1200)
block_end = min(len(text), match.end() + 8000)
block = text[block_start:block_end]
if not re.search(r'"state":"failed"', block):
object_start = text.rfind('{"title":"', 0, match.start())
alternate_start = text.rfind(',"title":"', 0, match.start())
if alternate_start != -1 and (object_start == -1 or alternate_start > object_start):
object_start = alternate_start + 1
if object_start == -1:
continue
testcase = extract_first_json_string(block, "title") or "failed testcase"
message = extract_first_json_string(block, "message") or ""
estack = extract_first_json_string(block, "estack") or ""
if testcase or message or estack:
object_end_candidates = [
index for index in (
text.find('},{"title":"', match.end()),
text.find('}]}', match.end()),
text.find('}]}</script>', match.end()),
)
if index != -1
]
object_end = min(object_end_candidates) if object_end_candidates else min(len(text), match.end() + 16000)
obj = text[object_start:object_end]
if not re.search(r'"state":"failed"', obj):
continue
testcase = extract_first_json_string(obj, "title") or "failed testcase"
message = extract_first_json_string(obj, "message") or ""
estack = extract_first_json_string(obj, "estack") or ""
if testcase and (message or estack):
return testcase, message, estack
return None
@@ -584,7 +611,7 @@ def summarize_host_detail_with_mochawesome(detail: str, testcase: str, message:
normalized_message = " ".join((message or "").split())
message_summary = ""
for pattern in (
r"(md5sum:\s.*?)(?:$)",
r"(md5sum:\s.*?No such file or directory)",
r"(sshpass does not contain OK(?:\.\s*Output:)?)(?:$)",
r"(AssertionError:\s.*?)(?:$)",
r"(Timed out!? .*?)(?:$)",
@@ -1203,11 +1230,22 @@ def build_status_markdown(
if not mochawesome_failure:
continue
testcase, message, estack = mochawesome_failure
if not (message or estack):
continue
existing_step = extract_step_number(host.detail)
mochawesome_step = extract_step_number(testcase)
if (
existing_step is not None
and mochawesome_step is not None
and existing_step != mochawesome_step
):
testcase = extract_testcase_from_host_detail(host.detail) or testcase
host.detail = summarize_host_detail_with_mochawesome(host.detail, testcase, message)
failure_excerpt_source = estack or message
failure_notes.append(
f"{host.host} failure excerpt: `{compact_failure_detail(failure_excerpt_source, limit=420)}`"
)
if failure_excerpt_source.strip():
failure_notes.append(
f"{host.host} failure excerpt: `{compact_failure_detail(failure_excerpt_source, limit=420)}`"
)
host_lines = ["| Host | Kernel | Status | Detail |", "| --- | --- | --- | --- |"]
for host in ordered_hosts: