Files
computer-playbook/cli/meta/roles/lifecycle/__main__.py
kevinveenbirkenbachandClaude Opus 5 5137465c6f style: delete every comment the comments-valid policy rejects
3529 invalid comments in 528 files, grandfathered in while the linter
only saw the working-tree diff. Removal ran through the linter's own
collectors, so detection and deletion cannot drift: a comment whose
opener line is blank before it and whose closer line is blank after it
loses all its lines, anything else loses only the comment region, and a
line left holding a bare delimiter goes with it.

Five files keep their comments behind a nocheck marker instead. Four are
upstream configs whose inline docs are upstream's own (mautrix, systemd
journald, nextcloud-oidc-login, MediaWiki). In littlejs the
commented-out entries ARE the deactivation mechanism for an example
tile, so deleting them would delete configuration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 03:22:02 +02:00

135 lines
3.9 KiB
Python

from __future__ import annotations
import argparse
import sys
from pathlib import Path
from typing import TYPE_CHECKING
from cli import PROJECT_ROOT
from utils.roles.meta_lookup import get_role_lifecycle
if TYPE_CHECKING:
from collections.abc import Iterable
def _iter_role_dirs(roles_dir: Path) -> Iterable[tuple[str, Path]]:
"""Yield ``(role_name, role_dir)`` for every directory under ``roles_dir``."""
if not roles_dir.exists() or not roles_dir.is_dir():
return
for role_dir in sorted(p for p in roles_dir.iterdir() if p.is_dir()):
yield role_dir.name, role_dir
def filter_roles(
roles_dir: Path,
mode: str,
statuses: set[str],
selection: set[str] | None = None,
include_missing_lifecycle_on_blacklist: bool = True,
) -> list[str]:
matched: list[str] = []
for role_name, role_dir in _iter_role_dirs(roles_dir):
if selection is not None and role_name not in selection:
continue
try:
lifecycle_value = get_role_lifecycle(role_dir, role_name=role_name)
except Exception:
lifecycle_value = None
lifecycle = (lifecycle_value or "").strip().lower()
if mode == "whitelist":
if lifecycle in statuses:
matched.append(role_name)
else:
if lifecycle == "":
if include_missing_lifecycle_on_blacklist:
matched.append(role_name)
continue
if lifecycle not in statuses:
matched.append(role_name)
return sorted(matched)
def build_parser() -> argparse.ArgumentParser:
default_roles_dir = PROJECT_ROOT / "roles"
p = argparse.ArgumentParser(
prog="infinito meta roles lifecycle",
description="Print role names (space-separated) filtered by galaxy_info.lifecycle "
"in roles/*/meta/main.yml.\n\n"
"Examples:\n"
" infinito meta roles lifecycle whitelist stable rc\n"
" infinito meta roles lifecycle blacklist deprecated eol\n"
" infinito meta roles lifecycle whitelist stable "
"--selection web-app-matomo docker-keycloak\n",
formatter_class=argparse.RawTextHelpFormatter,
)
p.add_argument(
"mode",
choices=["whitelist", "blacklist"],
help="Filtering mode.",
)
p.add_argument(
"statuses",
nargs="+",
help="Lifecycle statuses (space-separated), e.g. stable beta rc deprecated eol",
)
p.add_argument(
"--roles-dir",
type=Path,
default=default_roles_dir,
help=f"Roles directory to scan (default: {default_roles_dir})",
)
p.add_argument(
"--selection",
nargs="+",
help="Optional whitelist of role names. "
"Only roles contained in this list are returned if filters match.",
)
p.add_argument(
"--exclude-missing",
action="store_true",
help="In blacklist mode: exclude roles with missing lifecycle instead of including them.",
)
return p
def main(argv: list[str] | None = None) -> int:
args = build_parser().parse_args(argv)
roles_dir: Path = args.roles_dir
statuses = {s.strip().lower() for s in args.statuses if s.strip()}
selection = (
{s.strip() for s in args.selection if s.strip()} if args.selection else None
)
if not roles_dir.is_dir():
print(f"Error: roles directory not found: {roles_dir}", file=sys.stderr)
return 1
try:
role_names = filter_roles(
roles_dir=roles_dir,
mode=args.mode,
statuses=statuses,
selection=selection,
include_missing_lifecycle_on_blacklist=not args.exclude_missing,
)
except RuntimeError as exc:
print(str(exc), file=sys.stderr)
return 1
sys.stdout.write(" ".join(role_names) + "\n")
return 0
if __name__ == "__main__":
raise SystemExit(main())