diff --git a/.github/workflows/code_checks.yml b/.github/workflows/code_checks.yml index e4feb19..0b3c108 100644 --- a/.github/workflows/code_checks.yml +++ b/.github/workflows/code_checks.yml @@ -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 @@ -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 diff --git a/Makefile b/Makefile index 221c72f..c05581d 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -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) @@ -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) ############################################################################################################################################################## diff --git a/configs/clang-format/.clang-format b/config/clang-format/.clang-format similarity index 100% rename from configs/clang-format/.clang-format rename to config/clang-format/.clang-format diff --git a/configs/clang-tidy/.clang-tidy b/config/clang-tidy/.clang-tidy similarity index 100% rename from configs/clang-tidy/.clang-tidy rename to config/clang-tidy/.clang-tidy diff --git a/configs/cppcheck/misra.json b/config/cppcheck/misra.json similarity index 100% rename from configs/cppcheck/misra.json rename to config/cppcheck/misra.json diff --git a/configs/cppcheck/misra.txt b/config/cppcheck/misra.txt similarity index 100% rename from configs/cppcheck/misra.txt rename to config/cppcheck/misra.txt diff --git a/tools/code_checks/merge_clang_tidy_cppcheck.py b/tools/code_checks/merge_clang_tidy_cppcheck.py index 284c6b3..752e1de 100755 --- a/tools/code_checks/merge_clang_tidy_cppcheck.py +++ b/tools/code_checks/merge_clang_tidy_cppcheck.py @@ -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 = [] @@ -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 @@ -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"], @@ -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__": @@ -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) + diff --git a/tools/code_checks/run_generate_reports.sh b/tools/code_checks/run_generate_reports.sh new file mode 100644 index 0000000..cd3f8ff --- /dev/null +++ b/tools/code_checks/run_generate_reports.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +echo "Executing $* ..." + +usage() { + echo "Usage: $0 [--results-dir] [--merge-script] [--source-dir] " 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