[CI] Added feature to filter out files to file_check.py that do not require cppcheck (#7499)
Co-authored-by: supperthomas <78900636@qq.com>
This commit is contained in:
parent
01d1bbe40d
commit
b1584e9fa9
|
@ -1,6 +1,6 @@
|
||||||
name: Static code analysis
|
name: Static code analysis
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
@ -21,16 +21,10 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -qq install cppcheck
|
sudo apt-get -qq install cppcheck
|
||||||
|
pip install click PyYaml
|
||||||
git remote -v
|
git remote -v
|
||||||
git fetch origin
|
git fetch origin
|
||||||
cppcheck --version
|
cppcheck --version
|
||||||
ls
|
ls
|
||||||
git branch -a
|
git branch -a
|
||||||
changed_files=$(git diff --name-only HEAD origin/master | grep -E '\.(c|cpp|cc|cxx)$' || true)
|
python tools/ci/cpp_check.py check
|
||||||
if [ -n "$changed_files" ];then
|
|
||||||
cppcheck --enable=warning,performance,portability --inline-suppr --error-exitcode=1 --force $changed_files
|
|
||||||
err=$?
|
|
||||||
if [ $err -ne 0 ]; then
|
|
||||||
echo "CPPCHECK REPORT, PLEASE CHECK THE WARNING !!!!!!!!!"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# Change Logs:
|
||||||
|
# Date Author Notes
|
||||||
|
# 2023-05-16 dejavudwh the first version
|
||||||
|
#
|
||||||
|
|
||||||
|
import click
|
||||||
|
import logging
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import format_ignore
|
||||||
|
|
||||||
|
class CPPCheck:
|
||||||
|
def __init__(self, file_list):
|
||||||
|
self.file_list = file_list
|
||||||
|
|
||||||
|
def check(self):
|
||||||
|
file_list_filtered = [file for file in self.file_list if file.endswith(('.c', '.cpp', '.cc', '.cxx'))]
|
||||||
|
logging.info("Start to static code analysis.")
|
||||||
|
check_result = True
|
||||||
|
for file in file_list_filtered:
|
||||||
|
result = subprocess.run(['cppcheck', '--enable=warning', 'performance', 'portability', '--inline-suppr', '--error-exitcode=1', '--force', file], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
|
||||||
|
logging.info(result.stdout.decode())
|
||||||
|
logging.info(result.stderr.decode())
|
||||||
|
if result.stderr:
|
||||||
|
check_result = False
|
||||||
|
return check_result
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
@click.pass_context
|
||||||
|
def cli(ctx):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def check():
|
||||||
|
"""
|
||||||
|
static code analysis(cppcheck).
|
||||||
|
"""
|
||||||
|
format_ignore.init_logger()
|
||||||
|
# get modified files list
|
||||||
|
checkout = format_ignore.CheckOut()
|
||||||
|
file_list = checkout.get_new_file()
|
||||||
|
if file_list is None:
|
||||||
|
logging.error("checkout files fail")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# use cppcheck
|
||||||
|
cpp_check = CPPCheck(file_list)
|
||||||
|
cpp_check_result = cpp_check.check()
|
||||||
|
|
||||||
|
if not cpp_check_result:
|
||||||
|
logging.error("static code analysis(cppcheck) fail.")
|
||||||
|
sys.exit(1)
|
||||||
|
logging.info("check success.")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
cli()
|
|
@ -0,0 +1,84 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# Change Logs:
|
||||||
|
# Date Author Notes
|
||||||
|
# 2023-05-16 dejavudwh the first version
|
||||||
|
#
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def init_logger():
|
||||||
|
log_format = "[%(filename)s %(lineno)d %(levelname)s] %(message)s "
|
||||||
|
date_format = '%Y-%m-%d %H:%M:%S %a '
|
||||||
|
logging.basicConfig(level=logging.INFO,
|
||||||
|
format=log_format,
|
||||||
|
datefmt=date_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
class CheckOut:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __exclude_file(self, file_path):
|
||||||
|
dir_number = file_path.split('/')
|
||||||
|
ignore_path = file_path
|
||||||
|
|
||||||
|
# gets the file path depth.
|
||||||
|
for i in dir_number:
|
||||||
|
# current directory.
|
||||||
|
dir_name = os.path.dirname(ignore_path)
|
||||||
|
ignore_path = dir_name
|
||||||
|
# judge the ignore file exists in the current directory.
|
||||||
|
ignore_file_path = os.path.join(dir_name, ".ignore_format.yml")
|
||||||
|
if not os.path.exists(ignore_file_path):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
with open(ignore_file_path) as f:
|
||||||
|
ignore_config = yaml.safe_load(f.read())
|
||||||
|
file_ignore = ignore_config.get("file_path", [])
|
||||||
|
dir_ignore = ignore_config.get("dir_path", [])
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
continue
|
||||||
|
logging.debug("ignore file path: {}".format(ignore_file_path))
|
||||||
|
logging.debug("file_ignore: {}".format(file_ignore))
|
||||||
|
logging.debug("dir_ignore: {}".format(dir_ignore))
|
||||||
|
try:
|
||||||
|
# judge file_path in the ignore file.
|
||||||
|
for file in file_ignore:
|
||||||
|
if file is not None:
|
||||||
|
file_real_path = os.path.join(dir_name, file)
|
||||||
|
if file_real_path == file_path:
|
||||||
|
logging.info("ignore file path: {}".format(file_real_path))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
file_dir_path = os.path.dirname(file_path)
|
||||||
|
for _dir in dir_ignore:
|
||||||
|
if _dir is not None:
|
||||||
|
dir_real_path = os.path.join(dir_name, _dir)
|
||||||
|
if file_dir_path.startswith(dir_real_path):
|
||||||
|
logging.info("ignore dir path: {}".format(dir_real_path))
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
continue
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def get_new_file(self):
|
||||||
|
result = subprocess.run(['git', 'diff', '--name-only', 'HEAD', 'origin/master', '--diff-filter=ACMR', '--no-renames', '--full-index'], stdout = subprocess.PIPE)
|
||||||
|
file_list = result.stdout.decode().strip().split('\n')
|
||||||
|
new_files = []
|
||||||
|
for line in file_list:
|
||||||
|
logging.info("modified file -> {}".format(line))
|
||||||
|
result = self.__exclude_file(line)
|
||||||
|
if result != 0:
|
||||||
|
new_files.append(line)
|
||||||
|
|
||||||
|
return new_files
|
Loading…
Reference in New Issue