Add per-spec fallback for categorized watcher grouped summaries
- update the categorized watcher to fall back to earlier per-spec Run Finished entries when a grouped Cloud Run Finished section is present but does not contain host rows - broaden duration parsing so colon-form timings like 13:59 and 15:32 from per-spec Cypress summaries are converted into seconds correctly - make grouped Mattermost posting resilient across categorized batches whose cloud-summary output is incomplete or inconsistent, not just a single distro family
This commit is contained in:
@@ -265,6 +265,14 @@ def extract_check_xml_timestamp_from_file(xml_path: Path) -> Optional[datetime]:
|
|||||||
|
|
||||||
def parse_duration_seconds(raw: str) -> Optional[float]:
|
def parse_duration_seconds(raw: str) -> Optional[float]:
|
||||||
raw = " ".join(raw.split())
|
raw = " ".join(raw.split())
|
||||||
|
if re.fullmatch(r"\d+:\d+(?::\d+)?", raw):
|
||||||
|
parts = [int(part) for part in raw.split(":")]
|
||||||
|
if len(parts) == 2:
|
||||||
|
minutes, seconds = parts
|
||||||
|
return minutes * 60 + seconds
|
||||||
|
if len(parts) == 3:
|
||||||
|
hours, minutes, seconds = parts
|
||||||
|
return hours * 3600 + minutes * 60 + seconds
|
||||||
match = re.search(r"(?:(\d+)h\s+)?(?:(\d+)m\s+)?(\d+(?:\.\d+)?)(?:s)?", raw)
|
match = re.search(r"(?:(\d+)h\s+)?(?:(\d+)m\s+)?(\d+(?:\.\d+)?)(?:s)?", raw)
|
||||||
if not match:
|
if not match:
|
||||||
return None
|
return None
|
||||||
@@ -274,22 +282,11 @@ def parse_duration_seconds(raw: str) -> Optional[float]:
|
|||||||
return hours * 3600 + minutes * 60 + seconds
|
return hours * 3600 + minutes * 60 + seconds
|
||||||
|
|
||||||
|
|
||||||
def extract_completed_subrun_summaries(log_text: str, inventory: Dict[str, str]) -> List[Dict[str, object]]:
|
def extract_host_results_from_run_finished_segment(segment_text: str, inventory: Dict[str, str]) -> Dict[str, HostResult]:
|
||||||
summaries: List[Dict[str, object]] = []
|
|
||||||
cloud_blocks = list(
|
|
||||||
re.finditer(
|
|
||||||
r"Cloud Run Finished(.*?)(?:🏁 Recorded Run:\s*(https://\S+)|\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} - INFO - Detected 'Recorded Run' after 'Cloud Run Finished' - results uploaded successfully\.)",
|
|
||||||
log_text,
|
|
||||||
re.S,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for block in cloud_blocks:
|
|
||||||
block_text = block.group(1)
|
|
||||||
currents_url = block.group(2)
|
|
||||||
normalized = re.sub(r"\n\s*│\s*s\s*│", "s", block_text)
|
|
||||||
host_results: Dict[str, HostResult] = {}
|
host_results: Dict[str, HostResult] = {}
|
||||||
|
normalized = re.sub(r"\n\s*│\s*s\s*│", "s", segment_text)
|
||||||
for host_match in re.finditer(
|
for host_match in re.finditer(
|
||||||
r"✔\s+(atvm[^\s]+)\.ts\s+([0-9hms.\s]+?)\s+(\d+)\s+(\d+)\s+([-\d]+)\s+([-\d]+)\s+([-\d]+)",
|
r"✔\s+(atvm[^\s]+)\.ts\s+([0-9:hms.\s]+?)\s+(\d+)\s+(\d+)\s+([-\d]+)\s+([-\d]+)\s+([-\d]+)",
|
||||||
normalized,
|
normalized,
|
||||||
re.S,
|
re.S,
|
||||||
):
|
):
|
||||||
@@ -309,7 +306,28 @@ def extract_completed_subrun_summaries(log_text: str, inventory: Dict[str, str])
|
|||||||
failures=failing,
|
failures=failing,
|
||||||
duration_seconds=duration_seconds,
|
duration_seconds=duration_seconds,
|
||||||
)
|
)
|
||||||
|
return host_results
|
||||||
|
|
||||||
|
|
||||||
|
def extract_completed_subrun_summaries(log_text: str, inventory: Dict[str, str]) -> List[Dict[str, object]]:
|
||||||
|
summaries: List[Dict[str, object]] = []
|
||||||
|
cloud_blocks = list(
|
||||||
|
re.finditer(
|
||||||
|
r"Cloud Run Finished(.*?)(?:🏁 Recorded Run:\s*(https://\S+)|\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} - INFO - Detected 'Recorded Run' after 'Cloud Run Finished' - results uploaded successfully\.)",
|
||||||
|
log_text,
|
||||||
|
re.S,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
previous_block_end = 0
|
||||||
|
for block in cloud_blocks:
|
||||||
|
block_text = block.group(1)
|
||||||
|
currents_url = block.group(2)
|
||||||
|
host_results = extract_host_results_from_run_finished_segment(block_text, inventory)
|
||||||
if not host_results:
|
if not host_results:
|
||||||
|
prior_segment = log_text[previous_block_end:block.start()]
|
||||||
|
host_results = extract_host_results_from_run_finished_segment(prior_segment, inventory)
|
||||||
|
if not host_results:
|
||||||
|
previous_block_end = block.end()
|
||||||
continue
|
continue
|
||||||
summaries.append(
|
summaries.append(
|
||||||
{
|
{
|
||||||
@@ -317,6 +335,7 @@ def extract_completed_subrun_summaries(log_text: str, inventory: Dict[str, str])
|
|||||||
"currents_url": currents_url,
|
"currents_url": currents_url,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
previous_block_end = block.end()
|
||||||
return summaries
|
return summaries
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user