1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-18 11:12:20 +01:00

[core] Fix clean build files to properly clear PlatformIO cache (#10754)

This commit is contained in:
J. Nick Koston
2025-09-16 15:09:35 -05:00
committed by GitHub
parent 22989592f0
commit 27fa18dcec
2 changed files with 113 additions and 3 deletions

View File

@@ -315,6 +315,19 @@ def clean_build():
_LOGGER.info("Deleting %s", dependencies_lock) _LOGGER.info("Deleting %s", dependencies_lock)
os.remove(dependencies_lock) os.remove(dependencies_lock)
# Clean PlatformIO cache to resolve CMake compiler detection issues
# This helps when toolchain paths change or get corrupted
try:
from platformio.project.helpers import get_project_cache_dir
except ImportError:
# PlatformIO is not available, skip cache cleaning
pass
else:
cache_dir = get_project_cache_dir()
if cache_dir and cache_dir.strip() and os.path.isdir(cache_dir):
_LOGGER.info("Deleting PlatformIO cache %s", cache_dir)
shutil.rmtree(cache_dir)
GITIGNORE_CONTENT = """# Gitignore settings for ESPHome GITIGNORE_CONTENT = """# Gitignore settings for ESPHome
# This is an example and may include too much for your use-case. # This is an example and may include too much for your use-case.

View File

@@ -349,6 +349,14 @@ def test_clean_build(
dependencies_lock = tmp_path / "dependencies.lock" dependencies_lock = tmp_path / "dependencies.lock"
dependencies_lock.write_text("lock file") dependencies_lock.write_text("lock file")
# Create PlatformIO cache directory
platformio_cache_dir = tmp_path / ".platformio" / ".cache"
platformio_cache_dir.mkdir(parents=True)
(platformio_cache_dir / "downloads").mkdir()
(platformio_cache_dir / "http").mkdir()
(platformio_cache_dir / "tmp").mkdir()
(platformio_cache_dir / "downloads" / "package.tar.gz").write_text("package")
# Setup mocks # Setup mocks
mock_core.relative_pioenvs_path.return_value = str(pioenvs_dir) mock_core.relative_pioenvs_path.return_value = str(pioenvs_dir)
mock_core.relative_piolibdeps_path.return_value = str(piolibdeps_dir) mock_core.relative_piolibdeps_path.return_value = str(piolibdeps_dir)
@@ -358,21 +366,30 @@ def test_clean_build(
assert pioenvs_dir.exists() assert pioenvs_dir.exists()
assert piolibdeps_dir.exists() assert piolibdeps_dir.exists()
assert dependencies_lock.exists() assert dependencies_lock.exists()
assert platformio_cache_dir.exists()
# Call the function # Mock PlatformIO's get_project_cache_dir
with caplog.at_level("INFO"): with patch(
clean_build() "platformio.project.helpers.get_project_cache_dir"
) as mock_get_cache_dir:
mock_get_cache_dir.return_value = str(platformio_cache_dir)
# Call the function
with caplog.at_level("INFO"):
clean_build()
# Verify all were removed # Verify all were removed
assert not pioenvs_dir.exists() assert not pioenvs_dir.exists()
assert not piolibdeps_dir.exists() assert not piolibdeps_dir.exists()
assert not dependencies_lock.exists() assert not dependencies_lock.exists()
assert not platformio_cache_dir.exists()
# Verify logging # Verify logging
assert "Deleting" in caplog.text assert "Deleting" in caplog.text
assert ".pioenvs" in caplog.text assert ".pioenvs" in caplog.text
assert ".piolibdeps" in caplog.text assert ".piolibdeps" in caplog.text
assert "dependencies.lock" in caplog.text assert "dependencies.lock" in caplog.text
assert "PlatformIO cache" in caplog.text
@patch("esphome.writer.CORE") @patch("esphome.writer.CORE")
@@ -446,6 +463,86 @@ def test_clean_build_nothing_exists(
assert not dependencies_lock.exists() assert not dependencies_lock.exists()
@patch("esphome.writer.CORE")
def test_clean_build_platformio_not_available(
mock_core: MagicMock,
tmp_path: Path,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test clean_build when PlatformIO is not available."""
# Create directory structure and files
pioenvs_dir = tmp_path / ".pioenvs"
pioenvs_dir.mkdir()
piolibdeps_dir = tmp_path / ".piolibdeps"
piolibdeps_dir.mkdir()
dependencies_lock = tmp_path / "dependencies.lock"
dependencies_lock.write_text("lock file")
# Setup mocks
mock_core.relative_pioenvs_path.return_value = str(pioenvs_dir)
mock_core.relative_piolibdeps_path.return_value = str(piolibdeps_dir)
mock_core.relative_build_path.return_value = str(dependencies_lock)
# Verify all exist before
assert pioenvs_dir.exists()
assert piolibdeps_dir.exists()
assert dependencies_lock.exists()
# Mock import error for platformio
with (
patch.dict("sys.modules", {"platformio.project.helpers": None}),
caplog.at_level("INFO"),
):
# Call the function
clean_build()
# Verify standard paths were removed but no cache cleaning attempted
assert not pioenvs_dir.exists()
assert not piolibdeps_dir.exists()
assert not dependencies_lock.exists()
# Verify no cache logging
assert "PlatformIO cache" not in caplog.text
@patch("esphome.writer.CORE")
def test_clean_build_empty_cache_dir(
mock_core: MagicMock,
tmp_path: Path,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test clean_build when get_project_cache_dir returns empty/whitespace."""
# Create directory structure and files
pioenvs_dir = tmp_path / ".pioenvs"
pioenvs_dir.mkdir()
# Setup mocks
mock_core.relative_pioenvs_path.return_value = str(pioenvs_dir)
mock_core.relative_piolibdeps_path.return_value = str(tmp_path / ".piolibdeps")
mock_core.relative_build_path.return_value = str(tmp_path / "dependencies.lock")
# Verify pioenvs exists before
assert pioenvs_dir.exists()
# Mock PlatformIO's get_project_cache_dir to return whitespace
with patch(
"platformio.project.helpers.get_project_cache_dir"
) as mock_get_cache_dir:
mock_get_cache_dir.return_value = " " # Whitespace only
# Call the function
with caplog.at_level("INFO"):
clean_build()
# Verify pioenvs was removed
assert not pioenvs_dir.exists()
# Verify no cache cleaning was attempted due to empty string
assert "PlatformIO cache" not in caplog.text
@patch("esphome.writer.CORE") @patch("esphome.writer.CORE")
def test_write_gitignore_creates_new_file( def test_write_gitignore_creates_new_file(
mock_core: MagicMock, mock_core: MagicMock,