Fixed newlines in github_ci_tool.py
This commit is contained in:
+11
-32
@@ -288,13 +288,7 @@ class GitHubCIHelper(BaseTool): # Inherits from BaseTool
|
|||||||
# then a line of hyphens, "Traceback (most recent call last):", and the traceback details.
|
# then a line of hyphens, "Traceback (most recent call last):", and the traceback details.
|
||||||
# It stops before the next failure block or common summary lines.
|
# It stops before the next failure block or common summary lines.
|
||||||
failure_pattern = re.compile(
|
failure_pattern = re.compile(
|
||||||
r"^(FAIL|ERROR): (.*?)\s*\\((.*?)\\)\s*\
|
r"^(FAIL|ERROR): (.*?)\s*\\((.*?)\\)\s*\n-{5,}\\s*\nTraceback \\(most recent call last\\):\\s*\n(.*?)(?=\n(?:FAIL:|ERROR:)|\n-{5,}\\s*\nRan \\d+ tests? in|\\Z)",
|
||||||
-{5,}\\s*\
|
|
||||||
Traceback \\(most recent call last\\):\\s*\
|
|
||||||
(.*?)(?=\
|
|
||||||
(?:FAIL:|ERROR:)|\
|
|
||||||
-{5,}\\s*\
|
|
||||||
Ran \\d+ tests? in|\\Z)",
|
|
||||||
re.DOTALL | re.MULTILINE
|
re.DOTALL | re.MULTILINE
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -307,12 +301,9 @@ Ran \\d+ tests? in|\\Z)",
|
|||||||
|
|
||||||
# Reconstruct a readable failure block
|
# Reconstruct a readable failure block
|
||||||
failure_block = (
|
failure_block = (
|
||||||
f"{failure_type}: {test_name} ({test_module_class})\
|
f"{failure_type}: {test_name} ({test_module_class})\n"
|
||||||
"
|
f"---------------------\n"
|
||||||
f"---------------------\
|
f"Traceback (most recent call last):\n"
|
||||||
"
|
|
||||||
f"Traceback (most recent call last):\
|
|
||||||
"
|
|
||||||
f"{traceback_details}"
|
f"{traceback_details}"
|
||||||
)
|
)
|
||||||
failures.append(failure_block)
|
failures.append(failure_block)
|
||||||
@@ -324,20 +315,14 @@ Ran \\d+ tests? in|\\Z)",
|
|||||||
# Fallback: A more general pattern if the above doesn't match (e.g., due to slight variations in formatting)
|
# Fallback: A more general pattern if the above doesn't match (e.g., due to slight variations in formatting)
|
||||||
# This looks for "FAIL:" or "ERROR:", a line for the test name, then captures content until common separators.
|
# This looks for "FAIL:" or "ERROR:", a line for the test name, then captures content until common separators.
|
||||||
general_failure_pattern = re.compile(
|
general_failure_pattern = re.compile(
|
||||||
r"^(FAIL|ERROR): ([^\
|
r"^(FAIL|ERROR): ([^\n]+)\n(.*?)(?=\n(?:FAIL:|ERROR:)|\n-{20,}\n|Ran \\d+ tests? in|\\Z)",
|
||||||
]+)\
|
|
||||||
(.*?)(?=\
|
|
||||||
(?:FAIL:|ERROR:)|\
|
|
||||||
-{20,}\
|
|
||||||
|Ran \\d+ tests? in|\\Z)",
|
|
||||||
re.DOTALL | re.MULTILINE
|
re.DOTALL | re.MULTILINE
|
||||||
)
|
)
|
||||||
for match in general_failure_pattern.finditer(log_content):
|
for match in general_failure_pattern.finditer(log_content):
|
||||||
failure_type = match.group(1)
|
failure_type = match.group(1)
|
||||||
test_header = match.group(2).strip()
|
test_header = match.group(2).strip()
|
||||||
details = match.group(3).strip()
|
details = match.group(3).strip()
|
||||||
full_block = f"{failure_type}: {test_header}\
|
full_block = f"{failure_type}: {test_header}\n{details}"
|
||||||
{details}"
|
|
||||||
# Avoid adding essentially duplicate or overly broad captures if specific ones exist
|
# Avoid adding essentially duplicate or overly broad captures if specific ones exist
|
||||||
if not any(f.startswith(f"{failure_type}: {test_header}") for f in failures):
|
if not any(f.startswith(f"{failure_type}: {test_header}") for f in failures):
|
||||||
failures.append(full_block)
|
failures.append(full_block)
|
||||||
@@ -353,14 +338,12 @@ Ran \\d+ tests? in|\\Z)",
|
|||||||
start_index = log_content.find(summary_marker)
|
start_index = log_content.find(summary_marker)
|
||||||
if start_index != -1:
|
if start_index != -1:
|
||||||
# Try to find a reasonable end for this summary block
|
# Try to find a reasonable end for this summary block
|
||||||
end_pattern = re.compile(r"Ran \\d+ tests? in [\\d\\.]+s|\
|
end_pattern = re.compile(r"Ran \\d+ tests? in [\\d\\.]+s|\n-{70,}")
|
||||||
-{70,}")
|
|
||||||
end_match = end_pattern.search(log_content, start_index)
|
end_match = end_pattern.search(log_content, start_index)
|
||||||
end_index = end_match.start() if end_match else len(log_content)
|
end_index = end_match.start() if end_match else len(log_content)
|
||||||
failure_summary_block = log_content[start_index:end_index].strip()
|
failure_summary_block = log_content[start_index:end_index].strip()
|
||||||
if failure_summary_block:
|
if failure_summary_block:
|
||||||
failures.append(f"FAILURE SUMMARY BLOCK:\
|
failures.append(f"FAILURE SUMMARY BLOCK:\n{failure_summary_block}")
|
||||||
{failure_summary_block}")
|
|
||||||
self.logger.info("Captured a general failure summary block.")
|
self.logger.info("Captured a general failure summary block.")
|
||||||
return failures
|
return failures
|
||||||
|
|
||||||
@@ -400,19 +383,15 @@ if __name__ == "__main__":
|
|||||||
if isinstance(log_content, str) and not log_content.startswith("Error") and not log_content.startswith("Job") and not log_content.startswith("Failed"):
|
if isinstance(log_content, str) and not log_content.startswith("Error") and not log_content.startswith("Job") and not log_content.startswith("Failed"):
|
||||||
example_logger.info(f"Successfully downloaded logs (length: {len(log_content)} characters).")
|
example_logger.info(f"Successfully downloaded logs (length: {len(log_content)} characters).")
|
||||||
|
|
||||||
example_logger.info("\
|
example_logger.info("\n--- Parsing unittest failures ---")
|
||||||
--- Parsing unittest failures ---")
|
|
||||||
failures = helper.parse_unittest_failures_from_log(log_content)
|
failures = helper.parse_unittest_failures_from_log(log_content)
|
||||||
if failures:
|
if failures:
|
||||||
for i, failure_details in enumerate(failures):
|
for i, failure_details in enumerate(failures):
|
||||||
print(f"\
|
print(f"\nFailure {i+1}:\n{failure_details}")
|
||||||
Failure {i+1}:\
|
|
||||||
{failure_details}")
|
|
||||||
else:
|
else:
|
||||||
print("No specific unittest failures parsed by the tool.")
|
print("No specific unittest failures parsed by the tool.")
|
||||||
# Consider logging the beginning of the log if parsing fails, for debugging the regexes
|
# Consider logging the beginning of the log if parsing fails, for debugging the regexes
|
||||||
# print(f"Log start:\
|
# print(f"Log start:\n{log_content[:2000]}")
|
||||||
{log_content[:2000]}")
|
|
||||||
elif log_content is None:
|
elif log_content is None:
|
||||||
example_logger.error("Could not retrieve log content (returned None).")
|
example_logger.error("Could not retrieve log content (returned None).")
|
||||||
else: # If it\'s an error message string from the function itself
|
else: # If it\'s an error message string from the function itself
|
||||||
|
|||||||
Reference in New Issue
Block a user