mirror of
https://github.com/lvgl/lvgl.git
synced 2026-10-02 10:23:47 +08:00
ci(file_templ_check): move template check next to the other static checks (#10582)
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
name: Compare file templates with file names
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
# https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency
|
||||
# Ensure that only one commit will be running tests at a time on each PR
|
||||
concurrency:
|
||||
group: ${{ github.ref }}-${{ github.workflow }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
template-check:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v7
|
||||
with:
|
||||
python-version: 3.12
|
||||
- name: Compare file templates with file names
|
||||
run: python scripts/lv_templ_check.py --fix
|
||||
- name: Check that repository is clean
|
||||
run: git diff --exit-code >/dev/null 2>&1 || (echo "Please fix template issues using scripts/lv_templ_check.py"; false)
|
||||
@@ -125,6 +125,15 @@ jobs:
|
||||
continue-on-error: true
|
||||
run: python scripts/static_checks/check_comments.py src/core
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# The file name dependent parts of every lv_*.c/lv_*.h file
|
||||
# (@file comment, include guards) must match the file name
|
||||
# ------------------------------------------------------------------
|
||||
- name: "Check: file templates match file names"
|
||||
id: file-template
|
||||
continue-on-error: true
|
||||
run: python scripts/static_checks/check_file_template.py
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Final gate – fail the job if any step above failed.
|
||||
# This gives us full output from every check before failing.
|
||||
@@ -141,7 +150,8 @@ jobs:
|
||||
steps.defconfigs.outcome == 'failure' ||
|
||||
steps.labeler-globs.outcome == 'failure' ||
|
||||
steps.labeler-labels.outcome == 'failure' ||
|
||||
steps.comments.outcome == 'failure'
|
||||
steps.comments.outcome == 'failure' ||
|
||||
steps.file-template.outcome == 'failure'
|
||||
|
||||
run: |
|
||||
echo "Policy check results:"
|
||||
@@ -167,6 +177,7 @@ jobs:
|
||||
print_result "labeler-globs" "${{ steps.labeler-globs.outcome }}"
|
||||
print_result "labeler-labels" "${{ steps.labeler-labels.outcome }}"
|
||||
print_result "comments" "${{ steps.comments.outcome }}"
|
||||
print_result "file-template" "${{ steps.file-template.outcome }}"
|
||||
|
||||
echo "---------------------"
|
||||
echo "One or more policy checks failed. See above for details."
|
||||
|
||||
@@ -36,7 +36,7 @@ repos:
|
||||
# that depend on the file name are correct.
|
||||
- id: template-check
|
||||
name: Comparing file templates with file names
|
||||
entry: python scripts/lv_templ_check.py --fix --quiet
|
||||
entry: python scripts/static_checks/check_file_template.py --fix --quiet
|
||||
stages: [ commit ]
|
||||
language: system
|
||||
pass_filenames: false
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
import re
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Check that the file-name dependent parts of the lv_templ.c/lv_templ.h
|
||||
templates match the actual file name.
|
||||
|
||||
Usage:
|
||||
check_file_template.py [--fix] [-q] [-v]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_PATH = Path(__file__).resolve()
|
||||
LVGL_ROOT_DIR = SCRIPT_PATH.parents[2]
|
||||
|
||||
ignored_file_prefixes = {
|
||||
"lv_conf_template.h",
|
||||
"lv_conf_cmsis.h",
|
||||
"lv_test_perf_conf.h",
|
||||
"lv_font_"
|
||||
"lv_font_",
|
||||
}
|
||||
|
||||
ignored_top_dirs = {
|
||||
".git",
|
||||
"docs"
|
||||
}
|
||||
ignored_top_dirs = {".git", "docs"}
|
||||
|
||||
h_filename_pattern = re.compile(r"lv_[\w.]*\.h")
|
||||
h_pattern = re.compile(
|
||||
@@ -21,15 +31,11 @@ h_pattern = re.compile(
|
||||
r"@file +(\S*).+?"
|
||||
r"\*/\s+?#ifndef +(\w+_H)\s+#define +(\w+_H).+"
|
||||
r"#endif */\* *([^*]+?) *\*/\s*",
|
||||
flags=re.DOTALL
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
|
||||
c_filename_pattern = re.compile(r"lv_[\w.]*\.c")
|
||||
c_pattern = re.compile(
|
||||
r"\s*/\*\*.+?"
|
||||
r"@file +(\S*)",
|
||||
flags=re.DOTALL
|
||||
)
|
||||
c_pattern = re.compile(r"\s*/\*\*.+?" r"@file +(\S*)", flags=re.DOTALL)
|
||||
|
||||
file_comment_help_f = """\
|
||||
'{0}' should have at the top:
|
||||
@@ -59,6 +65,7 @@ instead, has:
|
||||
|
||||
# regex, arg parsing and other stuff skipped here.
|
||||
|
||||
|
||||
def ignore_file(basename):
|
||||
result = False
|
||||
|
||||
@@ -71,38 +78,32 @@ def ignore_file(basename):
|
||||
|
||||
|
||||
def ignore_dir(path):
|
||||
result = False
|
||||
rel = os.path.relpath(path, LVGL_ROOT_DIR)
|
||||
return rel.split(os.sep)[0] in ignored_top_dirs
|
||||
|
||||
for top_dir in ignored_top_dirs:
|
||||
sub_path = os.path.join('lvgl', top_dir)
|
||||
if sub_path in path:
|
||||
result = True
|
||||
break
|
||||
|
||||
return result
|
||||
|
||||
def debug(*args_, **kwargs):
|
||||
if args.verbose:
|
||||
print(*args_, **kwargs)
|
||||
|
||||
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument("--fix", action="store_true", help="fix incorrect files")
|
||||
arg_parser.add_argument("-q", "--quiet", action="store_true", help="don't print mismatch info")
|
||||
arg_parser.add_argument(
|
||||
"-q", "--quiet", action="store_true", help="don't print mismatch info"
|
||||
)
|
||||
arg_parser.add_argument("-v", "--verbose", action="store_true", help="print debug info")
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
cfg_project_dir = '..'
|
||||
base_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
project_dir = os.path.abspath(os.path.join(base_dir, cfg_project_dir))
|
||||
debug(f'ignore dirs [{ignored_top_dirs}]')
|
||||
debug(f"ignore dirs [{ignored_top_dirs}]")
|
||||
|
||||
ok = True
|
||||
|
||||
for root, dirs, basenames in os.walk(project_dir):
|
||||
for root, dirs, basenames in os.walk(LVGL_ROOT_DIR):
|
||||
if ignore_dir(root):
|
||||
continue
|
||||
|
||||
debug(f'root [{root}]')
|
||||
debug(f"root [{root}]")
|
||||
for basename in basenames:
|
||||
if ignore_file(basename):
|
||||
continue
|
||||
@@ -116,74 +117,74 @@ for root, dirs, basenames in os.walk(project_dir):
|
||||
# -------------------------------------------------------------
|
||||
if h_filename_pattern.fullmatch(basename):
|
||||
a_file_was_processed = True
|
||||
debug(f'Opening H file [{path}]')
|
||||
debug(f"Opening H file [{path}]")
|
||||
|
||||
try:
|
||||
with open(path, 'rb') as f:
|
||||
cont = f.read().decode('utf-8')
|
||||
with open(path, "rb") as f:
|
||||
cont = f.read().decode("utf-8")
|
||||
except:
|
||||
print(f'Error attempting UTF-8 decode on [{path}].')
|
||||
print(f"Error attempting UTF-8 decode on [{path}].")
|
||||
traceback.print_exc()
|
||||
continue
|
||||
|
||||
m = h_pattern.fullmatch(cont)
|
||||
if m is not None:
|
||||
debug(' Match.')
|
||||
debug(" Match.")
|
||||
if m[1] != basename:
|
||||
file_ok = False
|
||||
if not args.quiet:
|
||||
print(file_comment_help_f.format(path, basename, m[1]))
|
||||
|
||||
guard_name = f"LV_{basename[3:-2].upper()}_H"
|
||||
if any(m[i] != guard_name for i in range(2, 4+1)):
|
||||
if any(m[i] != guard_name for i in range(2, 4 + 1)):
|
||||
file_ok = False
|
||||
if not args.quiet:
|
||||
print(guard_help_f.format(path, guard_name, m[2], m[3], m[4]))
|
||||
|
||||
replacements = (basename, guard_name, guard_name, guard_name)
|
||||
else:
|
||||
debug(f' No match with regex [{h_pattern.pattern}].')
|
||||
debug(f" No match with regex [{h_pattern.pattern}].")
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# C File?
|
||||
# -------------------------------------------------------------
|
||||
elif c_filename_pattern.fullmatch(basename):
|
||||
a_file_was_processed = True
|
||||
debug(f'Opening C file [{path}]')
|
||||
debug(f"Opening C file [{path}]")
|
||||
|
||||
try:
|
||||
with open(path, 'rb') as f:
|
||||
cont = f.read().decode('utf-8')
|
||||
with open(path, "rb") as f:
|
||||
cont = f.read().decode("utf-8")
|
||||
except:
|
||||
print(f'Error attempting UTF-8 decode on [{path}].')
|
||||
print(f"Error attempting UTF-8 decode on [{path}].")
|
||||
traceback.print_exc()
|
||||
continue
|
||||
|
||||
m = c_pattern.match(cont)
|
||||
if m is not None:
|
||||
debug(' Match.')
|
||||
debug(" Match.")
|
||||
if m[1] != basename:
|
||||
file_ok = False
|
||||
if not args.quiet:
|
||||
print(file_comment_help_f.format(path, basename, m[1]))
|
||||
|
||||
replacements = (basename, )
|
||||
replacements = (basename,)
|
||||
else:
|
||||
debug(f' No match with regex [{c_pattern.pattern}].')
|
||||
debug(f" No match with regex [{c_pattern.pattern}].")
|
||||
|
||||
if a_file_was_processed:
|
||||
if not file_ok:
|
||||
debug(f'NOT OK [{path}]')
|
||||
debug(f"NOT OK [{path}]")
|
||||
ok = False
|
||||
if args.fix:
|
||||
for i in reversed(range(0, len(replacements))):
|
||||
span = m.regs[i + 1]
|
||||
repl = replacements[i]
|
||||
cont = cont[:span[0]] + repl + cont[span[1]:]
|
||||
cont = cont[: span[0]] + repl + cont[span[1] :]
|
||||
with open(path, "w") as f:
|
||||
f.write(cont)
|
||||
else:
|
||||
debug(f'OK [{path}]')
|
||||
debug(f"OK [{path}]")
|
||||
|
||||
|
||||
if not ok:
|
||||
Reference in New Issue
Block a user