From 1ace836744572002a305cc14b439e9f783ca066f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 22 Jun 2026 18:41:21 -0400 Subject: [PATCH] [espidf] Don't fail framework check on broken unrelated PATH tools (#17053) --- esphome/espidf/framework.py | 16 +++++++++------- tests/unit_tests/test_espidf_framework.py | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/esphome/espidf/framework.py b/esphome/espidf/framework.py index 6f4aeef9f0..4053898a8e 100644 --- a/esphome/espidf/framework.py +++ b/esphome/espidf/framework.py @@ -609,14 +609,16 @@ def _check_esphome_idf_framework_install( install = True if _check_stamp(env_stamp_file, stamp_info): _LOGGER.info("Checking ESP-IDF %s framework installation ...", version) - cmd = [ - get_system_python_path(), - str(idf_tools_path), - "--non-interactive", - "check", - ] - if run_command_ok(cmd, msg=f"ESP-IDF {version} check", env=env): + # Validate via the managed tool-path resolution, not ``idf_tools.py check``: + # ``check`` probes tools on the system PATH and aborts if any fail to run (e.g. a + # broken Homebrew openocd), which forced a toolchain reinstall on every build. + try: + _get_idf_tool_paths(framework_path, env) install = False + except RuntimeError as err: + _LOGGER.debug( + "ESP-IDF %s tool resolution failed, reinstalling: %s", version, err + ) # 4. Install framework tools if not installed or needs update if install: diff --git a/tests/unit_tests/test_espidf_framework.py b/tests/unit_tests/test_espidf_framework.py index d89b93f478..525cd55146 100644 --- a/tests/unit_tests/test_espidf_framework.py +++ b/tests/unit_tests/test_espidf_framework.py @@ -298,6 +298,9 @@ def espidf_mocks(setup_core: Path): patch("esphome.espidf.framework.archive_extract_all") as extract, patch("esphome.espidf.framework.create_venv") as venv, patch("esphome.espidf.framework.run_command_ok", return_value=True) as run_ok, + patch( + "esphome.espidf.framework._get_idf_tool_paths", return_value=([], {}) + ) as tool_paths, patch("esphome.espidf.framework._clone_idf_with_submodules") as clone, patch("esphome.espidf.framework._write_idf_version_txt"), patch("esphome.espidf.framework._patch_tools_json_for_linux_arm64"), @@ -308,7 +311,12 @@ def espidf_mocks(setup_core: Path): patch("esphome.espidf.framework.get_system_python_path", return_value="python"), ): yield SimpleNamespace( - download=download, extract=extract, venv=venv, run_ok=run_ok, clone=clone + download=download, + extract=extract, + venv=venv, + run_ok=run_ok, + tool_paths=tool_paths, + clone=clone, ) @@ -403,10 +411,10 @@ def test_check_esp_idf_install_stamp_mismatch_reinstalls( def test_check_esp_idf_install_check_command_failure_reinstalls( espidf_mocks: SimpleNamespace, ) -> None: - """A failing idf_tools check reinstalls tools (marker present, no re-extract).""" + """A failing tool-path resolution reinstalls tools (marker present, no re-extract).""" _mark_installed() - # idf_tools check fails -> install stays True; the later installs succeed. - espidf_mocks.run_ok.side_effect = [False, True, True, True] + # Managed tool resolution fails -> install stays True; the later installs succeed. + espidf_mocks.tool_paths.side_effect = RuntimeError("missing ESP-IDF tool") check_esp_idf_install(_IDF_VERSION, features=["fb"]) espidf_mocks.extract.assert_not_called()