From 85f33978e73a28df88955db52d8ccdb7557b5290 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 6 May 2026 06:23:35 -0500 Subject: [PATCH] [core] Skip external component update on `esphome clean` (#16268) --- esphome/__main__.py | 5 +++-- tests/unit_tests/test_main.py | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index f4a276b74c..825a502dbf 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -2301,8 +2301,9 @@ def run_esphome(argv): CORE.config_path = conf_path CORE.dashboard = args.dashboard - # For logs command, skip updating external components - skip_external = args.command == "logs" + # Commands that don't need fresh external components: logs just connects + # to the device, and clean is about to delete the build directory. + skip_external = args.command in ("logs", "clean") config = read_config( dict(args.substitution) if args.substitution else {}, skip_external_update=skip_external, diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index 0b96000a57..4ab7bb3344 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -5038,6 +5038,32 @@ def test_run_esphome_non_bundle_skips_extraction(tmp_path: Path) -> None: assert result == 2 +@pytest.mark.parametrize( + ("command", "expected_skip"), + [ + ("logs", True), + ("clean", True), + ("compile", False), + ("config", False), + ("run", False), + ("clean-mqtt", False), + ], +) +def test_run_esphome_skip_external_update_per_command( + tmp_path: Path, command: str, expected_skip: bool +) -> None: + """read_config is invoked with skip_external_update=True only for commands + that don't need fresh external components (logs, clean).""" + yaml_file = tmp_path / "device.yaml" + yaml_file.write_text("esphome:\n name: test\n") + + with patch("esphome.__main__.read_config", return_value=None) as mock_read: + run_esphome(["esphome", command, str(yaml_file)]) + + mock_read.assert_called_once() + assert mock_read.call_args.kwargs["skip_external_update"] is expected_skip + + def test_get_configured_xtal_freq_reads_sdkconfig(tmp_path: Path) -> None: """Test reading XTAL_FREQ from sdkconfig.""" CORE.name = "test-device"