From 35adff40e07d33d30a58c6fed41cf6e183b2519d Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 29 Nov 2022 17:11:33 +0800 Subject: [PATCH 1/5] ci: get_mr_info support components --- tools/ci/ci_get_mr_info.py | 63 ++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/tools/ci/ci_get_mr_info.py b/tools/ci/ci_get_mr_info.py index da3862d609..e2becc078e 100644 --- a/tools/ci/ci_get_mr_info.py +++ b/tools/ci/ci_get_mr_info.py @@ -10,22 +10,20 @@ import argparse import os import subprocess +import typing as t +from pathlib import Path from gitlab_api import Gitlab -try: - from typing import Any, Union -except ImportError: - # Only used for type annotations - pass +if t.TYPE_CHECKING: + from gitlab.v4.objects import ProjectCommit, ProjectMergeRequest -def _get_mr_obj(source_branch): # type: (str) -> Union[Gitlab, None] - if not source_branch: - return None +def _get_mr_obj(source_branch: str) -> t.Optional['ProjectMergeRequest']: gl = Gitlab(os.getenv('CI_PROJECT_ID', 'espressif/esp-idf')) if not gl.project: return None + mrs = gl.project.mergerequests.list(state='opened', source_branch=source_branch) if mrs: return mrs[0] # one source branch can only have one opened MR at one moment @@ -33,7 +31,7 @@ def _get_mr_obj(source_branch): # type: (str) -> Union[Gitlab, None] return None -def get_mr_iid(source_branch): # type: (str) -> str +def get_mr_iid(source_branch: str) -> str: mr = _get_mr_obj(source_branch) if not mr: return '' @@ -41,40 +39,65 @@ def get_mr_iid(source_branch): # type: (str) -> str return str(mr.iid) -def get_mr_changed_files(source_branch): # type: (str) -> Any +def get_mr_changed_files(source_branch: str) -> t.List[str]: mr = _get_mr_obj(source_branch) if not mr: - return '' + return [] - return subprocess.check_output(['git', 'diff', '--name-only', - 'origin/{}...origin/{}'.format(mr.target_branch, source_branch)]).decode('utf8') + git_output = subprocess.check_output( + ['git', 'diff', '--name-only', f'origin/{mr.target_branch}...origin/{source_branch}'] + ).decode('utf8') + + return [line.strip() for line in git_output.splitlines() if line.strip()] -def get_mr_commits(source_branch): # type: (str) -> str +def get_mr_commits(source_branch: str) -> t.List['ProjectCommit']: mr = _get_mr_obj(source_branch) if not mr: - return '' - return '\n'.join([commit.id for commit in mr.commits()]) + return [] + + return list(mr.commits()) + + +def get_mr_components(source_branch: str) -> t.List[str]: + components: t.Set[str] = set() + for f in get_mr_changed_files(source_branch): + file = Path(f) + if ( + file.parts[0] == 'components' + and 'test_apps' not in file.parts + and file.parts[-1] != '.build-test-rules.yml' + ): + components.add(file.parts[1]) + + return list(components) + + +def _print_list(_list: t.List[str], separator: str = '\n') -> None: + print(separator.join(_list)) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Get the latest merge request info by pipeline') - actions = parser.add_subparsers(dest='action', help='info type') + actions = parser.add_subparsers(dest='action', help='info type', required=True) common_args = argparse.ArgumentParser(add_help=False) - common_args.add_argument('src_branch', nargs='?', help='source branch') + common_args.add_argument('src_branch', help='source branch') actions.add_parser('id', parents=[common_args]) actions.add_parser('files', parents=[common_args]) actions.add_parser('commits', parents=[common_args]) + actions.add_parser('components', parents=[common_args]) args = parser.parse_args() if args.action == 'id': print(get_mr_iid(args.src_branch)) elif args.action == 'files': - print(get_mr_changed_files(args.src_branch)) + _print_list(get_mr_changed_files(args.src_branch)) elif args.action == 'commits': - print(get_mr_commits(args.src_branch)) + _print_list([commit.id for commit in get_mr_commits(args.src_branch)]) + elif args.action == 'components': + _print_list(get_mr_components(args.src_branch)) else: raise NotImplementedError('not possible to get here') From 2cbcafc4d393fd08c758a0c63208a2c8be32fa64 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Wed, 24 May 2023 10:54:11 +0800 Subject: [PATCH 2/5] ci: remove unused variables --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1c7669d66d..e0d1e6edd8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -57,7 +57,6 @@ variables: PYTHON_VER: 3.7.10 CLANG_TIDY_RUNNER_PROJ: 2107 # idf/clang-tidy-runner - IDF_BUILD_APPS_PROJ: 2818 # espressif/idf-build-apps # Docker images BOT_DOCKER_IMAGE_TAG: ":latest" From 22e2738f7831d00bbfdaa1ad7641221df9775b94 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Wed, 24 May 2023 10:53:57 +0800 Subject: [PATCH 3/5] ci: build and test only modified components related test cases --- .gitignore | 2 + .gitlab-ci.yml | 2 + .gitlab/ci/README.md | 13 +- .gitlab/ci/build.yml | 55 +++---- .gitlab/ci/pre_check.yml | 19 +++ .gitlab/ci/rules.yml | 44 +++--- .gitlab/ci/target-test.yml | 1 + .pre-commit-config.yaml | 2 +- conftest.py | 89 +++++++++-- pytest.ini | 2 +- tools/ci/ci_build_apps.py | 143 ++++++++++++++---- .../python_packages/ttfw_idf/IDFAssignTest.py | 2 +- 12 files changed, 274 insertions(+), 100 deletions(-) diff --git a/.gitignore b/.gitignore index 6e1a94fe68..20428dc70e 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,5 @@ managed_components # pytest log pytest_embedded_log/ +list_job_*.txt +size_info.txt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e0d1e6edd8..d44f2fee4b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,9 +20,11 @@ workflow: - if: $CI_OPEN_MERGE_REQUESTS != null variables: PIPELINE_COMMIT_SHA: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA + IS_MR_PIPELINE: 1 - if: $CI_OPEN_MERGE_REQUESTS == null variables: PIPELINE_COMMIT_SHA: $CI_COMMIT_SHA + IS_MR_PIPELINE: 0 - when: always variables: diff --git a/.gitlab/ci/README.md b/.gitlab/ci/README.md index 831a913cd4..e37dbf3384 100644 --- a/.gitlab/ci/README.md +++ b/.gitlab/ci/README.md @@ -21,11 +21,7 @@ - [Shell Script Related](#shell-script-related) - [Manifest File to Control the Build/Test apps](#manifest-file-to-control-the-buildtest-apps) - [Grammar](#grammar) - - [Operands](#operands) - - [Operators](#operators) - - [Limitation:](#limitation) - - [How does it work?](#how-does-it-work) - - [Example](#example) + - [Special Rules](#special-rules) ## General Workflow @@ -242,3 +238,10 @@ We're using the latest version of [idf-build-apps][idf-build-apps]. Please refer [idf-build-apps]: https://github.com/espressif/idf-build-apps [manifest-doc]: https://docs.espressif.com/projects/idf-build-apps/en/latest/manifest.html + +### Special Rules + +In ESP-IDF CI, there's a few more special rules are additionally supported to disable the check app dependencies feature: + +- Add MR labels `BUILD_AND_TEST_ALL_APPS` +- Run in protected branches diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index b3883ede7e..3e0e7e9ca2 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -21,6 +21,8 @@ needs: - job: fast_template_app artifacts: false + - job: mr_variables + optional: true # only MR pipelines would have this artifacts: paths: - "**/build*/size.json" @@ -37,7 +39,7 @@ - "**/build*/sdkconfig" - "**/build*/bootloader/*.bin" - "**/build*/partition_table/*.bin" - - list_job_*.json + - list_job_*.txt - size_info.txt # unit test specific - components/idf_test/unit_test/*.yml @@ -66,18 +68,18 @@ # would be clean up after 4 days - mc share download shiny-s3/idf-artifacts/${CI_PIPELINE_ID}/${CI_JOB_ID}.zip --expire=96h script: - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v -t $IDF_TARGET --copy-sdkconfig - --collect-size-info size_info.txt - --collect-app-info list_job_${CI_NODE_INDEX:-1}.json --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} --extra-preserve-dirs examples/bluetooth/esp_ble_mesh/ble_mesh_console examples/bluetooth/hci/controller_hci_uart_esp32 examples/wifi/iperf + --modified-components ${MR_MODIFIED_COMPONENTS} + --modified-files ${MR_MODIFIED_FILES} .build_cmake_clang_template: extends: @@ -87,14 +89,14 @@ TEST_BUILD_OPTS_EXTRA: "" TEST_DIR: tools/test_apps/system/cxx_pthread_bluetooth script: - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v -t $IDF_TARGET --copy-sdkconfig - --collect-size-info size_info.txt - --collect-app-info list_job_${CI_NODE_INDEX:-1}.json --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} + --modified-components ${MR_MODIFIED_COMPONENTS} + --modified-files ${MR_MODIFIED_FILES} $TEST_BUILD_OPTS_EXTRA .build_pytest_template: @@ -114,30 +116,32 @@ - "**/build*/config/sdkconfig.json" - "**/build*/bootloader/*.bin" - "**/build*/partition_table/*.bin" - - list_job_*.json + - list_job_*.txt - size_info.txt when: always expire_in: 4 days script: - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v -t $IDF_TARGET --pytest-apps - --collect-size-info size_info.txt --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} + --modified-components ${MR_MODIFIED_COMPONENTS} + --modified-files ${MR_MODIFIED_FILES} .build_pytest_no_jtag_template: extends: .build_pytest_template script: - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v -t $IDF_TARGET -m \"not host_test and not jtag\" --pytest-apps - --collect-size-info size_info.txt --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} + --modified-components ${MR_MODIFIED_COMPONENTS} + --modified-files ${MR_MODIFIED_FILES} .build_pytest_jtag_template: extends: @@ -156,19 +160,20 @@ - "**/build*/config/sdkconfig.json" - "**/build*/bootloader/*.bin" - "**/build*/partition_table/*.bin" - - list_job_*.json + - list_job_*.txt - size_info.txt when: always expire_in: 4 days script: - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v -t $IDF_TARGET -m \"not host_test and jtag\" --pytest-apps - --collect-size-info size_info.txt --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} + --modified-components ${MR_MODIFIED_COMPONENTS} + --modified-files ${MR_MODIFIED_FILES} build_pytest_examples_esp32: extends: @@ -310,13 +315,13 @@ build_only_components_apps: parallel: 5 script: - set_component_ut_vars - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py $COMPONENT_UT_DIRS -v -t all - --collect-size-info size_info.txt - --collect-app-info list_job_${CI_NODE_INDEX:-1}.json --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} + --modified-components ${MR_MODIFIED_COMPONENTS} + --modified-files ${MR_MODIFIED_FILES} .build_pytest_test_apps_template: extends: .build_pytest_template @@ -336,7 +341,7 @@ build_only_components_apps: - "**/build*/bootloader/*.bin" - "**/build*/partition_table/*.bin" - "**/build*/project_description.json" - - list_job_*.json + - list_job_*.txt - size_info.txt when: always expire_in: 4 days @@ -404,13 +409,13 @@ build_only_tools_test_apps: - .rules:build:custom_test parallel: 9 script: - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py tools/test_apps -v -t all - --collect-size-info size_info.txt - --collect-app-info list_job_${CI_NODE_INDEX:-1}.json --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} + --modified-components ${MR_MODIFIED_COMPONENTS} + --modified-files ${MR_MODIFIED_FILES} .build_template_app_template: extends: @@ -529,20 +534,18 @@ build_ssc_esp32h2: - "**/build*/sdkconfig" - "**/build*/bootloader/*.bin" - "**/build*/partition_table/*.bin" - - list_job_*.json + - list_job_*.txt - size_info.txt - components/idf_test/unit_test/*.yml when: always expire_in: 4 days script: - # CI specific options start from "--collect-size-info xxx". could ignore when running locally + # CI specific options start from "--parallel-count xxx". could ignore when running locally - run_cmd python tools/ci/ci_build_apps.py tools/unit-test-app -v -t $IDF_TARGET --config "configs/*=" --copy-sdkconfig --preserve-all - --collect-size-info size_info.txt - --collect-app-info list_job_${CI_NODE_INDEX:-1}.json --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} - run_cmd python tools/unit-test-app/tools/UnitTestParser.py tools/unit-test-app ${CI_NODE_INDEX:-1} diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index 0e86577b72..a70f2fd2e0 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -186,3 +186,22 @@ check_configure_ci_environment_parsing: script: - cd tools/ci - python -m unittest ci_build_apps.py + +mr_variables: + extends: + - .pre_check_template + - .rules:mr + - .before_script_minimal + tags: + - build + script: + - echo "MR_MODIFIED_FILES=$(python tools/ci/ci_get_mr_info.py files ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} | xargs)" >> mr.env + - echo "MR_MODIFIED_COMPONENTS=$(python tools/ci/ci_get_mr_info.py components ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} | xargs)" >> mr.env + - > + if echo "$CI_MERGE_REQUEST_LABELS" | egrep "^([^,\n\r]+,)*BUILD_AND_TEST_ALL_APPS(,[^,\n\r]+)*$"; then + echo "BUILD_AND_TEST_ALL_APPS=1" >> mr.env + fi + artifacts: + reports: + dotenv: mr.env + expire_in: 4 days diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index 108c16ef6b..cb1ebb12bc 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -374,6 +374,7 @@ ######### # Rules # ######### +### Branches ### .rules:protected: rules: - <<: *if-protected @@ -382,6 +383,30 @@ rules: - <<: *if-protected-no_label +.rules:dev: + rules: + - <<: *if-trigger + - <<: *if-dev-push + +.rules:mr: + rules: + - <<: *if-dev-push + +.rules:tag:release: + rules: + - <<: *if-tag-release + +.rules:ref:master-schedule: + rules: + - <<: *if-ref-master + - <<: *if-schedule + +.rules:ref:master-always: + rules: + - <<: *if-ref-master + when: always + +### Patterns ### .rules:patterns:python-cache: rules: - *if-schedule @@ -404,25 +429,6 @@ - <<: *if-dev-push changes: *patterns-danger-npm -.rules:dev: - rules: - - <<: *if-trigger - - <<: *if-dev-push - -.rules:tag:release: - rules: - - <<: *if-tag-release - -.rules:ref:master-schedule: - rules: - - <<: *if-ref-master - - <<: *if-schedule - -.rules:ref:master-always: - rules: - - <<: *if-ref-master - when: always - .rules:patterns:clang_tidy: rules: - <<: *if-protected diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index c7530dcf34..8236592797 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -39,6 +39,7 @@ --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} ${PYTEST_EXTRA_FLAGS} + --app-info-filepattern \"list_job_*.txt\" .pytest_examples_dir_template: extends: .pytest_template diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 412b2562be..14d3827799 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -143,7 +143,7 @@ repos: require_serial: true additional_dependencies: - PyYAML == 5.3.1 - - idf_build_apps + - idf_build_apps~=1.0 - id: sort-build-test-rules-ymls name: sort .build-test-rules.yml files entry: tools/ci/check_build_test_rules.py sort-yaml diff --git a/conftest.py b/conftest.py index 385fe9fb26..881d01d182 100644 --- a/conftest.py +++ b/conftest.py @@ -13,6 +13,8 @@ # This is an experimental feature, and if you found any bug or have any question, please report to # https://github.com/espressif/pytest-embedded/issues +import glob +import json import logging import os import re @@ -36,11 +38,11 @@ from pytest_embedded.utils import find_by_suffix from pytest_embedded_idf.dut import IdfDut try: - from idf_ci_utils import to_list + from idf_ci_utils import IDF_PATH, to_list from idf_unity_tester import CaseTester except ImportError: sys.path.append(os.path.join(os.path.dirname(__file__), 'tools', 'ci')) - from idf_ci_utils import to_list + from idf_ci_utils import IDF_PATH, to_list from idf_unity_tester import CaseTester try: @@ -252,7 +254,7 @@ def test_case_name(request: FixtureRequest, target: str, config: str) -> str: @pytest.fixture @multi_dut_fixture -def build_dir(app_path: str, target: Optional[str], config: Optional[str]) -> str: +def build_dir(request: FixtureRequest, app_path: str, target: Optional[str], config: Optional[str]) -> str: """ Check local build dir with the following priority: @@ -261,11 +263,6 @@ def build_dir(app_path: str, target: Optional[str], config: Optional[str]) -> st 3. build_ 4. build - Args: - app_path: app path - target: target - config: config - Returns: valid build directory """ @@ -278,6 +275,25 @@ def build_dir(app_path: str, target: Optional[str], config: Optional[str]) -> st check_dirs.append(f'build_{config}') check_dirs.append('build') + idf_pytest_embedded = request.config.stash[_idf_pytest_embedded_key] + + build_dir = None + if idf_pytest_embedded.apps_list is not None: + for check_dir in check_dirs: + binary_path = os.path.join(app_path, check_dir) + if binary_path in idf_pytest_embedded.apps_list: + build_dir = check_dir + break + + if build_dir is None: + pytest.skip( + f'app path {app_path} with target {target} and config {config} is not listed in app info list files' + ) + return '' # not reachable, to fool mypy + + if build_dir: + check_dirs = [build_dir] + for check_dir in check_dirs: binary_path = os.path.join(app_path, check_dir) if os.path.isdir(binary_path): @@ -286,9 +302,8 @@ def build_dir(app_path: str, target: Optional[str], config: Optional[str]) -> st logging.warning('checking binary path: %s... missing... try another place', binary_path) - recommend_place = check_dirs[0] raise ValueError( - f'no build dir valid. Please build the binary via "idf.py -B {recommend_place} build" and run pytest again' + f'no build dir valid. Please build the binary via "idf.py -B {check_dirs[0]} build" and run pytest again' ) @@ -412,20 +427,32 @@ def dev_user(request: FixtureRequest) -> str: # Hook functions # ################## def pytest_addoption(parser: pytest.Parser) -> None: - base_group = parser.getgroup('idf') - base_group.addoption( + idf_group = parser.getgroup('idf') + idf_group.addoption( '--sdkconfig', help='sdkconfig postfix, like sdkconfig.ci.. (Default: None, which would build all found apps)', ) - base_group.addoption('--known-failure-cases-file', help='known failure cases file path') - base_group.addoption( + idf_group.addoption('--known-failure-cases-file', help='known failure cases file path') + idf_group.addoption( '--dev-user', help='user name associated with some specific device/service used during the test execution', ) - base_group.addoption( + idf_group.addoption( '--dev-passwd', help='password associated with some specific device/service used during the test execution', ) + idf_group.addoption( + '--app-info-basedir', + default=IDF_PATH, + help='app info base directory. specify this value when you\'re building under a ' + 'different IDF_PATH. (Default: $IDF_PATH)', + ) + idf_group.addoption( + '--app-info-filepattern', + help='glob pattern to specify the files that include built app info generated by ' + '`idf-build-apps --collect-app-info ...`. will not raise ValueError when binary ' + 'paths not exist in local file system if not listed recorded in the app info.', + ) _idf_pytest_embedded_key = pytest.StashKey['IdfPytestEmbedded']() @@ -446,10 +473,34 @@ def pytest_configure(config: Config) -> None: if not target: # also could specify through markexpr via "-m" target = get_target_marker_from_expr(config.getoption('markexpr') or '') + apps_list = None + app_info_basedir = config.getoption('app_info_basedir') + app_info_filepattern = config.getoption('app_info_filepattern') + if app_info_filepattern: + apps_list = [] + for file in glob.glob(os.path.join(IDF_PATH, app_info_filepattern)): + with open(file) as fr: + for line in fr.readlines(): + if not line.strip(): + continue + + # each line is a valid json + app_info = json.loads(line.strip()) + if app_info_basedir and app_info['app_dir'].startswith(app_info_basedir): + relative_app_dir = os.path.relpath(app_info['app_dir'], app_info_basedir) + apps_list.append(os.path.join(IDF_PATH, os.path.join(relative_app_dir, app_info['build_dir']))) + print('Detected app: ', apps_list[-1]) + else: + print( + f'WARNING: app_info base dir {app_info_basedir} not recognizable in {app_info["app_dir"]}, skipping...' + ) + continue + config.stash[_idf_pytest_embedded_key] = IdfPytestEmbedded( target=target, sdkconfig=config.getoption('sdkconfig'), known_failure_cases_file=config.getoption('known_failure_cases_file'), + apps_list=apps_list, ) config.pluginmanager.register(config.stash[_idf_pytest_embedded_key]) @@ -470,11 +521,13 @@ class IdfPytestEmbedded: target: str, sdkconfig: Optional[str] = None, known_failure_cases_file: Optional[str] = None, + apps_list: Optional[List[str]] = None, ): # CLI options to filter the test cases self.target = target.lower() self.sdkconfig = sdkconfig self.known_failure_patterns = self._parse_known_failure_cases_file(known_failure_cases_file) + self.apps_list = apps_list self._failed_cases: List[Tuple[str, bool, bool]] = [] # (test_case_name, is_known_failure_cases, is_xfail) @@ -599,7 +652,11 @@ class IdfPytestEmbedded: test_case_name = item.funcargs.get('test_case_name', '') if test_case_name: self._failed_cases.append( - (test_case_name, self._is_known_failure(test_case_name), report.keywords.get('xfail', False)) + ( + test_case_name, + self._is_known_failure(test_case_name), + report.keywords.get('xfail', False), + ) ) return report diff --git a/pytest.ini b/pytest.ini index ffc14c7019..c9c0c43560 100644 --- a/pytest.ini +++ b/pytest.ini @@ -5,7 +5,7 @@ python_files = pytest_*.py # ignore PytestExperimentalApiWarning for record_xml_attribute # set traceback to "short" to prevent the overwhelming tracebacks addopts = - -s + -s -vv --embedded-services esp,idf --tb short --strict-markers diff --git a/tools/ci/ci_build_apps.py b/tools/ci/ci_build_apps.py index 90961eb211..b7443395a0 100644 --- a/tools/ci/ci_build_apps.py +++ b/tools/ci/ci_build_apps.py @@ -8,10 +8,10 @@ This file is used in CI generate binary files for different kinds of apps import argparse import os import sys +import typing as t import unittest from collections import defaultdict from pathlib import Path -from typing import List, Optional, Set import yaml from idf_build_apps import LOGGER, App, build_apps, find_apps, setup_logging @@ -20,25 +20,28 @@ from idf_ci_utils import IDF_PATH, PytestApp, get_pytest_cases, get_ttfw_app_pat CI_ENV_VARS = { 'EXTRA_CFLAGS': '-Werror -Werror=deprecated-declarations -Werror=unused-variable ' - '-Werror=unused-but-set-variable -Werror=unused-function -Wstrict-prototypes', + '-Werror=unused-but-set-variable -Werror=unused-function -Wstrict-prototypes', 'EXTRA_CXXFLAGS': '-Werror -Werror=deprecated-declarations -Werror=unused-variable ' - '-Werror=unused-but-set-variable -Werror=unused-function', + '-Werror=unused-but-set-variable -Werror=unused-function', 'LDGEN_CHECK_MAPPING': '1', } def get_pytest_apps( - paths: List[str], + paths: t.List[str], target: str, - config_rules_str: List[str], + config_rules_str: t.List[str], marker_expr: str, filter_expr: str, preserve_all: bool = False, - extra_default_build_targets: Optional[List[str]] = None, -) -> List[App]: + extra_default_build_targets: t.Optional[t.List[str]] = None, + modified_components: t.Optional[t.List[str]] = None, + modified_files: t.Optional[t.List[str]] = None, + ignore_app_dependencies_filepatterns: t.Optional[t.List[str]] = None, +) -> t.List[App]: pytest_cases = get_pytest_cases(paths, target, marker_expr, filter_expr) - _paths: Set[str] = set() + _paths: t.Set[str] = set() test_related_app_configs = defaultdict(set) for case in pytest_cases: for app in case.apps: @@ -53,6 +56,9 @@ def get_pytest_apps( if not case.nightly_run: test_related_app_configs[app.path].add(app.config) + if not extra_default_build_targets: + extra_default_build_targets = [] + app_dirs = list(_paths) if not app_dirs: raise RuntimeError('No apps found') @@ -68,9 +74,12 @@ def get_pytest_apps( build_log_path='build_log.txt', size_json_path='size.json', check_warnings=True, + manifest_rootpath=IDF_PATH, manifest_files=[str(p) for p in Path(IDF_PATH).glob('**/.build-test-rules.yml')], default_build_targets=SUPPORTED_TARGETS + extra_default_build_targets, - manifest_rootpath=IDF_PATH, + modified_components=modified_components, + modified_files=modified_files, + ignore_app_dependencies_filepatterns=ignore_app_dependencies_filepatterns, ) for app in apps: @@ -85,12 +94,15 @@ def get_pytest_apps( def get_cmake_apps( - paths: List[str], + paths: t.List[str], target: str, - config_rules_str: List[str], + config_rules_str: t.List[str], preserve_all: bool = False, - extra_default_build_targets: Optional[List[str]] = None, -) -> List[App]: + extra_default_build_targets: t.Optional[t.List[str]] = None, + modified_components: t.Optional[t.List[str]] = None, + modified_files: t.Optional[t.List[str]] = None, + ignore_app_dependencies_filepatterns: t.Optional[t.List[str]] = None, +) -> t.List[App]: ttfw_app_dirs = get_ttfw_app_paths(paths, target) apps = find_apps( @@ -103,9 +115,12 @@ def get_cmake_apps( size_json_path='size.json', check_warnings=True, preserve=False, + manifest_rootpath=IDF_PATH, manifest_files=[str(p) for p in Path(IDF_PATH).glob('**/.build-test-rules.yml')], default_build_targets=SUPPORTED_TARGETS + extra_default_build_targets, - manifest_rootpath=IDF_PATH, + modified_components=modified_components, + modified_files=modified_files, + ignore_app_dependencies_filepatterns=ignore_app_dependencies_filepatterns, ) apps_for_build = [] @@ -130,7 +145,7 @@ APPS_BUILD_PER_JOB = 30 def main(args: argparse.Namespace) -> None: - extra_default_build_targets: List[str] = [] + extra_default_build_targets: t.List[str] = [] if args.default_build_test_rules: with open(args.default_build_test_rules) as fr: configs = yaml.safe_load(fr) @@ -148,6 +163,9 @@ def main(args: argparse.Namespace) -> None: args.filter_expr, args.preserve_all, extra_default_build_targets, + args.modified_components, + args.modified_files, + args.ignore_app_dependencies_filepatterns, ) else: LOGGER.info('build apps. will skip pytest apps with pytest scripts') @@ -157,6 +175,9 @@ def main(args: argparse.Namespace) -> None: args.config, args.preserve_all, extra_default_build_targets, + args.modified_components, + args.modified_files, + args.ignore_app_dependencies_filepatterns, ) LOGGER.info('Found %d apps after filtering', len(apps)) @@ -175,22 +196,28 @@ def main(args: argparse.Namespace) -> None: if abs_extra_preserve_dir == abs_app_dir or abs_extra_preserve_dir in abs_app_dir.parents: app.preserve = True - sys.exit( - build_apps( - apps, - parallel_count=args.parallel_count, - parallel_index=args.parallel_index, - dry_run=False, - build_verbose=args.build_verbose, - keep_going=True, - collect_size_info=args.collect_size_info, - collect_app_info=args.collect_app_info, - ignore_warning_strs=args.ignore_warning_str, - ignore_warning_file=args.ignore_warning_file, - copy_sdkconfig=args.copy_sdkconfig, - ) + res = build_apps( + apps, + parallel_count=args.parallel_count, + parallel_index=args.parallel_index, + dry_run=False, + build_verbose=args.build_verbose, + keep_going=True, + collect_size_info='size_info.txt', + collect_app_info='list_job_@p.txt', + ignore_warning_strs=args.ignore_warning_str, + ignore_warning_file=args.ignore_warning_file, + copy_sdkconfig=args.copy_sdkconfig, + modified_components=args.modified_components, + modified_files=args.modified_files, + ignore_app_dependencies_filepatterns=args.ignore_app_dependencies_filepatterns, ) + if isinstance(res, tuple): + sys.exit(res[0]) + else: + sys.exit(res) + if __name__ == '__main__': parser = argparse.ArgumentParser( @@ -249,8 +276,7 @@ if __name__ == '__main__': parser.add_argument( '--ignore-warning-str', nargs='+', - help='Ignore the warning string that match the specified regex in the build output. ' - 'Can be specified multiple times.', + help='Ignore the warning string that match the specified regex in the build output. space-separated list', ) parser.add_argument( '--ignore-warning-file', @@ -298,6 +324,30 @@ if __name__ == '__main__': help='by default this script would set the build flags exactly the same as the CI ones. ' 'Set this flag to use your local build flags.', ) + parser.add_argument( + '--modified-components', + nargs='*', + default=None, + help='space-separated list which specifies the modified components. app with `depends_components` set in the ' + 'corresponding manifest files would only be built if depends on any of the specified components.', + ) + parser.add_argument( + '--modified-files', + nargs='*', + default=None, + help='space-separated list which specifies the modified files. app with `depends_filepatterns` set in the ' + 'corresponding manifest files would only be built if any of the specified file pattern matches any of the ' + 'specified modified files.', + ) + parser.add_argument( + '-if', + '--ignore-app-dependencies-filepatterns', + nargs='*', + default=None, + help='space-separated list which specifies the file patterns used for ignoring checking the app dependencies. ' + 'The `depends_components` and `depends_filepatterns` set in the manifest files will be ignored when any of the ' + 'specified file patterns matches any of the modified files. Must be used together with --modified-files', + ) arguments = parser.parse_args() @@ -309,6 +359,37 @@ if __name__ == '__main__': os.environ[_k] = _v LOGGER.info(f'env var {_k} set to "{_v}"') + if os.getenv('IS_MR_PIPELINE') == '0' or os.getenv('BUILD_AND_TEST_ALL_APPS') == '1': + # if it's not MR pipeline or env var BUILD_AND_TEST_ALL_APPS=1, + # remove component dependency related arguments + if 'modified_components' in arguments: + arguments.modified_components = None + if 'modified_files' in arguments: + arguments.modified_files = None + + # file patterns to tigger full build + if 'modified_components' in arguments and not arguments.ignore_app_dependencies_filepatterns: + arguments.ignore_app_dependencies_filepatterns = [ + # tools + 'tools/cmake/**/*', + 'tools/tools.json', + # components + 'components/cxx/**/*', + 'components/esp_common/**/*', + 'components/esp_hw_support/**/*', + 'components/esp_rom/**/*', + 'components/esp_system/**/*', + 'components/esp_timer/**/*', + 'components/freertos/**/*', + 'components/hal/**/*', + 'components/heap/**/*', + 'components/log/**/*', + 'components/newlib/**/*', + 'components/riscv/**/*', + 'components/soc/**/*', + 'components/xtensa/**/*', + ] + main(arguments) diff --git a/tools/ci/python_packages/ttfw_idf/IDFAssignTest.py b/tools/ci/python_packages/ttfw_idf/IDFAssignTest.py index 3b8262f8ba..68a151e323 100644 --- a/tools/ci/python_packages/ttfw_idf/IDFAssignTest.py +++ b/tools/ci/python_packages/ttfw_idf/IDFAssignTest.py @@ -54,7 +54,7 @@ class IDFAssignTest(CIAssignTest.AssignTest): super(IDFAssignTest, self).__init__(test_case_path, ci_config_file, case_group) def format_build_log_path(self, parallel_num): - return 'list_job_{}.json'.format(parallel_num) + return 'list_job_{}.txt'.format(parallel_num) def create_artifact_index_file(self, project_id=None, pipeline_id=None): if project_id is None: From 2ad2e3cb04b5f40bf8341219428590f1a90af46d Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 23 May 2023 08:55:47 +0800 Subject: [PATCH 4/5] ci(ccs811): use manifest file instead of patterns in rules.yml --- .gitlab/ci/dependencies/dependencies.yml | 1 - .gitlab/ci/rules.yml | 38 ---------------------- .gitlab/ci/target-test.yml | 2 +- examples/peripherals/.build-test-rules.yml | 10 ++++++ 4 files changed, 11 insertions(+), 40 deletions(-) diff --git a/.gitlab/ci/dependencies/dependencies.yml b/.gitlab/ci/dependencies/dependencies.yml index 2cd4cd47c0..7b12825373 100644 --- a/.gitlab/ci/dependencies/dependencies.yml +++ b/.gitlab/ci/dependencies/dependencies.yml @@ -140,7 +140,6 @@ build:integration_test: - i154 - flash_multi - ecdsa - - ccs811 # pytest*ccs811* - nvs_encr_hmac patterns: - "{0}-{1}-{2}" diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index cb1ebb12bc..d877e7c964 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -261,13 +261,6 @@ - "components/driver/include/driver/sdmmc*.h" - "components/sdmmc/**/*" -.patterns-example_test-ccs811: &patterns-example_test-ccs811 - # components - - "examples/system/console/advanced/components/**/*" - - "components/driver/i2c/**/*" - # tests - - "examples/peripherals/i2c/i2c_tools/**/*" - # for jobs: UT_xx_SDSPI related .patterns-unit_test-sdio: &patterns-unit_test-sdio - "components/hal/sdio*.c" @@ -1170,8 +1163,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1215,8 +1206,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1259,8 +1248,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1304,8 +1291,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1348,8 +1333,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1392,8 +1375,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1436,8 +1417,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1480,8 +1459,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -1605,8 +1582,6 @@ changes: *patterns-example_test - <<: *if-dev-push changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - <<: *if-dev-push changes: *patterns-example_test-ethernet - <<: *if-dev-push @@ -2409,19 +2384,6 @@ - <<: *if-dev-push changes: *patterns-target_test-adc -.rules:test:example_test-esp32-ccs811: - rules: - - <<: *if-revert-branch - when: never - - <<: *if-protected - - <<: *if-label-build-only - when: never - - <<: *if-label-example_test - - <<: *if-label-example_test_esp32 - - <<: *if-label-target_test - - <<: *if-dev-push - changes: *patterns-example_test-ccs811 - .rules:test:example_test-esp32-ethernet: rules: - <<: *if-revert-branch diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 8236592797..d9c202ddb9 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -101,7 +101,7 @@ pytest_examples_esp32_jtag: pytest_examples_esp32_ccs811: extends: - .pytest_examples_dir_template - - .rules:test:example_test-esp32-ccs811 + - .rules:test:example_test-esp32 needs: - build_pytest_examples_esp32 tags: [ esp32, ccs811 ] diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 46fbc9ee1e..775b701505 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -1,5 +1,12 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps +.i2c_dependencies: &i2c_dependencies + depends_filepatterns: + # components + - examples/system/console/advanced/components/**/* + - components/driver/i2c/**/* + - components/driver/Kconfig + examples/peripherals/adc/continuous_read: disable: - if: SOC_ADC_DMA_SUPPORTED != 1 @@ -24,11 +31,13 @@ examples/peripherals/i2c/i2c_self_test: disable: - if: SOC_I2C_SUPPORT_SLAVE != 1 reason: the test requires both master and slave + <<: *i2c_dependencies examples/peripherals/i2c/i2c_simple: disable: - if: SOC_I2C_SUPPORT_SLAVE != 1 reason: the test requires both master and slave + <<: *i2c_dependencies examples/peripherals/i2c/i2c_tools: disable: @@ -37,6 +46,7 @@ examples/peripherals/i2c/i2c_tools: - if: IDF_TARGET != "esp32" temporary: true reason: lack of runners + <<: *i2c_dependencies examples/peripherals/i2s/i2s_adc_dac: disable: From ac7e51903ab00a1fcccc01ad0a52c885ac8bacdc Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Wed, 24 May 2023 09:18:07 +0800 Subject: [PATCH 5/5] ci: remove unused jobs and patterns --- .gitlab/ci/assign-test.yml | 30 ------------- .gitlab/ci/dependencies/dependencies.yml | 8 ---- .gitlab/ci/rules.yml | 55 ------------------------ .gitlab/ci/target-test.yml | 41 ++---------------- 4 files changed, 3 insertions(+), 131 deletions(-) diff --git a/.gitlab/ci/assign-test.yml b/.gitlab/ci/assign-test.yml index d470655708..663d084e57 100644 --- a/.gitlab/ci/assign-test.yml +++ b/.gitlab/ci/assign-test.yml @@ -14,36 +14,6 @@ script: - run_cmd python tools/ci/python_packages/ttfw_idf/IDFAssignTest.py $TEST_TYPE $TEST_DIR -c $CI_TARGET_TEST_CONFIG_FILE -o $TEST_DIR/test_configs -assign_example_test: - extends: - - .assign_test_template - - .rules:build:example_test - needs: - - job: build_examples_cmake_esp32 - artifacts: false - optional: true - - job: build_examples_cmake_esp32s2 - artifacts: false - optional: true - - job: build_examples_cmake_esp32c2 - artifacts: false - optional: true - - job: build_examples_cmake_esp32c3 - artifacts: false - optional: true - - job: build_examples_cmake_esp32c6 - artifacts: false - optional: true - - job: build_examples_cmake_esp32h2 - artifacts: false - optional: true - - job: build_examples_cmake_esp32s3 - artifacts: false - optional: true - variables: - TEST_TYPE: example_test - TEST_DIR: examples - assign_unit_test: extends: - .assign_test_template diff --git a/.gitlab/ci/dependencies/dependencies.yml b/.gitlab/ci/dependencies/dependencies.yml index 7b12825373..4aba4857bd 100644 --- a/.gitlab/ci/dependencies/dependencies.yml +++ b/.gitlab/ci/dependencies/dependencies.yml @@ -39,14 +39,6 @@ - build_system - downloadable-tools -"build:windows": - labels: - - build - - windows - patterns: - - build_system - - windows - "build:macos": labels: - build diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index d877e7c964..154e2013ed 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -166,9 +166,6 @@ - "tools/split_paths_by_spaces.py" -.patterns-windows: &patterns-windows - - "tools/windows/**/*" - .patterns-docker: &patterns-docker - "tools/docker/**/*" @@ -587,9 +584,6 @@ .if-label-unit_test_esp32s3: &if-label-unit_test_esp32s3 if: '$BOT_LABEL_UNIT_TEST_ESP32S3 || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*unit_test_esp32s3(?:,[^,\n\r]+)*$/i' -.if-label-windows: &if-label-windows - if: '$BOT_LABEL_WINDOWS || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*windows(?:,[^,\n\r]+)*$/i' - .rules:build: rules: - <<: *if-revert-branch @@ -1135,55 +1129,6 @@ - <<: *if-dev-push changes: *patterns-submodule -.rules:build:example_test: - rules: - - <<: *if-revert-branch - when: never - - <<: *if-protected - - <<: *if-example_test-ota-include_nightly_run-rule - - <<: *if-label-build - - <<: *if-label-example_test - - <<: *if-label-example_test_esp32 - - <<: *if-label-example_test_esp32c2 - - <<: *if-label-example_test_esp32c3 - - <<: *if-label-example_test_esp32c6 - - <<: *if-label-example_test_esp32h2 - - <<: *if-label-example_test_esp32s2 - - <<: *if-label-example_test_esp32s3 - - <<: *if-label-target_test - - <<: *if-dev-push - changes: *patterns-build-example_test - - <<: *if-dev-push - changes: *patterns-build_components - - <<: *if-dev-push - changes: *patterns-build_system - - <<: *if-dev-push - changes: *patterns-downloadable-tools - - <<: *if-dev-push - changes: *patterns-example_test - - <<: *if-dev-push - changes: *patterns-example_test-bt - - <<: *if-dev-push - changes: *patterns-example_test-ethernet - - <<: *if-dev-push - changes: *patterns-example_test-i154 - - <<: *if-dev-push - changes: *patterns-example_test-nvs_encr_hmac - - <<: *if-dev-push - changes: *patterns-example_test-sdio - - <<: *if-dev-push - changes: *patterns-example_test-usb - - <<: *if-dev-push - changes: *patterns-example_test-wifi - - <<: *if-dev-push - changes: *patterns-target_test-adc - - <<: *if-dev-push - changes: *patterns-target_test-ecdsa - - <<: *if-dev-push - changes: *patterns-target_test-i154 - - <<: *if-dev-push - changes: *patterns-target_test-wifi - .rules:build:example_test-esp32: rules: - <<: *if-revert-branch diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index d9c202ddb9..2499d1d257 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -1133,36 +1133,6 @@ pytest_test_apps_esp32s3_mspi_f4r4: - cd tools/ci/python_packages/tiny_test_fw/bin - run_cmd python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE -e $ENV_FILE --known_failure_cases_file $CI_PROJECT_DIR/known_failure_cases/known_failure_cases.txt -.example_test_template: - extends: .target_test_job_template - needs: - - assign_example_test - variables: - TEST_CASE_PATH: "$CI_PROJECT_DIR/examples" - CONFIG_FILE_PATH: "${CI_PROJECT_DIR}/examples/test_configs" - -.example_test_esp32_template: - extends: - - .example_test_template - - .rules:test:example_test-esp32 - -.example_test_esp32c3_template: - extends: - - .example_test_template - - .rules:test:example_test-esp32c3 - -example_test_001C: - extends: .example_test_esp32_template - tags: - - ESP32 - - Example_GENERIC - -example_test_C3_GENERIC: - extends: .example_test_esp32c3_template - tags: - - ESP32C3 - - Example_GENERIC - .unit_test_template: extends: .target_test_job_template needs: # the assign already needs all the build jobs @@ -1209,7 +1179,7 @@ example_test_C3_GENERIC: UT_001: extends: .unit_test_esp32_template - parallel: 16 + parallel: 2 tags: - ESP32_IDF - UT_T1_1 @@ -1218,7 +1188,6 @@ UT_001: UT_002: extends: .unit_test_esp32_template - parallel: 7 tags: - ESP32_IDF - UT_T1_1 @@ -1265,7 +1234,7 @@ UT_028: UT_035: extends: .unit_test_esp32s2_template - parallel: 16 + parallel: 2 tags: - ESP32S2_IDF - UT_T1_1 @@ -1280,7 +1249,6 @@ UT_S2_SDSPI: UT_C2: extends: .unit_test_esp32c2_template - parallel: 8 tags: - ESP32C2_IDF - UT_T1_1 @@ -1288,7 +1256,6 @@ UT_C2: UT_C3: extends: .unit_test_esp32c3_template - parallel: 11 tags: - ESP32C3_IDF - UT_T1_1 @@ -1303,21 +1270,19 @@ UT_C3_SDSPI: UT_C6: extends: .unit_test_esp32c6_template - parallel: 8 tags: - ESP32C6_IDF - UT_T1_1 UT_H2: extends: .unit_test_esp32h2_template - parallel: 5 tags: - ESP32H2_IDF - UT_T1_1 UT_S3: extends: .unit_test_esp32s3_template - parallel: 9 + parallel: 2 tags: - ESP32S3_IDF - UT_T1_1