Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 9 additions & 35 deletions .github/workflows/code_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,8 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: false
submodules: true

- name: Checkout makers-devops
uses: actions/checkout@v4
with:
repository: Infineon/makers-devops
path: extras/makers-devops

- name: Set strategy matrix
id: set-matrix
Expand Down Expand Up @@ -130,54 +125,33 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: false

- name: Checkout makers-devops
uses: actions/checkout@v4
with:
repository: Infineon/makers-devops
path: extras/makers-devops
submodules: true

- name: Download cppcheck artifacts
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
name: code-quality-cppcheck
path: _results

- name: Download clang-tidy artifacts
uses: actions/download-artifact@v4
with:
name: code-quality-clang-tidy
path: _results

- name: Merge cppcheck and clang-tidy Reports
- name: Generate Reports
run: |
python3 extras/makers-devops/tools/code_checks/merge_clang_tidy_cppcheck.py \
--logDir=_results/clang-tidy/code-quality-clang-tidy \
--xmlPath=_results/cppcheck/code-quality-cppcheck/code-quality-cppcheck-errors.xml

cppcheck-htmlreport \
--file=_results/cppcheck/code-quality-cppcheck/code-quality-cppcheck-errors.xml \
--title=CPPCheck \
--report-dir=_results/cppcheck/code-quality-cppcheck/html-report \
--source-dir=.
extras/makers-devops/tools/code_checks/run_generate_reports.sh _results

- name: Upload HTML report as artifact
uses: actions/upload-artifact@v4
with:
name: html-report
path: _results/cppcheck/code-quality-cppcheck/html-report
path: _results/html-report

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: _results/cppcheck/code-quality-cppcheck/html-report
publish_dir: _results/html-report
keep_files: false

- name: Display Report URL
run: |
REPORT_URL="https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/"
echo "**Deploying report to GitHub Pages**" >> $GITHUB_STEP_SUMMARY
echo "[View Cppcheck and Clang-tidy Report]($REPORT_URL)" >> $GITHUB_STEP_SUMMARY
echo "URL: $REPORT_URL" # Also print it in logs for visibility
echo "[View Code Quality Report]($REPORT_URL)" >> $GITHUB_STEP_SUMMARY
echo "URL: $REPORT_URL" # Also print it in logs for visibility
29 changes: 17 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ FQBN ?= infineon:psoc6:cy8ckit_062s2_ai
TARGET ?= test_interrupts_single

##############################################################################################################################################################
CLANGTIDY_OUTPUT=_results/clang-tidy/check-clang-tidy
CPPCHECK_OUTPUT=_results/cppcheck/check-cppcheck

RESULT_DIRECTORY=_results
CLANGTIDY_OUTPUT=$(RESULT_DIRECTORY)/clang-tidy/check-clang-tidy
CPPCHECK_OUTPUT=$(RESULT_DIRECTORY)/cppcheck/check-cppcheck
##############################################################################################################################################################

TAG=latest
Expand All @@ -25,6 +25,7 @@ CODECHECK=extras/makers-devops/tools/code_checks/codeChecks.py
MERGEXML=extras/makers-devops/tools/code_checks/merge_clang_tidy_cppcheck.py
PROJECTYAML=config/project.yml
USERYAML=config/user.yml
GENERATEREPORT=./extras/makers-devops/tools/code_checks/run_generate_reports.sh

pull-container:
docker pull $(REGISTRY)
Expand All @@ -34,22 +35,26 @@ run-container-check-all: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --getAllChecks
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runAllChecks

run-container-cppcheck: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck check-cppcheck
run-container-source-cppcheck: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck source-code-quality-cppcheck

run-container-source-clang-tidy-check: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck source-code-quality-clang-tidy

run-container-test-cppcheck: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck test-code-quality-cppcheck

run-container-clang-tidy-check: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck check-clang-tidy
run-container-test-clang-tidy-check: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck test-code-quality-clang-tidy

run-container-clang-tidy-format: pull-container
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck clang-format
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck code-quality-clang-format

run-container-black-format:
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck black-format
$(DOCKER) python3 $(CODECHECK) --projectYAML $(PROJECTYAML) --userYAML $(USERYAML) --runCheck code-quality-black-format

