mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
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>
135 lines
3.9 KiB
Python
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())
|