mirror of
https://github.com/esphome/esphome.git
synced 2025-11-19 16:25:50 +00:00
[ci] Skip memory impact analysis for release and beta branches (#11740)
This commit is contained in:
@@ -63,6 +63,7 @@ from helpers import (
|
|||||||
get_components_from_integration_fixtures,
|
get_components_from_integration_fixtures,
|
||||||
get_components_with_dependencies,
|
get_components_with_dependencies,
|
||||||
get_cpp_changed_components,
|
get_cpp_changed_components,
|
||||||
|
get_target_branch,
|
||||||
git_ls_files,
|
git_ls_files,
|
||||||
parse_test_filename,
|
parse_test_filename,
|
||||||
root_path,
|
root_path,
|
||||||
@@ -471,6 +472,20 @@ def detect_memory_impact_config(
|
|||||||
- platform: platform name for the merged build
|
- platform: platform name for the merged build
|
||||||
- use_merged_config: "true" (always use merged config)
|
- use_merged_config: "true" (always use merged config)
|
||||||
"""
|
"""
|
||||||
|
# Skip memory impact analysis for release* or beta* branches
|
||||||
|
# These branches typically contain many merged changes from dev, and building
|
||||||
|
# all components at once would produce nonsensical memory impact results.
|
||||||
|
# Memory impact analysis is most useful for focused PRs targeting dev.
|
||||||
|
target_branch = get_target_branch()
|
||||||
|
if target_branch and (
|
||||||
|
target_branch.startswith("release") or target_branch.startswith("beta")
|
||||||
|
):
|
||||||
|
print(
|
||||||
|
f"Memory impact: Skipping analysis for target branch {target_branch} "
|
||||||
|
f"(would try to build all components at once, giving nonsensical results)",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
return {"should_run": "false"}
|
||||||
|
|
||||||
# Get actually changed files (not dependencies)
|
# Get actually changed files (not dependencies)
|
||||||
files = changed_files(branch)
|
files = changed_files(branch)
|
||||||
|
|||||||
@@ -196,6 +196,20 @@ def splitlines_no_ends(string: str) -> list[str]:
|
|||||||
return [s.strip() for s in string.splitlines()]
|
return [s.strip() for s in string.splitlines()]
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def _get_github_event_data() -> dict | None:
|
||||||
|
"""Read and parse GitHub event file (cached).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Parsed event data dictionary, or None if not available
|
||||||
|
"""
|
||||||
|
github_event_path = os.environ.get("GITHUB_EVENT_PATH")
|
||||||
|
if github_event_path and os.path.exists(github_event_path):
|
||||||
|
with open(github_event_path) as f:
|
||||||
|
return json.load(f)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_pr_number_from_github_env() -> str | None:
|
def _get_pr_number_from_github_env() -> str | None:
|
||||||
"""Extract PR number from GitHub environment variables.
|
"""Extract PR number from GitHub environment variables.
|
||||||
|
|
||||||
@@ -208,10 +222,7 @@ def _get_pr_number_from_github_env() -> str | None:
|
|||||||
return github_ref.split("/pull/")[1].split("/")[0]
|
return github_ref.split("/pull/")[1].split("/")[0]
|
||||||
|
|
||||||
# Fallback to GitHub event file
|
# Fallback to GitHub event file
|
||||||
github_event_path = os.environ.get("GITHUB_EVENT_PATH")
|
if event_data := _get_github_event_data():
|
||||||
if github_event_path and os.path.exists(github_event_path):
|
|
||||||
with open(github_event_path) as f:
|
|
||||||
event_data = json.load(f)
|
|
||||||
pr_data = event_data.get("pull_request", {})
|
pr_data = event_data.get("pull_request", {})
|
||||||
if pr_number := pr_data.get("number"):
|
if pr_number := pr_data.get("number"):
|
||||||
return str(pr_number)
|
return str(pr_number)
|
||||||
@@ -219,6 +230,26 @@ def _get_pr_number_from_github_env() -> str | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_target_branch() -> str | None:
|
||||||
|
"""Get the target branch from GitHub environment variables.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Target branch name (e.g., "dev", "release", "beta"), or None if not in PR context
|
||||||
|
"""
|
||||||
|
# First try GITHUB_BASE_REF (set for pull_request events)
|
||||||
|
if base_ref := os.environ.get("GITHUB_BASE_REF"):
|
||||||
|
return base_ref
|
||||||
|
|
||||||
|
# Fallback to GitHub event file
|
||||||
|
if event_data := _get_github_event_data():
|
||||||
|
pr_data = event_data.get("pull_request", {})
|
||||||
|
base_data = pr_data.get("base", {})
|
||||||
|
if ref := base_data.get("ref"):
|
||||||
|
return ref
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
def _get_changed_files_github_actions() -> list[str] | None:
|
def _get_changed_files_github_actions() -> list[str] | None:
|
||||||
"""Get changed files in GitHub Actions environment.
|
"""Get changed files in GitHub Actions environment.
|
||||||
|
|||||||
@@ -1240,3 +1240,73 @@ def test_detect_memory_impact_config_filters_incompatible_esp8266_on_esp32(
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result["use_merged_config"] == "true"
|
assert result["use_merged_config"] == "true"
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_memory_impact_config_skips_release_branch(tmp_path: Path) -> None:
|
||||||
|
"""Test that memory impact analysis is skipped for release* branches."""
|
||||||
|
# Create test directory structure with components that have tests
|
||||||
|
tests_dir = tmp_path / "tests" / "components"
|
||||||
|
wifi_dir = tests_dir / "wifi"
|
||||||
|
wifi_dir.mkdir(parents=True)
|
||||||
|
(wifi_dir / "test.esp32-idf.yaml").write_text("test: wifi")
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch.object(determine_jobs, "root_path", str(tmp_path)),
|
||||||
|
patch.object(helpers, "root_path", str(tmp_path)),
|
||||||
|
patch.object(determine_jobs, "changed_files") as mock_changed_files,
|
||||||
|
patch.object(determine_jobs, "get_target_branch", return_value="release"),
|
||||||
|
):
|
||||||
|
mock_changed_files.return_value = ["esphome/components/wifi/wifi.cpp"]
|
||||||
|
determine_jobs._component_has_tests.cache_clear()
|
||||||
|
|
||||||
|
result = determine_jobs.detect_memory_impact_config()
|
||||||
|
|
||||||
|
# Memory impact should be skipped for release branch
|
||||||
|
assert result["should_run"] == "false"
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_memory_impact_config_skips_beta_branch(tmp_path: Path) -> None:
|
||||||
|
"""Test that memory impact analysis is skipped for beta* branches."""
|
||||||
|
# Create test directory structure with components that have tests
|
||||||
|
tests_dir = tmp_path / "tests" / "components"
|
||||||
|
wifi_dir = tests_dir / "wifi"
|
||||||
|
wifi_dir.mkdir(parents=True)
|
||||||
|
(wifi_dir / "test.esp32-idf.yaml").write_text("test: wifi")
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch.object(determine_jobs, "root_path", str(tmp_path)),
|
||||||
|
patch.object(helpers, "root_path", str(tmp_path)),
|
||||||
|
patch.object(determine_jobs, "changed_files") as mock_changed_files,
|
||||||
|
patch.object(determine_jobs, "get_target_branch", return_value="beta"),
|
||||||
|
):
|
||||||
|
mock_changed_files.return_value = ["esphome/components/wifi/wifi.cpp"]
|
||||||
|
determine_jobs._component_has_tests.cache_clear()
|
||||||
|
|
||||||
|
result = determine_jobs.detect_memory_impact_config()
|
||||||
|
|
||||||
|
# Memory impact should be skipped for beta branch
|
||||||
|
assert result["should_run"] == "false"
|
||||||
|
|
||||||
|
|
||||||
|
def test_detect_memory_impact_config_runs_for_dev_branch(tmp_path: Path) -> None:
|
||||||
|
"""Test that memory impact analysis runs for dev branch."""
|
||||||
|
# Create test directory structure with components that have tests
|
||||||
|
tests_dir = tmp_path / "tests" / "components"
|
||||||
|
wifi_dir = tests_dir / "wifi"
|
||||||
|
wifi_dir.mkdir(parents=True)
|
||||||
|
(wifi_dir / "test.esp32-idf.yaml").write_text("test: wifi")
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch.object(determine_jobs, "root_path", str(tmp_path)),
|
||||||
|
patch.object(helpers, "root_path", str(tmp_path)),
|
||||||
|
patch.object(determine_jobs, "changed_files") as mock_changed_files,
|
||||||
|
patch.object(determine_jobs, "get_target_branch", return_value="dev"),
|
||||||
|
):
|
||||||
|
mock_changed_files.return_value = ["esphome/components/wifi/wifi.cpp"]
|
||||||
|
determine_jobs._component_has_tests.cache_clear()
|
||||||
|
|
||||||
|
result = determine_jobs.detect_memory_impact_config()
|
||||||
|
|
||||||
|
# Memory impact should run for dev branch
|
||||||
|
assert result["should_run"] == "true"
|
||||||
|
assert result["components"] == ["wifi"]
|
||||||
|
|||||||
@@ -31,6 +31,13 @@ print_file_list = helpers.print_file_list
|
|||||||
get_all_dependencies = helpers.get_all_dependencies
|
get_all_dependencies = helpers.get_all_dependencies
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def clear_helpers_cache() -> None:
|
||||||
|
"""Clear cached functions before each test."""
|
||||||
|
helpers._get_github_event_data.cache_clear()
|
||||||
|
helpers._get_changed_files_github_actions.cache_clear()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("github_ref", "expected_pr_number"),
|
("github_ref", "expected_pr_number"),
|
||||||
[
|
[
|
||||||
|
|||||||
Reference in New Issue
Block a user