scripts: Make workflow of test_plan.py script more robust

The script was not resolving all detected changes uniformly:
find_excludes() could skip or not certain patterns based on
required testing scope. The idea was to not include files
that were already handled by find_test() and find_boards() workflows.
However, only boards and tests folders could be removed but
not samples. This also led to blind spots: changes in some files
were not triggering any tests. E.g. change in a test/common, where
no corresponding yaml can be found by find_tests() which is also
ignored by find_excludes(). In the new workflow a list of resolved
files (for which find_arch(), find_tests() or find_boards()
found scope) is created. Instead of using skip in find_excludes,
files are excluded only if they were resolved.

Signed-off-by: Maciej Perkowski <Maciej.Perkowski@nordicsemi.no>
This commit is contained in:
Maciej Perkowski 2023-08-17 14:34:31 +02:00 committed by Anas Nashif
commit 9f85001061
2 changed files with 24 additions and 34 deletions

View file

@ -97,13 +97,13 @@ class Filters:
pull_request=False, platforms=[], detailed_test_id=True):
self.modified_files = modified_files
self.testsuite_root = testsuite_root
self.resolved_files = []
self.twister_options = []
self.full_twister = False
self.all_tests = []
self.tag_options = []
self.pull_request = pull_request
self.platforms = platforms
self.default_run = False
self.detailed_test_id = detailed_test_id
self.ignore_path = ignore_path
self.tag_cfg_file = alt_tags
@ -115,10 +115,6 @@ class Filters:
if not self.platforms:
self.find_archs()
self.find_boards()
if self.default_run:
self.find_excludes(skip=["tests/*", "boards/*/*/*"])
else:
self.find_excludes()
def get_plan(self, options, integration=False, use_testsuite_root=True):
@ -200,6 +196,8 @@ class Filters:
archs.add('riscv64')
else:
archs.add(p.group(1))
# Modified file is treated as resolved, since a matching scope was found
self.resolved_files.append(f)
_options = []
for arch in archs:
@ -218,6 +216,7 @@ class Filters:
def find_boards(self):
boards = set()
all_boards = set()
resolved = []
for f in self.modified_files:
if f.endswith(".rst") or f.endswith(".png") or f.endswith(".jpg"):
@ -225,6 +224,7 @@ class Filters:
p = re.match(r"^boards\/[^/]+\/([^/]+)\/", f)
if p and p.groups():
boards.add(p.group(1))
resolved.append(f)
roots = [zephyr_base]
if repository_path != zephyr_base:
@ -239,10 +239,16 @@ class Filters:
if name_re.search(kb.name):
all_boards.add(kb.name)
# If modified file is catched by "find_boards" workflow (change in "boards" dir AND board recognized)
# it means a proper testing scope for this file was found and this file can be removed
# from further consideration
for board in all_boards:
self.resolved_files.extend(list(filter(lambda f: board in f, resolved)))
_options = []
if len(all_boards) > 20:
logging.warning(f"{len(boards)} boards changed, this looks like a global change, skipping test handling, revert to default.")
self.default_run = True
self.full_twister = True
return
for board in all_boards:
@ -262,6 +268,8 @@ class Filters:
if os.path.exists(os.path.join(d, "testcase.yaml")) or \
os.path.exists(os.path.join(d, "sample.yaml")):
tests.add(d)
# Modified file is treated as resolved, since a matching scope was found
self.resolved_files.append(f)
break
else:
d = os.path.dirname(d)
@ -272,7 +280,7 @@ class Filters:
if len(tests) > 20:
logging.warning(f"{len(tests)} tests changed, this looks like a global change, skipping test handling, revert to default")
self.default_run = True
self.full_twister = True
return
if _options:
@ -328,21 +336,22 @@ class Filters:
ignores = filter(lambda x: not x.startswith("#"), ignores)
found = set()
files = list(filter(lambda x: x, self.modified_files))
files_not_resolved = list(filter(lambda x: x not in self.resolved_files, self.modified_files))
for pattern in ignores:
if pattern in skip:
continue
if pattern:
found.update(fnmatch.filter(files, pattern))
found.update(fnmatch.filter(files_not_resolved, pattern))
logging.debug(found)
logging.debug(files)
logging.debug(files_not_resolved)
if sorted(files) != sorted(found):
# Full twister run can be ordered by detecting great number of tests/boards changed
# or if not all modified files were resolved (corresponding scope found)
self.full_twister = self.full_twister or sorted(files_not_resolved) != sorted(found)
if self.full_twister:
_options = []
logging.info(f'Need to run full or partial twister...')
self.full_twister = True
if self.platforms:
for platform in self.platforms:
_options.extend(["-p", platform])

View file

@ -17,25 +17,6 @@ CODEOWNERS
MAINTAINERS.yml
LICENSE
Makefile
tests/*
samples/*
boards/*/*/*
arch/xtensa/*
arch/x86/*
arch/posix/*
arch/arc/*
arch/sparc/*
arch/arm/*
arch/nios2/*
arch/riscv/*
include/arch/xtensa/*
include/arch/x86/*
include/arch/posix/*
include/arch/arc/*
include/arch/sparc/*
include/arch/arm/*
include/arch/nios2/*
include/arch/riscv/*
doc/*
# GH action have no impact on code
.github/*