1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-19 03:32:20 +01:00

[core] Fix clean build files to properly clear PlatformIO cache

This commit is contained in:
J. Nick Koston
2025-09-16 10:49:05 -05:00
parent cbaf8d309b
commit bc73346f1f
4 changed files with 62 additions and 0 deletions

View File

@@ -694,6 +694,15 @@ class EsphomeCore:
def relative_piolibdeps_path(self, *path): def relative_piolibdeps_path(self, *path):
return self.relative_build_path(".piolibdeps", *path) return self.relative_build_path(".piolibdeps", *path)
@property
def platformio_cache_dir(self) -> str:
"""Get the PlatformIO cache directory path."""
# Check if running in Docker/HA addon with custom cache dir
if cache_dir := os.environ.get("PLATFORMIO_CACHE_DIR"):
return cache_dir
# Default PlatformIO cache location
return os.path.expanduser("~/.platformio/.cache")
@property @property
def firmware_bin(self): def firmware_bin(self):
if self.is_libretiny: if self.is_libretiny:

View File

@@ -315,6 +315,13 @@ 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
cache_dir = CORE.platformio_cache_dir
if 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

@@ -660,3 +660,37 @@ class TestEsphomeCore:
os.environ.pop("ESPHOME_IS_HA_ADDON", None) os.environ.pop("ESPHOME_IS_HA_ADDON", None)
os.environ.pop("ESPHOME_DATA_DIR", None) os.environ.pop("ESPHOME_DATA_DIR", None)
assert target.data_dir == expected_default assert target.data_dir == expected_default
def test_platformio_cache_dir_with_env_var(self):
"""Test platformio_cache_dir when PLATFORMIO_CACHE_DIR env var is set."""
target = core.EsphomeCore()
test_cache_dir = "/custom/cache/dir"
with patch.dict(os.environ, {"PLATFORMIO_CACHE_DIR": test_cache_dir}):
assert target.platformio_cache_dir == test_cache_dir
def test_platformio_cache_dir_without_env_var(self):
"""Test platformio_cache_dir defaults to ~/.platformio/.cache."""
target = core.EsphomeCore()
with patch.dict(os.environ, {}, clear=True):
# Ensure env var is not set
os.environ.pop("PLATFORMIO_CACHE_DIR", None)
expected = os.path.expanduser("~/.platformio/.cache")
assert target.platformio_cache_dir == expected
def test_platformio_cache_dir_empty_env_var(self):
"""Test platformio_cache_dir with empty env var falls back to default."""
target = core.EsphomeCore()
with patch.dict(os.environ, {"PLATFORMIO_CACHE_DIR": ""}):
expected = os.path.expanduser("~/.platformio/.cache")
assert target.platformio_cache_dir == expected
def test_platformio_cache_dir_docker_addon_path(self):
"""Test platformio_cache_dir in Docker/HA addon environment."""
target = core.EsphomeCore()
addon_cache = "/data/cache/platformio"
with patch.dict(os.environ, {"PLATFORMIO_CACHE_DIR": addon_cache}):
assert target.platformio_cache_dir == addon_cache

View File

@@ -349,15 +349,25 @@ 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)
mock_core.relative_build_path.return_value = str(dependencies_lock) mock_core.relative_build_path.return_value = str(dependencies_lock)
mock_core.platformio_cache_dir = str(platformio_cache_dir)
# Verify all exist before # Verify all exist before
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 # Call the function
with caplog.at_level("INFO"): with caplog.at_level("INFO"):
@@ -367,12 +377,14 @@ def test_clean_build(
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")