diff --git a/developer_support_script/check_build_stability.py b/developer_support_script/check_build_stability.py index bfdc597..520d5e2 100644 --- a/developer_support_script/check_build_stability.py +++ b/developer_support_script/check_build_stability.py @@ -5,6 +5,7 @@ job via secret text environment variables """ +import logging import os from collections import Counter, defaultdict from typing import Any @@ -15,6 +16,8 @@ WARNING_THRESHOLD_PERCENTAGE = 10 ERROR_THRESHOLD_PERCENTAGE = 50 +logging.basicConfig(format="%(levelname)s: %(message)s", level=logging.INFO) + def request_json(url: str) -> dict | None: """ @@ -30,11 +33,11 @@ def request_json(url: str) -> dict | None: if request.status_code == requests.codes["ok"]: return request.json() else: - print(f"ERROR: Failed to get '{url}': [{request.status_code}] {request.reason}") + logging.error(f"Failed to get '{url}': [{request.status_code}] {request.reason}") return None -def calculate_level(percentage: int, error_percentage: int, warning_percentage: int) -> str: +def calculate_level(percentage: float, error_percentage: float, warning_percentage: float) -> int: """ Utility function to calculate log level based on a percentage. @@ -44,11 +47,11 @@ def calculate_level(percentage: int, error_percentage: int, warning_percentage: warning_percentage: The warning threshold. """ if percentage >= error_percentage: - return "ERROR" + return logging.ERROR elif percentage >= warning_percentage: - return "WARNING" + return logging.WARNING else: - return "INFO" + return logging.INFO class JobData: @@ -176,14 +179,17 @@ def _get_failed_tests(self) -> Counter: return counter - def print_results(self) -> None: + def print_results(self) -> set[int]: """ Prints the percentage of aborted builds for the job, the percentage of failures with no test report, and the percentage failure of each failing test. + returns levels messages printed at """ + levels = set() if not self.buildable: - print("WARNING: build is currently disabled") - return + logging.warning("build is currently disabled") + levels.add(logging.WARNING) + return levels # Aborted builds. valid_builds = self.num_evaluate_builds + self.no_test_report_failures @@ -194,8 +200,8 @@ def print_results(self) -> None: level = calculate_level( percentage_aborted_builds, ERROR_THRESHOLD_PERCENTAGE, WARNING_THRESHOLD_PERCENTAGE ) - print(f"{level}: Aborted builds [{percentage_aborted_builds:.0f}%]") - + logging.log(level, f"Aborted builds [{percentage_aborted_builds:.0f}%]") + levels.add(level) # Failures with no test report # valid_builds will only be 0 if self.no_test_report_failures is also 0 if valid_builds > 0: @@ -208,10 +214,10 @@ def print_results(self) -> None: ERROR_THRESHOLD_PERCENTAGE, WARNING_THRESHOLD_PERCENTAGE, ) - print( - f"{level}: Failed builds with no Test Report " - f"[{percentage_no_test_report_failures:.0f}%]" + logging.log( + level, f"Failed builds with no Test Report [{percentage_no_test_report_failures:.0f}%]" ) + levels.add(level) # Tests. for name, num in self.failed_tests.most_common(): @@ -222,7 +228,9 @@ def print_results(self) -> None: level = calculate_level( percentage_test_failure, ERROR_THRESHOLD_PERCENTAGE, WARNING_THRESHOLD_PERCENTAGE ) - print(f"{level}: [{percentage_test_failure:.0f}%] {name}") + logging.log(level, f"[{percentage_test_failure:.0f}%] {name}") + levels.add(level) + return levels def process_jobs(jobs: list[str], summary_name: str) -> None: @@ -237,8 +245,16 @@ def process_jobs(jobs: list[str], summary_name: str) -> None: job_summary.add_job(job_data) job_data.print_results() - print(f"****** Summary across {summary_name} jobs ******") - job_summary.print_results() + if job_summary is not None and len(jobs) > 1: + print(f"****** Summary across {len(jobs)} {summary_name} jobs ******") + levels = job_summary.print_results() + for lev in [logging.INFO, logging.ERROR, logging.WARNING]: + if lev not in levels: + logging.log( + lev, + f"OK as threshold not reached when viewed/summed over {len(jobs)} jobs, " + "however individual jobs may have met the threshold", + ) if __name__ == "__main__": @@ -253,7 +269,6 @@ def process_jobs(jobs: list[str], summary_name: str) -> None: ] SQUISH_JOBS = [ "System_Tests_Squish", - "System_Tests_Squish_Win11", ] process_jobs(EPICS_JOBS, "EPICS") process_jobs(SQUISH_JOBS, "SQUISH")