run-container-generate-html-report: pull-container
$(DOCKER) python3 $(MERGEXML) --logDir=$(CLANGTIDY_OUTPUT) --xmlPath=$(CPPCHECK_OUTPUT)/check-cppcheck-errors.xml
$(DOCKER) cppcheck-htmlreport --file=$(CPPCHECK_OUTPUT)/check-cppcheck-errors.xml --title=CPPCheck --report-dir=$(CPPCHECK_OUTPUT)/html-report --source-dir=. 2>&1 | tee -a $(CPPCHECK_OUTPUT)/check-cppcheck.log
firefox _results/cppcheck/check-cppcheck/html-report/index.html
$(DOCKER) $(GENERATEREPORT) --results-dir $(RESULT_DIRECTORY)

##############################################################################################################################################################

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
73 changes: 58 additions & 15 deletions tools/code_checks/merge_clang_tidy_cppcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,36 @@
from xml.dom import minidom
import argparse

def create_results_xml(file_path):
"""
This function is used to initialize the XML file where code check results will be appended.
It creates an XML file with a root element named "results" and a version attribute set to "2".

Args:
file_path (str): The path where the XML file will be created.
"""
# Create the root element
root = ET.Element("results")
root.set("version", "2")

# Create an ElementTree object from the root
tree = ET.ElementTree(root)

# Write the XML to the specified file with the proper declaration
with open(file_path, "wb") as f:
tree.write(f, encoding="utf-8", xml_declaration=True)

def append_code_check_xml_to_results_xml(output_xml_path, xml_file):
tree = ET.parse(output_xml_path)
root = tree.getroot()
xml_tree = ET.parse(xml_file)
xml_root = xml_tree.getroot()

for child in xml_root:
root.append(child)

# Write back the updated results.xml
tree.write(output_xml_path, encoding="utf-8", xml_declaration=True)

def parse_clang_tidy_log(file_path):
errors = []
Expand Down Expand Up @@ -32,8 +62,8 @@ def parse_clang_tidy_log(file_path):
return errors


def append_clang_tidy_results_to_xml(xml_path, results):
tree = ET.parse(xml_path)
def append_clang_tidy_results_to_xml(output_xml_path, clang_tidy_results):
tree = ET.parse(output_xml_path)
root = tree.getroot()

# Check if clang-tidy section exists, else create it
Expand All @@ -45,7 +75,7 @@ def append_clang_tidy_results_to_xml(xml_path, results):
errors_section = clang_tidy_section.find("errors")
existing_errors = set()

for result in results:
for result in clang_tidy_results:
unique_id = (
result["file"],
result["line"],
Expand Down Expand Up @@ -80,20 +110,26 @@ def append_clang_tidy_results_to_xml(xml_path, results):
xml_str = ET.tostring(root, encoding="unicode")
pretty_xml_str = minidom.parseString(xml_str).toprettyxml(indent=" ")

with open(xml_path, "w") as file:
with open(output_xml_path, "w") as file:
file.write(pretty_xml_str)


def main(clang_tidy_log_dir, cppcheck_xml_path):
clang_tidy_results = []
def main(clang_tidy_log_dir, cppcheck_xml_path, output_xml_path):
create_results_xml(output_xml_path)

for log_file in os.listdir(clang_tidy_log_dir):
if log_file.endswith(".log"):
log_path = os.path.join(clang_tidy_log_dir, log_file)
results = parse_clang_tidy_log(log_path)
clang_tidy_results.extend(results)
if cppcheck_xml_path != "":
append_code_check_xml_to_results_xml(output_xml_path, cppcheck_xml_path)

if clang_tidy_log_dir != "":
clang_tidy_results = []

append_clang_tidy_results_to_xml(cppcheck_xml_path, clang_tidy_results)
for log_file in os.listdir(clang_tidy_log_dir):
if log_file.endswith(".log"):
log_path = os.path.join(clang_tidy_log_dir, log_file)
results = parse_clang_tidy_log(log_path)
clang_tidy_results.extend(results)

append_clang_tidy_results_to_xml(output_xml_path, clang_tidy_results)


if __name__ == "__main__":
Expand All @@ -103,14 +139,21 @@ def main(clang_tidy_log_dir, cppcheck_xml_path):
parser.add_argument(
"--logDir",
type=str,
required=True,
default="",
help="Directory containing clang-tidy log files.",
)
parser.add_argument(
"--xmlPath",
type=str,
default="",
help="Path to the cppcheck XML file.",
)
parser.add_argument(
"--outputPath",
type=str,
required=True,
help="Path to the cppcheck XML file to append results.",
help="Path to the output XML file to append results.",
)
args = parser.parse_args()
main(args.logDir, args.xmlPath)
main(args.logDir, args.xmlPath, args.outputPath)

124 changes: 124 additions & 0 deletions tools/code_checks/run_generate_reports.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/bin/bash

echo "Executing $* ..."

usage() {
echo "Usage: $0 [--results-dir] <Results directory> [--merge-script] <Path to merge script> [--source-dir] <Source directory>" 1>&2
exit 1
}

TEMP=`getopt -o r:m:s: --long results-dir:,merge-script:,source-dir: -n "$0" -- "$@"`
if [ $? != 0 ]; then
echo "Terminating..." >&2
usage
exit 1
fi

eval set -- "$TEMP"

results_dir=""
merge_script="extras/makers-devops/tools/code_checks/merge_clang_tidy_cppcheck.py"
source_dir="."

while true; do
case "$1" in
--results-dir ) results_dir=$2; shift 2 ;;
--merge-script ) merge_script=$2; shift 2 ;;
--source-dir ) source_dir=$2; shift 2 ;;
-- ) shift; break ;;
* ) echo "Unknown option '$1' found!"; usage; break ;;
esac
done

