diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 584bf618ce5..09168abed02 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -38,7 +38,7 @@ jobs: run: | pip3 install setuptools pip3 install wheel - pip3 install python-magic lxml junitparser gitlint pylint pykwalify yamllint + pip3 install python-magic lxml junitparser gitlint pylint pykwalify yamllint clang-format unidiff pip3 install west - name: west setup @@ -94,16 +94,23 @@ jobs: exit 1; fi + warns=("ClangFormat") files=($(./scripts/ci/check_compliance.py -l)) + for file in "${files[@]}"; do f="${file}.txt" if [[ -s $f ]]; then - errors=$(cat $f) - errors="${errors//'%'/'%25'}" - errors="${errors//$'\n'/'%0A'}" - errors="${errors//$'\r'/'%0D'}" - echo "::error file=${f}::$errors" - exit=1 + results=$(cat $f) + results="${results//'%'/'%25'}" + results="${results//$'\n'/'%0A'}" + results="${results//$'\r'/'%0D'}" + + if [[ "${warns[@]}" =~ "${file}" ]]; then + echo "::warning file=${f}::$results" + else + echo "::error file=${f}::$results" + exit=1 + fi fi done diff --git a/.gitignore b/.gitignore index 66441114df2..f590a8a38bb 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ tags BinaryFiles.txt BoardYml.txt Checkpatch.txt +ClangFormat.txt DevicetreeBindings.txt GitDiffCheck.txt Gitlint.txt diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 33ba1436766..c22c67a35aa 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -19,6 +19,7 @@ import traceback import shlex import shutil import textwrap +import unidiff from yamllint import config, linter @@ -262,6 +263,41 @@ class BoardYmlCheck(ComplianceTest): for file in path.glob("**/board.yml"): self.check_board_file(file, vendor_prefixes) + +class ClangFormatCheck(ComplianceTest): + """ + Check if clang-format reports any issues + """ + name = "ClangFormat" + doc = "See https://docs.zephyrproject.org/latest/contribute/guidelines.html#clang-format for more details." + path_hint = "" + + def run(self): + for file in get_files(): + diff = subprocess.Popen(('git', 'diff', '-U0', '--no-color', COMMIT_RANGE, '--', file), + stdout=subprocess.PIPE, + cwd=GIT_TOP) + try: + subprocess.run(('clang-format-diff.py', '-p1'), + check=True, + stdin=diff.stdout, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=GIT_TOP) + + except subprocess.CalledProcessError as ex: + patchset = unidiff.PatchSet.from_string(ex.output, encoding="utf-8") + for patch in patchset: + for hunk in patch: + # Strip the before and after context + msg = "".join([str(l) for l in hunk[3:-3]]) + # show the hunk at the last line + self.fmtd_failure("notice", + "You may want to run clang-format on this change", + file, line=hunk.source_start + hunk.source_length - 3, + desc=f'\r\n{msg}') + + class DevicetreeBindingsCheck(ComplianceTest): """ Checks if we are introducing any unwanted properties in Devicetree Bindings. diff --git a/scripts/requirements-compliance.txt b/scripts/requirements-compliance.txt index 68469fc80ea..62e51c8d332 100644 --- a/scripts/requirements-compliance.txt +++ b/scripts/requirements-compliance.txt @@ -1,9 +1,11 @@ # COMPLIANCE: required by the compliance scripts # used by ci/check_compliance +clang-format python-magic python-magic-bin; sys_platform == "win32" lxml junitparser>=2 pylint>=3 +unidiff yamllint