mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
test_limit.py hard-capped meta/variants.yml at MAX_VARIANTS (3) with no opt-out. Allow a role whose extra matrix rounds are justified (e.g. distributing many bridged partners so each variant stays within the memory budget) to opt out via a '# nocheck: variant-limit' comment in its meta/variants.yml. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
95 lines
3.1 KiB
Python
95 lines
3.1 KiB
Python
"""Integration guard: every role's ``meta/variants.yml`` MUST declare
|
|
at most ``MAX_VARIANTS`` entries.
|
|
|
|
Rationale
|
|
---------
|
|
|
|
The matrix-deploy CLI iterates one inventory folder per variant
|
|
(see ``docs/contributing/design/variants.md``). Total deploy time grows
|
|
linearly with ``max(variant_count)`` across the primary apps, and every
|
|
extra variant doubles the surface area for cross-app/cross-round state
|
|
divergence. Capping the per-role variant count keeps the matrix
|
|
tractable: variants exist to exercise the dynamic-flag polarities,
|
|
not to enumerate every product feature.
|
|
|
|
Roles that need to express more than ``MAX_VARIANTS`` distinct
|
|
configurations SHOULD prune the matrix to the highest-value subset
|
|
(e.g. drop redundant LDAP/OIDC permutations) or move the extra
|
|
combinations into a dedicated test fixture rather than the deploy
|
|
matrix. A role that genuinely needs more rounds may opt out by adding
|
|
a ``# nocheck: variant-limit`` comment to its ``meta/variants.yml``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import unittest
|
|
from typing import TYPE_CHECKING
|
|
|
|
from utils.cache.files import read_text
|
|
from utils.cache.yaml import load_yaml_any
|
|
from utils.roles.mapping import (
|
|
ROLE_FILE_META_VARIANTS,
|
|
ROLE_TYPE_APPLICATION,
|
|
)
|
|
from utils.roles.type import get_role_types
|
|
|
|
from . import PROJECT_ROOT
|
|
|
|
if TYPE_CHECKING:
|
|
from pathlib import Path
|
|
|
|
ROLES_DIR = PROJECT_ROOT / "roles"
|
|
|
|
MAX_VARIANTS = 3
|
|
_NOCHECK_RE = re.compile(r"#\s*nocheck:\s*variant-limit\b")
|
|
|
|
|
|
def _has_nocheck(path: Path) -> bool:
|
|
try:
|
|
return bool(_NOCHECK_RE.search(read_text(str(path))))
|
|
except OSError:
|
|
return False
|
|
|
|
|
|
def _load_yaml(path: Path) -> object:
|
|
if not path.is_file():
|
|
return None
|
|
try:
|
|
return load_yaml_any(str(path), default_if_missing=None)
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
class TestVariantsLimit(unittest.TestCase):
|
|
def test_variant_count_does_not_exceed_limit(self) -> None:
|
|
offenders: list[str] = []
|
|
|
|
for role_dir in sorted(p for p in ROLES_DIR.iterdir() if p.is_dir()):
|
|
role_name = role_dir.name
|
|
if ROLE_TYPE_APPLICATION not in get_role_types(role_dir):
|
|
continue
|
|
variants_path = role_dir / ROLE_FILE_META_VARIANTS
|
|
variants = _load_yaml(variants_path)
|
|
if not isinstance(variants, list):
|
|
continue
|
|
|
|
count = len(variants)
|
|
if count > MAX_VARIANTS and not _has_nocheck(variants_path):
|
|
offenders.append(
|
|
f"{role_name}: meta/variants.yml has {count} entries, "
|
|
f"but the matrix-deploy cap is {MAX_VARIANTS}. Prune "
|
|
f"the variant list down to {MAX_VARIANTS} or fewer, or add "
|
|
f"'# nocheck: variant-limit' if the extra rounds are justified."
|
|
)
|
|
|
|
if offenders:
|
|
self.fail(
|
|
f"Roles exceed the {MAX_VARIANTS}-variant matrix-deploy cap:\n"
|
|
+ "\n".join(f" - {o}" for o in offenders)
|
|
)
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
unittest.main()
|