Skip to content

Commit 7468f79

Browse files
committed
enrich maintenance issue classification with step name from junit XML
When build-log.txt lacks the "Logs for container test in pod" pattern (e.g. pod killed during init), fall through to check junit_operator.xml before returning a generic Maintenance Issue. Extract the pod/step name from the junit failure message as a fallback when the test case name doesn't contain it. The categorization now shows which step failed (e.g. "Maintenance Issue: openshift-qe-orion-node-density failed in test phase") instead of a generic message. Signed-off-by: Mohit Sheth <msheth@redhat.com>
1 parent f4633fc commit 7468f79

3 files changed

Lines changed: 43 additions & 23 deletions

File tree

bugzooka/analysis/failure_keywords.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
FAILURE_KEYWORDS = {
2+
"maintenance issue": ("Maintenance", "maintenance issue"),
23
"install": ("Install", "installation failure"),
34
"provision": ("Provision", "provision failure"),
45
"deprovision": ("Deprovision", "deprovision failure"),
@@ -8,5 +9,4 @@
89
"node-readiness": ("Node Readiness", "node-readiness check failure"),
910
"openshift-qe": ("Workload", "openshift-qe workload failure"),
1011
"upgrade": ("Upgrade", "upgrade failure"),
11-
"maintenance issue": ("Maintenance", "maintenance issue"),
1212
}

bugzooka/analysis/prow_analyzer.py

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,7 @@ def _build_changepoint_preview(json_data, test_label):
8686
lines.append(f"\n[{test_label}]")
8787

8888
github_ctx = entry.get("github_context") or {}
89-
version = github_ctx.get(
90-
"current_version", entry.get("ocpVersion", "unknown")
91-
)
89+
version = github_ctx.get("current_version", entry.get("ocpVersion", "unknown"))
9290
prs = entry.get("prs", [])
9391
lines.append(f" {', '.join(regressed)}")
9492
lines.append(f" Changepoint at: {version}")
@@ -138,9 +136,11 @@ def scan_orion_jsons(directory_path):
138136

139137
# Per-step subdirectories: each subdir name matches the viz URL key
140138
# (both derived from strip_step_prefixes on the GCS folder name).
141-
step_subdirs = sorted(
142-
[d for d in base_dir.iterdir() if d.is_dir()]
143-
) if base_dir.exists() else []
139+
step_subdirs = (
140+
sorted([d for d in base_dir.iterdir() if d.is_dir()])
141+
if base_dir.exists()
142+
else []
143+
)
144144

145145
if step_subdirs:
146146
json_pairs = [
@@ -153,7 +153,9 @@ def scan_orion_jsons(directory_path):
153153
json_files = list(base_dir.glob("*.json")) if base_dir.exists() else []
154154
if not json_files:
155155
root = Path(directory_path)
156-
json_files = list(root.glob("junit_*.json")) or list(root.glob("output_*.json"))
156+
json_files = list(root.glob("junit_*.json")) or list(
157+
root.glob("output_*.json")
158+
)
157159
json_pairs = [(strip_step_prefixes(f.stem), f) for f in json_files]
158160

159161
preview_results, changepoint_tests = _collect_changepoints(json_pairs)
@@ -260,18 +262,6 @@ def analyze_prow_artifacts(directory_path, job_name):
260262
),
261263
None,
262264
)
263-
if matched_line is None:
264-
matched_line = (
265-
"Couldn't identify the failure step, likely a maintanence issue"
266-
)
267-
return ProwAnalysisResult(
268-
errors=[matched_line],
269-
categorization_message=MAINTENANCE_ISSUE,
270-
requires_llm=False,
271-
is_install_issue=True,
272-
step_name=None,
273-
full_errors_for_file=None,
274-
)
275265
junit_operator_file_path = os.path.join(directory_path, "junit_operator.xml")
276266
# Defaults in case XML parsing yields no values
277267
step_phase, step_name, step_summary = None, None, ""
@@ -293,10 +283,35 @@ def analyze_prow_artifacts(directory_path, job_name):
293283
step_name, step_phase, job_name
294284
)
295285
else:
296-
categorization_message = categorize_prow_failure(
297-
matched_line, "unknown", job_name
298-
)
286+
if matched_line is not None:
287+
categorization_message = categorize_prow_failure(
288+
matched_line, "unknown", job_name
289+
)
290+
else:
291+
categorization_message = MAINTENANCE_ISSUE
299292
step_summary = ""
293+
if matched_line is None:
294+
if step_name and step_phase:
295+
return ProwAnalysisResult(
296+
errors=[step_summary] if step_summary else [],
297+
categorization_message=(
298+
f"Maintenance Issue: {step_name} failed in" f" {step_phase} phase"
299+
),
300+
requires_llm=False,
301+
is_install_issue=True,
302+
step_name=step_name,
303+
full_errors_for_file=None,
304+
)
305+
return ProwAnalysisResult(
306+
errors=[
307+
"Couldn't identify the failure step," " likely a maintenance issue"
308+
],
309+
categorization_message=MAINTENANCE_ISSUE,
310+
requires_llm=False,
311+
is_install_issue=True,
312+
step_name=None,
313+
full_errors_for_file=None,
314+
)
300315
cluster_operators_file_path = os.path.join(directory_path, "clusteroperators.json")
301316
if not os.path.isfile(cluster_operators_file_path):
302317
with open(build_file_path, "r", errors="replace", encoding="utf-8") as f:

bugzooka/analysis/xmlparser.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import re
23

34
try:
45
import xmltodict # type: ignore
@@ -75,6 +76,10 @@ def summarize_junit_operator_xml(xml_path):
7576
# If all found, no need to keep looping
7677
if test_phase and test_name and failure_message:
7778
break
79+
if not test_name and failure_message:
80+
pod_match = re.search(r'pod\s+"([^"]+)"', failure_message)
81+
if pod_match:
82+
test_name = pod_match.group(1)
7883
return test_phase, test_name, failure_message
7984
except Exception as e:
8085
logger.error("Error parsing junit_operator.xml file: %s", e)

0 commit comments

Comments
 (0)