-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from driftregion/static_analysis
add static analysis
- Loading branch information
Showing
33 changed files
with
868 additions
and
427 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
--suppressions-list=.CodeChecker/suppressions.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
#!/usr/bin/env python3 | ||
import os | ||
import sys | ||
import json | ||
import requests | ||
|
||
def chunked(lst, size=50): | ||
"""Yield successive `size`-sized chunks from the list.""" | ||
for i in range(0, len(lst), size): | ||
yield lst[i:i + size] | ||
|
||
def main(report_path): | ||
# 1. Read environment variables needed for GitHub API | ||
github_token = os.environ.get("GITHUB_TOKEN") | ||
if not github_token: | ||
print("Error: GITHUB_TOKEN not found in environment.") | ||
sys.exit(1) | ||
|
||
repository = os.environ.get("GITHUB_REPOSITORY") | ||
if not repository: | ||
print("Error: GITHUB_REPOSITORY not found in environment.") | ||
sys.exit(1) | ||
|
||
head_sha = os.environ.get("GITHUB_HEAD_SHA") | ||
if not head_sha: | ||
print("Error: GITHUB_HEAD_SHA not found in environment.") | ||
sys.exit(1) | ||
|
||
owner, repo = repository.split("/") | ||
headers = { | ||
"Authorization": f"Bearer {github_token}", | ||
"Accept": "application/vnd.github+json" | ||
} | ||
|
||
# 2. Read CodeChecker JSON report | ||
with open(report_path, "r") as f: | ||
data = json.load(f) | ||
|
||
reports = data.get("reports", []) | ||
if not reports: | ||
print("No CodeChecker reports found. Exiting without annotations.") | ||
# Optionally, you might create a check run that says "No issues found". | ||
sys.exit(0) | ||
|
||
# 3. Build annotations from each CodeChecker issue | ||
annotations = [] | ||
highest_severity = "LOW" # track highest severity seen | ||
|
||
for r in reports: | ||
file_path = r["file"]["path"] | ||
line = r.get("line", 1) | ||
col = r.get("column", 1) | ||
message = r.get("message", "No message") | ||
severity = r.get("severity", "LOW") | ||
checker = r.get("checker_name", "UnknownChecker") | ||
|
||
# Convert absolute path to relative if needed: | ||
# e.g. if your build paths differ from your repo structure, | ||
# you might strip out something like GITHUB_WORKSPACE. | ||
# For example: | ||
workspace = os.environ.get("GITHUB_WORKSPACE", "") | ||
if file_path.startswith(workspace): | ||
file_path = file_path[len(workspace)+1:] | ||
|
||
# Convert severity to annotation_level | ||
# GitHub recognizes "notice", "warning", or "failure" for annotation_level. | ||
# We'll treat HIGH as 'failure', otherwise 'warning' or 'notice'. | ||
if severity.upper() == "HIGH": | ||
annotation_level = "failure" | ||
highest_severity = "HIGH" | ||
else: | ||
annotation_level = "warning" | ||
|
||
annotations.append({ | ||
"path": file_path, | ||
"start_line": line, | ||
"end_line": line, | ||
# if you want column coverage: | ||
"start_column": col, | ||
"end_column": col, | ||
"annotation_level": annotation_level, | ||
"message": message, | ||
"title": checker | ||
}) | ||
|
||
# Decide final conclusion: | ||
# e.g., if we found any 'HIGH' severity issues, mark "failure". | ||
# else "success", or "neutral", depending on your preference. | ||
conclusion = "success" | ||
if highest_severity == "HIGH": | ||
conclusion = "failure" | ||
|
||
# 4. Create a check run (status in_progress) to get an ID | ||
create_url = f"https://api.github.com/repos/{owner}/{repo}/check-runs" | ||
create_payload = { | ||
"name": "CodeChecker Analysis", | ||
"head_sha": head_sha, | ||
"status": "in_progress" | ||
} | ||
|
||
resp = requests.post(create_url, headers=headers, json=create_payload) | ||
if resp.status_code not in (200, 201): | ||
print("Error creating check run:", resp.text) | ||
sys.exit(1) | ||
|
||
check_run_id = resp.json()["id"] | ||
print(f"Created check run with ID={check_run_id}") | ||
|
||
# 5. Update the check run in multiple batches if needed (50 annotations per request limit). | ||
update_url = f"https://api.github.com/repos/{owner}/{repo}/check-runs/{check_run_id}" | ||
|
||
all_annotations = len(annotations) | ||
index = 0 | ||
|
||
for chunk in chunked(annotations, 50): | ||
index += len(chunk) | ||
|
||
# Only on the *final chunk* do we set status "completed" with conclusion | ||
is_last_chunk = (index == all_annotations) | ||
|
||
update_payload = { | ||
"name": "CodeChecker Analysis", | ||
"head_sha": head_sha, | ||
# partial updates can keep "status" as "in_progress" until last chunk | ||
"status": "in_progress", | ||
"output": { | ||
"title": "CodeChecker Results", | ||
"summary": f"Found {all_annotations} issue(s).", | ||
"annotations": chunk | ||
} | ||
} | ||
|
||
if is_last_chunk: | ||
update_payload["conclusion"] = conclusion | ||
update_payload["status"] = "completed" | ||
|
||
resp = requests.patch(update_url, headers=headers, json=update_payload) | ||
if resp.status_code not in (200, 201): | ||
print("Error updating check run:", resp.text) | ||
sys.exit(1) | ||
|
||
print(f"Updated check run with {len(chunk)} annotations (total {index}/{all_annotations}). Last chunk: {is_last_chunk}") | ||
|
||
print("All annotations posted successfully.") | ||
|
||
if __name__ == "__main__": | ||
if len(sys.argv) < 2: | ||
print("Usage: python post_to_github.py <report.json>") | ||
sys.exit(1) | ||
main(sys.argv[1]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/bin/bash | ||
|
||
CodeChecker analyze compile_commands.json \ | ||
--ignore .CodeChecker/skipfile_bazel.txt \ | ||
-o reports | ||
|
||
# MISRA checking via CodeChecker isn't working properly. Use ./.cppcheck/run.sh instead. | ||
# CodeChecker analyze compile_commands.json \ | ||
# --ignore .CodeChecker/skipfile_bazel.txt \ | ||
# --ignore .CodeChecker/skipfile_thirdparty.txt \ | ||
# --cppcheckargs .CodeChecker/cppcheckargs.txt \ | ||
# --analyzer-config cppcheck:addons=.cppcheck/misra.json \ | ||
# --analyzer-config cppcheck:platform=unix64 \ | ||
# -o misra_reports |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-*/launcher_maker.cc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-*src/tp/isotp-c/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
misra-c2012-15.5 // Rule 15.5 Advisory A function should have a single point of exit at the end | ||
// A project should not contain unused macro definitions | ||
misra-c2012-2.5:src/uds.h // this file declares macros intended for external use, not all of which are used internally | ||
|
||
// Don't warn on system header contents | ||
*:*/usr/include/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"script": "misra.py", | ||
"args": [ | ||
"--rule-texts=.cppcheck/misra_c_2023__headlines_for_cppcheck.txt" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#!/bin/bash | ||
mkdir -p ./cppcheck_reports ./codechecker_cppcheck_reports | ||
|
||
|
||
cppcheck \ | ||
--project=compile_commands.json \ | ||
--platform=unix64 \ | ||
--enable=all \ | ||
--addon=.cppcheck/misra.json \ | ||
--suppressions-list=.CodeChecker/suppressions.txt \ | ||
--plist-output=cppcheck_reports \ | ||
-DUDS_SYS=UDS_SYS_UNIX \ | ||
--checkers-report=cppcheck_reports/checkers.txt \ | ||
--library=posix \ | ||
--output-file=cppcheck_reports/cppcheck.txt \ | ||
--file-filter='src/*' \ | ||
|
||
|
||
# report-converter -c -t cppcheck -o ./codechecker_cppcheck_reports ./cppcheck_reports | ||
# CodeChecker parse codechecker_cppcheck_reports --trim-path-prefix '*/cppcheck_reports' > report.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
name: Static Analysis | ||
|
||
on: | ||
pull_request: | ||
branches: [ "main" ] | ||
|
||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: checkout | ||
uses: actions/checkout@v3 | ||
|
||
- name: Install dependencies | ||
run: | | ||
sudo apt-get update | ||
sudo apt-get install -y build-essential cmake python3-pip jq cppcheck | ||
pip3 install codechecker requests | ||
CodeChecker analyzers --details | ||
- name: Analyze with CodeChecker | ||
run: | | ||
make static_analysis | ||
- name: Print report summary | ||
run: | | ||
CodeChecker parse reports || true | ||
- name: Generate json report | ||
run: | | ||
CodeChecker parse reports --export json -o report.json || true | ||
- name: Create Check Run with Annotations | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
GITHUB_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | ||
GITHUB_REPOSITORY: ${{ github.repository }} | ||
run: | | ||
python3 .CodeChecker/post_to_github.py report.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
all: static_analysis | ||
|
||
MISRA_RULES_TXT = .cppcheck/misra_c_2023__headlines_for_cppcheck.txt | ||
|
||
$(MISRA_RULES_TXT): | ||
mkdir -p .cppcheck | ||
wget -O $(MISRA_RULES_TXT) https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/tools/-/raw/main/misra_c_2023__headlines_for_cppcheck.txt | ||
|
||
compile_commands.json: | ||
bazel build //:iso14229 && bazel run //:lib_compile_commands | ||
|
||
static_analysis: compile_commands.json $(MISRA_RULES_TXT) | ||
.CodeChecker/run.sh | ||
|
||
.phony: static_analysis compile_commands.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.