Refactor CodeQL CI (#3319)
- Move CodeQL scripts to the scripts directory - Only report error in CI if it's a CodeQL reported issue and was not dismissed before and is likely to be an actual error
This commit is contained in:
124
.github/scripts/codeql_fail_on_error.py
vendored
Executable file
124
.github/scripts/codeql_fail_on_error.py
vendored
Executable file
@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import requests
|
||||
|
||||
|
||||
def fetch_dismissed_alerts(repo_name, github_token):
|
||||
headers = {
|
||||
"Authorization": f"token {github_token}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
url = (
|
||||
f"https://api.github.com/repos/{repo_name}/code-scanning/alerts?state=dismissed"
|
||||
)
|
||||
response = requests.get(url, headers=headers)
|
||||
return response.json() # This assumes a successful API call
|
||||
|
||||
|
||||
def parse_location(location):
|
||||
path = location.get("physicalLocation", {}).get("artifactLocation", {}).get("uri")
|
||||
start_line = location.get("physicalLocation", {}).get("region", {}).get("startLine")
|
||||
column_range = (
|
||||
location.get("physicalLocation", {}).get("region", {}).get("startColumn"),
|
||||
location.get("physicalLocation", {}).get("region", {}).get("endColumn"),
|
||||
)
|
||||
return (path, start_line, column_range)
|
||||
|
||||
|
||||
def is_dismissed(rule_id, path, start_line, column_range, dismissed_alerts):
|
||||
for alert in dismissed_alerts:
|
||||
alert_rule_id = alert.get("rule", {}).get("id")
|
||||
alert_path = alert.get("location", {}).get("path")
|
||||
alert_start_line = alert.get("location", {}).get("start_line")
|
||||
alert_column_range = (
|
||||
alert.get("location", {}).get("start_column"),
|
||||
alert.get("location", {}).get("end_column"),
|
||||
)
|
||||
|
||||
if (
|
||||
rule_id == alert_rule_id
|
||||
and path == alert_path
|
||||
and start_line == alert_start_line
|
||||
and column_range == alert_column_range
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Return whether SARIF file contains error-level results
|
||||
def codeql_sarif_contain_error(filename, dismissed_alerts):
|
||||
has_error = False
|
||||
|
||||
with open(filename, "r") as f:
|
||||
s = json.load(f)
|
||||
|
||||
for run in s.get("runs", []):
|
||||
rules_metadata = run["tool"]["driver"]["rules"]
|
||||
if not rules_metadata:
|
||||
rules_metadata = run["tool"]["extensions"][0]["rules"]
|
||||
|
||||
for res in run.get("results", []):
|
||||
if "ruleIndex" in res:
|
||||
rule_index = res["ruleIndex"]
|
||||
elif "rule" in res and "index" in res["rule"]:
|
||||
rule_index = res["rule"]["index"]
|
||||
else:
|
||||
continue
|
||||
|
||||
# check whether it's dismissed before
|
||||
rule_id = res["ruleId"]
|
||||
path, start_line, column_range = parse_location(res["locations"][0])
|
||||
# the source code is from dependencies
|
||||
if "_deps" in path:
|
||||
continue
|
||||
if is_dismissed(rule_id, path, start_line, column_range, dismissed_alerts):
|
||||
print(
|
||||
f"====== Finding a dismissed entry: {rule_id} at {path}:{start_line} is dismissed.======"
|
||||
)
|
||||
print(res)
|
||||
continue
|
||||
|
||||
try:
|
||||
rule_level = rules_metadata[rule_index]["defaultConfiguration"]["level"]
|
||||
except IndexError as e:
|
||||
print(e, rule_index, len(rules_metadata))
|
||||
else:
|
||||
if rule_level == "error":
|
||||
# very likely to be an actual error
|
||||
if rules_metadata[rule_index]["properties"].get("precision") in [
|
||||
"high",
|
||||
"very-high",
|
||||
]:
|
||||
# the security severity is above medium(Common Vulnerability Scoring System (CVSS) >= 4.0)
|
||||
if "security-severity" in rules_metadata[rule_index][
|
||||
"properties"
|
||||
] and (
|
||||
float(
|
||||
rules_metadata[rule_index]["properties"][
|
||||
"security-severity"
|
||||
]
|
||||
)
|
||||
> 4.0
|
||||
):
|
||||
print("====== Finding a likely error. ======")
|
||||
print(res)
|
||||
has_error = True
|
||||
|
||||
return has_error
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
|
||||
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY")
|
||||
dismissed_alerts = fetch_dismissed_alerts(GITHUB_REPOSITORY, GITHUB_TOKEN)
|
||||
|
||||
if codeql_sarif_contain_error(sys.argv[1], dismissed_alerts):
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user