diff --git a/.github/actions/create_workflow_report/ci_run_report.html.jinja b/.github/actions/create_workflow_report/ci_run_report.html.jinja index ac9a7a70bb01..4c94465a16c6 100644 --- a/.github/actions/create_workflow_report/ci_run_report.html.jinja +++ b/.github/actions/create_workflow_report/ci_run_report.html.jinja @@ -226,6 +226,8 @@ element.className = element.className.replace(regex_dir, '') + dir } function getValue(element) { + var childWithSort = element.querySelector('[data-sort]') + if (childWithSort) return childWithSort.getAttribute('data-sort') return ( (alt_sort && element.getAttribute('data-sort-alt')) || element.getAttribute('data-sort') || element.innerText diff --git a/.github/actions/create_workflow_report/create_workflow_report.py b/.github/actions/create_workflow_report/create_workflow_report.py index 90db4cc4ddcc..bb094473eefc 100755 --- a/.github/actions/create_workflow_report/create_workflow_report.py +++ b/.github/actions/create_workflow_report/create_workflow_report.py @@ -26,6 +26,9 @@ GITHUB_REPO = "Altinity/ClickHouse" GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") or os.getenv("GH_TOKEN") +CVE_SEVERITY_ORDER = {"critical": 1, "high": 2, "medium": 3, "low": 4, "negligible": 5} + + def get_commit_statuses(sha: str) -> pd.DataFrame: """ Fetch commit statuses for a given SHA and return as a pandas DataFrame. @@ -498,7 +501,9 @@ def format_prefix(pr_number, commit_sha, branch): Bucket=S3_BUCKET, Prefix=s3_prefix, Delimiter="/" ) grype_result_dirs.extend( - content["Prefix"] for content in response.get("CommonPrefixes", []) + content["Prefix"] + for content in response.get("CommonPrefixes", []) + if isinstance(content, dict) and content.get("Prefix") ) except Exception as e: print(f"Error listing S3 objects at {s3_prefix}: {e}") @@ -536,12 +541,13 @@ def format_prefix(pr_number, commit_sha, branch): return pd.DataFrame() df = pd.DataFrame(rows).drop_duplicates() - df = df.sort_values( - by="severity", - key=lambda col: col.str.lower().map( - {"critical": 1, "high": 2, "medium": 3, "low": 4, "negligible": 5} - ), - ) + + def _cve_sort_key(col): + if col.name == "severity": + return col.str.lower().map(CVE_SEVERITY_ORDER) + return col + + df = df.sort_values(by=["severity", "docker_image"], key=_cve_sort_key) return df @@ -589,6 +595,9 @@ def format_results_as_html_table(results) -> str: "Identifier": lambda i: url_to_html_link( "https://nvd.nist.gov/vuln/detail/" + i ), + "Severity": lambda s: ( + f'{s}' + ), }, escape=False, border=0, @@ -772,11 +781,16 @@ def create_workflow_report( "pr_new_fails": [], "checks_errors": get_checks_errors(db_client, commit_sha, branch_name), "regression_fails": get_regression_fails(db_client, actions_run_url), - "docker_images_cves": ( - [] if not check_cves else get_cves(pr_number, commit_sha, branch_name) - ), + "docker_images_cves": [], } + try: + fail_results["docker_images_cves"] = ( + [] if not check_cves else get_cves(pr_number, commit_sha, branch_name) + ) + except Exception as e: + print(f"Error in get_cves: {e}") + # get_cves returns ... in the case where no Grype result files were found. # This might occur when run in preview mode. cves_not_checked = not check_cves or fail_results["docker_images_cves"] is ...