From 588ac5f4fb8cb2125ab6f637ba246783c9aadc81 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 16 Apr 2024 15:31:45 +0200 Subject: [PATCH 1/4] ci: ensure macos selected the correct python installed by pyenv --- .gitlab/ci/build.yml | 4 +++- .gitlab/ci/common.yml | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 50598e9482..7fd511cda6 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -206,11 +206,13 @@ pytest_build_system_macos: extends: - .test_build_system_template - .before_script:build:macos + - .after_script:build:macos:ccache:upload-when-fail - .rules:build:macos tags: - macos_shell parallel: 3 - allow_failure: true # IDFCI-2107 + variables: + PYENV_VERSION: "3.8" build_docker: extends: diff --git a/.gitlab/ci/common.yml b/.gitlab/ci/common.yml index 6d11621af0..7ea9a87dd5 100644 --- a/.gitlab/ci/common.yml +++ b/.gitlab/ci/common.yml @@ -52,7 +52,6 @@ variables: IDF_PATH: "$CI_PROJECT_DIR" V: "0" CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py" - PYTHON_VER: 3.8.17 # Docker images ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.3:1" @@ -208,6 +207,10 @@ variables: .before_script:build:macos: before_script: + # macos is running shell executor, which means it would use + # the system installed /usr/local/bin/python3 by default. + # Ensure pyenv and PYENV_VERSION installed + - eval "$(pyenv init -)" - *common-before_scripts # On macOS, these tools need to be installed - export IDF_TOOLS_PATH="${HOME}/.espressif_runner_${CI_RUNNER_ID}_${CI_CONCURRENT_ID}" @@ -216,6 +219,15 @@ variables: - *setup_tools_and_idf_python_venv - fetch_submodules +.after_script:build:macos:ccache:upload-when-fail: + after_script: + # macos is running shell executor, which means it would use + # the system installed /usr/local/bin/python3 by default. + # Ensure pyenv and PYENV_VERSION installed + - eval "$(pyenv init -)" + - *show_ccache_statistics + - *upload_failed_job_log_artifacts + .before_script:build: before_script: - *common-before_scripts From b5607cf43cd998161a82196b6d449079c07a1d78 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 16 Apr 2024 15:01:02 +0200 Subject: [PATCH 2/4] ci: disable ccache on macos build system test --- .gitlab/ci/build.yml | 3 ++- .gitlab/ci/common.yml | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 7fd511cda6..1bea0af01d 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -206,13 +206,14 @@ pytest_build_system_macos: extends: - .test_build_system_template - .before_script:build:macos - - .after_script:build:macos:ccache:upload-when-fail + - .after_script:build:macos:upload-when-fail - .rules:build:macos tags: - macos_shell parallel: 3 variables: PYENV_VERSION: "3.8" + CI_CCACHE_DISABLE: "1" # ccache: error: Read-only file system build_docker: extends: diff --git a/.gitlab/ci/common.yml b/.gitlab/ci/common.yml index 7ea9a87dd5..b811b9c8e4 100644 --- a/.gitlab/ci/common.yml +++ b/.gitlab/ci/common.yml @@ -219,13 +219,12 @@ variables: - *setup_tools_and_idf_python_venv - fetch_submodules -.after_script:build:macos:ccache:upload-when-fail: +.after_script:build:macos:upload-when-fail: after_script: # macos is running shell executor, which means it would use # the system installed /usr/local/bin/python3 by default. # Ensure pyenv and PYENV_VERSION installed - eval "$(pyenv init -)" - - *show_ccache_statistics - *upload_failed_job_log_artifacts .before_script:build: From a4f691b88a1e43dce8812b82dd479b2f62f4aaad Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 16 Apr 2024 14:11:31 +0200 Subject: [PATCH 3/4] ci: always cleanup idf copy in ci --- .gitlab/ci/build.yml | 8 ++++++-- tools/test_build_system/conftest.py | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 1bea0af01d..0844f420b2 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -194,8 +194,12 @@ build_clang_test_apps_esp32c6: - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh - cd ${IDF_PATH}/tools/test_build_system - python ${IDF_PATH}/tools/ci/get_known_failure_cases_file.py - - pytest --parallel-count ${CI_NODE_TOTAL:-1} --parallel-index ${CI_NODE_INDEX:-1} - --work-dir ${CI_PROJECT_DIR}/test_build_system --junitxml=${CI_PROJECT_DIR}/XUNIT_RESULT.xml + - pytest + --cleanup-idf-copy + --parallel-count ${CI_NODE_TOTAL:-1} + --parallel-index ${CI_NODE_INDEX:-1} + --work-dir ${CI_PROJECT_DIR}/test_build_system + --junitxml ${CI_PROJECT_DIR}/XUNIT_RESULT.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} pytest_build_system: diff --git a/tools/test_build_system/conftest.py b/tools/test_build_system/conftest.py index 16fe7cd75a..fbfc97c053 100644 --- a/tools/test_build_system/conftest.py +++ b/tools/test_build_system/conftest.py @@ -31,7 +31,7 @@ def pytest_runtest_makereport(item: typing.Any, call: typing.Any) -> typing.Gene def should_clean_test_dir(request: FixtureRequest) -> bool: # Only remove the test directory if the test has passed - return getattr(request.node, 'passed', False) + return getattr(request.node, 'passed', False) or request.config.getoption('cleanup_idf_copy', False) def pytest_addoption(parser: pytest.Parser) -> None: @@ -40,6 +40,10 @@ def pytest_addoption(parser: pytest.Parser) -> None: help='Directory for temporary files. If not specified, an OS-specific ' 'temporary directory will be used.' ) + parser.addoption( + '--cleanup-idf-copy', action='store_true', + help='Always clean up the IDF copy after the test. By default, the copy is cleaned up only if the test passes.' + ) @pytest.fixture(scope='session') From 2cde75b53101c07d54c0be15cc7a02f379391d31 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 16 Apr 2024 14:13:40 +0200 Subject: [PATCH 4/4] ci: improve pytest build system tests - remove temp dirs - remove idf-component-manager unit test --- tools/test_build_system/test_build.py | 35 ++++++++++++++++++-------- tools/test_build_system/test_common.py | 25 ++++++++---------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/tools/test_build_system/test_build.py b/tools/test_build_system/test_build.py index 5529aab277..bcc2d73527 100644 --- a/tools/test_build_system/test_build.py +++ b/tools/test_build_system/test_build.py @@ -1,17 +1,25 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import logging import os +import shutil import stat import sys import textwrap from pathlib import Path -from typing import List, Union +from typing import List +from typing import Union import pytest -from test_build_system_helpers import (APP_BINS, BOOTLOADER_BINS, PARTITION_BIN, IdfPyFunc, append_to_file, - file_contains, get_idf_build_env, replace_in_file, run_cmake_and_build) +from test_build_system_helpers import APP_BINS +from test_build_system_helpers import append_to_file +from test_build_system_helpers import BOOTLOADER_BINS +from test_build_system_helpers import file_contains +from test_build_system_helpers import get_idf_build_env +from test_build_system_helpers import IdfPyFunc +from test_build_system_helpers import PARTITION_BIN +from test_build_system_helpers import replace_in_file +from test_build_system_helpers import run_cmake_and_build def assert_built(paths: Union[List[str], List[Path]]) -> None: @@ -22,11 +30,16 @@ def assert_built(paths: Union[List[str], List[Path]]) -> None: def test_build_alternative_directories(idf_py: IdfPyFunc, func_work_dir: Path, test_app_copy: Path) -> None: logging.info('Moving BUILD_DIR_BASE out of tree') alt_build_dir = func_work_dir / 'alt_build' - idf_py('-B', str(alt_build_dir), 'build') - assert os.listdir(alt_build_dir) != [], 'No files found in new build directory!' - default_build_dir = test_app_copy / 'build' - if default_build_dir.exists(): - assert os.listdir(default_build_dir) == [], f'Some files were incorrectly put into the default build directory: {default_build_dir}' + try: + idf_py('-B', str(alt_build_dir), 'build') + assert os.listdir(alt_build_dir) != [], 'No files found in new build directory!' + default_build_dir = test_app_copy / 'build' + if default_build_dir.exists(): + assert os.listdir(default_build_dir) == [], f'Some files were incorrectly put into the default build directory: {default_build_dir}' + except Exception: + raise + else: + shutil.rmtree(alt_build_dir) logging.info('BUILD_DIR_BASE inside default build directory') build_subdir_inside_build_dir = default_build_dir / 'subdirectory' @@ -120,7 +133,7 @@ def test_build_compiler_flag_in_source_file(idf_py: IdfPyFunc, test_app_copy: Pa @pytest.mark.usefixtures('test_app_copy') def test_build_compiler_flags_no_overwriting(idf_py: IdfPyFunc) -> None: logging.info('Compiler flags cannot be overwritten') - # If the compiler flags are overriden, the following build command will + # If the compiler flags are overridden, the following build command will # cause issues at link time. idf_py('build', '-DCMAKE_C_FLAGS=', '-DCMAKE_CXX_FLAGS=') diff --git a/tools/test_build_system/test_common.py b/tools/test_build_system/test_common.py index 515acce6f9..affc60bdf8 100644 --- a/tools/test_build_system/test_common.py +++ b/tools/test_build_system/test_common.py @@ -46,18 +46,6 @@ def test_compile_commands_json_updated_by_reconfigure(idf_py: IdfPyFunc) -> None snapshot_3.assert_different(snapshot_2) -@pytest.mark.usefixtures('test_app_copy') -def test_of_test_app_copy(idf_py: IdfPyFunc) -> None: - p = Path('main/idf_component.yml') - p.write_text('syntax_error\n') - try: - with (pytest.raises(subprocess.CalledProcessError)) as exc_info: - idf_py('reconfigure') - assert 'ERROR: Unknown format of the manifest file:' in exc_info.value.stderr - finally: - p.unlink() - - @pytest.mark.usefixtures('test_app_copy') def test_hints_no_color_output_when_noninteractive(idf_py: IdfPyFunc) -> None: """Check that idf.py hints don't include color escape codes in non-interactive builds""" @@ -252,11 +240,20 @@ def test_create_project_with_idf_readonly(idf_copy: Path) -> None: for name in files: path = os.path.join(root, name) if '/bin/' in path: - continue # skip excutables + continue # skip executables os.chmod(os.path.join(root, name), 0o444) # readonly logging.info('Check that command for creating new project will success if the IDF itself is readonly.') change_to_readonly(idf_copy) - run_idf_py('create-project', '--path', str(idf_copy / 'example_proj'), 'temp_test_project') + try: + run_idf_py('create-project', '--path', str(idf_copy / 'example_proj'), 'temp_test_project') + except Exception: + raise + else: + def del_rw(function, path, excinfo): # type: ignore + os.chmod(path, stat.S_IWRITE) + os.remove(path) + + shutil.rmtree(idf_copy, onerror=del_rw) @pytest.mark.usefixtures('test_app_copy')