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:
parent
2f43b0b696
commit
9f85001061
2 changed files with 24 additions and 34 deletions
|
@ -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])
|
||||
|
|
|
@ -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/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue