from __future__ import annotations import json from pathlib import Path from scripts.release_headroom_preflight import ( DEFAULT_API_SURGE_CPU_M, DEFAULT_API_SURGE_MEMORY, DEFAULT_MCP_SURGE_CPU_M, DEFAULT_MIGRATE_CPU_M, DEFAULT_VALUES_FILES, evaluate, load_values, main, pod_effective_requests, release_from_values, ) FIXTURES = Path(__file__).parent / "fixtures" / "release_headroom" HISTORICAL_100M = {"api_surge_cpu_m": 100} def _load(name: str) -> dict: return json.loads((FIXTURES / name).read_text()) def test_revision_61_65m_refuses_api_surge() -> None: report = evaluate(_load("rev61-65m.json")) assert report["ok"] is False assert report["remaining_cpu_m"] == 65 assert any("65m remaining" in r or "needs 100m" in r for r in report["reasons"]) assert "not a kube-scheduler guarantee" in " ".join(report["notes"]).lower() or any( "guarantee" in n.lower() for n in report["notes"] ) def test_revision_63_105m_is_narrowly_sufficient() -> None: report = evaluate(_load("rev63-105m.json"), HISTORICAL_100M) assert report["ok"] is True assert report["remaining_cpu_m"] == 105 assert report["reasons"] == [] assert any("105m" in n or "Not factory" in n for n in report["notes"]) def test_unrelated_pending_demand_refuses_105m() -> None: report = evaluate(_load("rev63-105m-concurrent-pending.json"), HISTORICAL_100M) assert report["ok"] is False assert any("unrelated pending" in r for r in report["reasons"]) def test_stale_observation_refuses() -> None: observation = _load("rev63-105m.json") observation["freshness_seconds"] = 3600 report = evaluate(observation, HISTORICAL_100M) assert report["ok"] is False assert any("old" in r for r in report["reasons"]) def test_non_atomic_refuses() -> None: report = evaluate(_load("rev63-105m.json"), {**HISTORICAL_100M, "atomic": False}) assert report["ok"] is False assert any("atomic" in r for r in report["reasons"]) def test_init_overhead_uses_max_not_sum() -> None: pod = { "spec": { "initContainers": [{"resources": {"requests": {"cpu": "80m", "memory": "64Mi"}}}], "containers": [{"resources": {"requests": {"cpu": "100m", "memory": "512Mi"}}}], } } cpu, _mem = pod_effective_requests(pod) assert cpu == 100 def test_cli_fixture_exit_codes() -> None: historical = str(FIXTURES / "historical-100m-release.json") assert main(["--fixture", str(FIXTURES / "rev63-105m.json"), "--release", historical]) == 0 assert main(["--fixture", str(FIXTURES / "rev61-65m.json"), "--release", historical]) == 1 # Default surge now derives from the shipped values (390m): 105m refuses. assert main(["--fixture", str(FIXTURES / "rev63-105m.json")]) == 1 # STATE-WP-0099: the surge follows the API request the release deploys. def test_shipped_values_drive_surge_and_match_fallbacks() -> None: release = release_from_values(load_values(DEFAULT_VALUES_FILES)) assert release["api_surge_cpu_m"] == 390 assert release["api_surge_cpu_m"] == DEFAULT_API_SURGE_CPU_M assert release["api_surge_memory_bytes"] == DEFAULT_API_SURGE_MEMORY assert release["mcp_surge_cpu_m"] == DEFAULT_MCP_SURGE_CPU_M assert release["migrate_cpu_m"] == DEFAULT_MIGRATE_CPU_M def test_values_override_order_and_disabled_sections() -> None: chart = {"resources": {"requests": {"cpu": "250m", "memory": "512Mi"}}, "mcp": {"enabled": False, "resources": {"requests": {"cpu": "50m"}}}, "migrations": {"enabled": True, "resources": {"requests": {"cpu": "50m"}}}} override = {"resources": {"requests": {"cpu": "0.39"}}, "migrations": {"enabled": False}} from scripts.release_headroom_preflight import _deep_merge release = release_from_values(_deep_merge(chart, override)) assert release["api_surge_cpu_m"] == 390 assert release["api_surge_memory_bytes"] == 512 * 1024**2 assert release["mcp_surge_cpu_m"] == 0 assert release["migrate_cpu_m"] == 0 def test_today_395m_fits_390m_surge_narrowly() -> None: report = evaluate(_load("2026-10-21-395m-live250.json")) assert report["ok"] is True assert report["api_surge_cpu_m"] == 390 assert report["remaining_after_rollout_cpu_m"] == 255 notes = " ".join(report["notes"]) assert "250m -> 390m" in notes assert "only 5m above" in notes assert "next release will be refused" in notes def test_after_knative_reduction_fits_with_margin() -> None: report = evaluate(_load("2026-10-21-555m-after-knative.json")) assert report["ok"] is True assert report["remaining_after_rollout_cpu_m"] == 415 assert "next release will be refused" not in " ".join(report["notes"]) def test_forge_increase_before_state_hub_refuses() -> None: report = evaluate(_load("2026-10-21-320m-forge-first.json")) assert report["ok"] is False assert any("needs 390m" in r for r in report["reasons"]) def test_after_full_wave1_routine_release_refuses() -> None: report = evaluate(_load("2026-10-21-110m-after-wave1.json")) assert report["ok"] is False assert report["remaining_cpu_m"] == 110 assert any("needs 390m" in r for r in report["reasons"])