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):
|
pull_request=False, platforms=[], detailed_test_id=True):
|
||||||
self.modified_files = modified_files
|
self.modified_files = modified_files
|
||||||
self.testsuite_root = testsuite_root
|
self.testsuite_root = testsuite_root
|
||||||
|
self.resolved_files = []
|
||||||
self.twister_options = []
|
self.twister_options = []
|
||||||
self.full_twister = False
|
self.full_twister = False
|
||||||
self.all_tests = []
|
self.all_tests = []
|
||||||
self.tag_options = []
|
self.tag_options = []
|
||||||
self.pull_request = pull_request
|
self.pull_request = pull_request
|
||||||
self.platforms = platforms
|
self.platforms = platforms
|
||||||
self.default_run = False
|
|
||||||
self.detailed_test_id = detailed_test_id
|
self.detailed_test_id = detailed_test_id
|
||||||
self.ignore_path = ignore_path
|
self.ignore_path = ignore_path
|
||||||
self.tag_cfg_file = alt_tags
|
self.tag_cfg_file = alt_tags
|
||||||
|
@ -115,11 +115,7 @@ class Filters:
|
||||||
if not self.platforms:
|
if not self.platforms:
|
||||||
self.find_archs()
|
self.find_archs()
|
||||||
self.find_boards()
|
self.find_boards()
|
||||||
|
self.find_excludes()
|
||||||
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):
|
def get_plan(self, options, integration=False, use_testsuite_root=True):
|
||||||
fname = "_test_plan_partial.json"
|
fname = "_test_plan_partial.json"
|
||||||
|
@ -200,6 +196,8 @@ class Filters:
|
||||||
archs.add('riscv64')
|
archs.add('riscv64')
|
||||||
else:
|
else:
|
||||||
archs.add(p.group(1))
|
archs.add(p.group(1))
|
||||||
|
# Modified file is treated as resolved, since a matching scope was found
|
||||||
|
self.resolved_files.append(f)
|
||||||
|
|
||||||
_options = []
|
_options = []
|
||||||
for arch in archs:
|
for arch in archs:
|
||||||
|
@ -218,6 +216,7 @@ class Filters:
|
||||||
def find_boards(self):
|
def find_boards(self):
|
||||||
boards = set()
|
boards = set()
|
||||||
all_boards = set()
|
all_boards = set()
|
||||||
|
resolved = []
|
||||||
|
|
||||||
for f in self.modified_files:
|
for f in self.modified_files:
|
||||||
if f.endswith(".rst") or f.endswith(".png") or f.endswith(".jpg"):
|
if f.endswith(".rst") or f.endswith(".png") or f.endswith(".jpg"):
|
||||||
|
@ -225,6 +224,7 @@ class Filters:
|
||||||
p = re.match(r"^boards\/[^/]+\/([^/]+)\/", f)
|
p = re.match(r"^boards\/[^/]+\/([^/]+)\/", f)
|
||||||
if p and p.groups():
|
if p and p.groups():
|
||||||
boards.add(p.group(1))
|
boards.add(p.group(1))
|
||||||
|
resolved.append(f)
|
||||||
|
|
||||||
roots = [zephyr_base]
|
roots = [zephyr_base]
|
||||||
if repository_path != zephyr_base:
|
if repository_path != zephyr_base:
|
||||||
|
@ -239,10 +239,16 @@ class Filters:
|
||||||
if name_re.search(kb.name):
|
if name_re.search(kb.name):
|
||||||
all_boards.add(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 = []
|
_options = []
|
||||||
if len(all_boards) > 20:
|
if len(all_boards) > 20:
|
||||||
logging.warning(f"{len(boards)} boards changed, this looks like a global change, skipping test handling, revert to default.")
|
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
|
return
|
||||||
|
|
||||||
for board in all_boards:
|
for board in all_boards:
|
||||||
|
@ -262,6 +268,8 @@ class Filters:
|
||||||
if os.path.exists(os.path.join(d, "testcase.yaml")) or \
|
if os.path.exists(os.path.join(d, "testcase.yaml")) or \
|
||||||
os.path.exists(os.path.join(d, "sample.yaml")):
|
os.path.exists(os.path.join(d, "sample.yaml")):
|
||||||
tests.add(d)
|
tests.add(d)
|
||||||
|
# Modified file is treated as resolved, since a matching scope was found
|
||||||
|
self.resolved_files.append(f)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
d = os.path.dirname(d)
|
d = os.path.dirname(d)
|
||||||
|
@ -272,7 +280,7 @@ class Filters:
|
||||||
|
|
||||||
if len(tests) > 20:
|
if len(tests) > 20:
|
||||||
logging.warning(f"{len(tests)} tests changed, this looks like a global change, skipping test handling, revert to default")
|
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
|
return
|
||||||
|
|
||||||
if _options:
|
if _options:
|
||||||
|
@ -328,21 +336,22 @@ class Filters:
|
||||||
ignores = filter(lambda x: not x.startswith("#"), ignores)
|
ignores = filter(lambda x: not x.startswith("#"), ignores)
|
||||||
|
|
||||||
found = set()
|
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:
|
for pattern in ignores:
|
||||||
if pattern in skip:
|
|
||||||
continue
|
|
||||||
if pattern:
|
if pattern:
|
||||||
found.update(fnmatch.filter(files, pattern))
|
found.update(fnmatch.filter(files_not_resolved, pattern))
|
||||||
|
|
||||||
logging.debug(found)
|
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 = []
|
_options = []
|
||||||
logging.info(f'Need to run full or partial twister...')
|
logging.info(f'Need to run full or partial twister...')
|
||||||
self.full_twister = True
|
|
||||||
if self.platforms:
|
if self.platforms:
|
||||||
for platform in self.platforms:
|
for platform in self.platforms:
|
||||||
_options.extend(["-p", platform])
|
_options.extend(["-p", platform])
|
||||||
|
|
|
@ -17,25 +17,6 @@ CODEOWNERS
|
||||||
MAINTAINERS.yml
|
MAINTAINERS.yml
|
||||||
LICENSE
|
LICENSE
|
||||||
Makefile
|
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/*
|
doc/*
|
||||||
# GH action have no impact on code
|
# GH action have no impact on code
|
||||||
.github/*
|
.github/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue