diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3631faaece8..3073a664cd5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,3 +4,4 @@ /litellm/deploy/helm/ @yassin-berriai /litellm/deploy/terraform/ @yassin-berriai /.github/workflows/zizmor.yml @yuneng-berri +/.github/root-entries-allowlist.json @mateo-berri @ryan-crabbe-berri @kerry-berri @joshua-berri diff --git a/.github/root-entries-allowlist.json b/.github/root-entries-allowlist.json new file mode 100644 index 00000000000..f95777f9703 --- /dev/null +++ b/.github/root-entries-allowlist.json @@ -0,0 +1,20 @@ +{ + ".agents": "Agent skills discovered from the repository root.", + ".cargo": "Cargo configuration discovered by root-invoked Cargo and maturin.", + ".gitguardian.yaml": "Root configuration discovered by GitGuardian.", + ".github": "GitHub workflows, repository automation, policy and ownership discovery.", + ".gitignore": "Git ignore rules for repository worktrees.", + "AGENTS.md": "Root instructions discovered by coding agents.", + "LICENSE": "Repository license consumed by hosting and package builds.", + "Makefile": "Root entry points for workspace development and testing.", + "README.md": "Repository overview consumed by hosting and package builds.", + "gateway": "Top-level supervisor supports worker imports without loading the SDK.", + "litellm": "Python SDK and consolidated project sources.", + "model_prices_and_context_window.json": "Published model metadata consumed by the SDK and external readers.", + "policy_templates.json": "Published policy templates retained at their existing root URL.", + "provider_endpoints_support.json": "Published provider endpoint metadata retained at its existing root URL.", + "pyproject.toml": "Root Python package manifest and workspace configuration.", + "rust-toolchain.toml": "Toolchain selection discovered by root-invoked Cargo and maturin.", + "tests": "Repository-wide test suites and test infrastructure.", + "uv.lock": "Locked dependency graph for the root Python workspace." +} diff --git a/tests/unit/test_repo_root_allowlist.py b/tests/unit/test_repo_root_allowlist.py new file mode 100644 index 00000000000..8568784684e --- /dev/null +++ b/tests/unit/test_repo_root_allowlist.py @@ -0,0 +1,34 @@ +import json +import subprocess +from pathlib import Path +from typing import Final + +ROOT: Final = Path(__file__).resolve().parents[2] +ALLOWLIST: Final = ROOT / ".github/root-entries-allowlist.json" + + +def test_tracked_root_entries_have_reviewed_reasons() -> None: + allowed: Final[dict[str, str]] = json.loads(ALLOWLIST.read_text()) + tracked: Final = frozenset( + path.split("/", 1)[0] + for path in subprocess.run( + ["git", "ls-files", "-z"], cwd=ROOT, capture_output=True, text=True, check=True + ).stdout.split("\0") + if path + ) + unlisted: Final = tuple(sorted(tracked - allowed.keys())) + stale: Final = tuple(sorted(allowed.keys() - tracked)) + invalid_reasons: Final = tuple( + sorted( + entry + for entry, reason in allowed.items() + if not isinstance(reason, str) or not reason.strip() or len(reason.splitlines()) != 1 + ) + ) + assert not (unlisted or stale or invalid_reasons), ( + f"Unlisted tracked root entries: {unlisted}\n" + f"Stale allowlist entries: {stale}\n" + f"Entries without a one-line reason: {invalid_reasons}\n" + "Edit .github/root-entries-allowlist.json to add each allowed root entry with a one-line reason, " + "or remove stale entries. Code owners must review allowlist changes." + )