if [ -z "$results_dir" ]; then
echo "Error: --results-dir is required."
usage
fi

html_report_base_dir="${results_dir}/html-reports"
mkdir -p "${html_report_base_dir}"

echo ""
echo "results-dir : $results_dir"
echo "merge-script : $merge_script"
echo "source-dir : $source_dir"
echo ""

# Collect cppcheck XML files and clang-tidy directories into arrays
declare -A cppcheck_reports
declare -A clang_tidy_reports

# Find cppcheck XML files for each group (source, library, test, etc.)
if [ -d "${results_dir}/cppcheck" ]; then
for file in $(find "${results_dir}/cppcheck" -name "*.xml"); do
group=$(basename "$(dirname "${file}")" | sed -E 's/-cppcheck.*//') # Extract group name (e.g., source, examples, test)
cppcheck_reports["${group}"]="${cppcheck_reports[${group}]} ${file}"
done
fi

# Find clang-tidy directories for each group
if [ -d "${results_dir}/clang-tidy" ]; then
for dir in $(find "${results_dir}/clang-tidy" -type d -name "*-clang-tidy"); do
group=$(basename "${dir}" | sed -E 's/-clang-tidy//') # Extract group name (e.g., source, library, test)
clang_tidy_reports["${group}"]="${clang_tidy_reports[${group}]} ${dir}"
done
fi

# Check if any reports are found
if [ ${#cppcheck_reports[@]} -eq 0 ] && [ ${#clang_tidy_reports[@]} -eq 0 ]; then
echo "Error: No cppcheck or clang-tidy reports found in ${results_dir}. Exiting."
exit 1
fi

# Print collected tool reports for debugging
echo "Found cppcheck reports:"
for group in "${!cppcheck_reports[@]}"; do
echo " ${group}: ${cppcheck_reports[$group]}"
done

echo "Found clang-tidy reports:"
for group in "${!clang_tidy_reports[@]}"; do
echo " ${group}: ${clang_tidy_reports[$group]}"
done

# Process each group and generate reports
for group in "${!cppcheck_reports[@]}" "${!clang_tidy_reports[@]}"; do
merged_report_xml="${results_dir}/${group}-code-check.xml"
html_report_dir="${html_report_base_dir}/${group}"

cppcheck_xml_files=${cppcheck_reports[$group]}
clang_tidy_dirs=${clang_tidy_reports[$group]}

echo "Processing group: ${group}"
echo " cppcheck reports: ${cppcheck_xml_files}"
echo " clang-tidy directories: ${clang_tidy_dirs}"

# Merge reports using the Python script
if [ ! -f "${merge_script}" ]; then
echo "Error: Merge script not found at ${merge_script}. Exiting."
exit 1
fi

echo "Merging tool reports for group '${group}' into a single XML..."
python3 "${merge_script}" \
--logDir="$(echo ${clang_tidy_dirs} | tr ' ' ',')" \
--xmlPath="$(echo ${cppcheck_xml_files} | tr ' ' ',')" \
--outputPath="${merged_report_xml}"

# Generate HTML report for this group
echo "Generating HTML report for group '${group}'..."
mkdir -p "${html_report_dir}"
cppcheck-htmlreport \
--file="${merged_report_xml}" \
--title="Code Check Report - ${group}" \
--report-dir="${html_report_dir}" \
--source-dir="${source_dir}"

echo "HTML report for group '${group}' available at: ${html_report_dir}"
done

# Set permissions
chown -R --reference=. "${html_report_base_dir}"

echo "$0 done."
exit 0