litellm/tests/code_coverage_tests/check_json_duplicate_keys.py
Claude 9856bdf22f
address review: wire the duplicate-key guard into CI
Greptile was right: the guard was added to check_endpoint_coverage.py, and that
script is not run by any workflow - so it would never have executed. A check that
never runs is decoration.

It cannot simply be added to CI as-is: check_endpoint_coverage.py currently exits 1
because docs/my-website/sidebars.js no longer exists at the path it expects. That
failure is unrelated to this change, and wiring the script up as-is would turn CI
red for a reason this PR did not cause.

So the guard moves into its own small script and gets its own CI step:

  - tests/code_coverage_tests/check_json_duplicate_keys.py (new, standalone)
  - one step in .github/workflows/test-code-quality.yml, next to check_licenses
  - check_endpoint_coverage.py reverted to exactly its upstream contents

Verified it fails when it should: re-inserting the duplicate charity_engine entry
makes the new step exit 1 and name the key; removing it again exits 0.

The script also exits 1 if FILES_TO_CHECK is empty or a listed path is gone -
scanning zero files must not look like success.
2026-09-05 22:04:23 +00:00

98 lines
3.1 KiB
Python

"""
Fail if a hand-maintained JSON config file declares the same key twice inside one object.
Why this needs its own check:
json.load() keeps the LAST of a repeated key and reports no error. So when two
copies of the same object exist and they are not identical, the earlier copy is
dropped without a trace - the file parses, CI passes, and whatever fields only
the earlier copy had are simply not there. Nobody is told.
Every existing check reads the PARSED file, and the duplicate is already gone by
then. This check re-reads the raw text with object_pairs_hook, which is the only
place the evidence still exists.
Add a file to FILES_TO_CHECK when it is edited by hand and read by code at runtime.
Generated files and lockfiles do not belong here.
"""
import json
import sys
from pathlib import Path
from typing import Dict, List, Tuple
# Repo-root-relative paths of hand-maintained JSON that code reads at runtime.
FILES_TO_CHECK = [
"provider_endpoints_support.json",
]
def get_repo_root() -> Path:
return Path(__file__).parent.parent.parent
def find_duplicate_keys(file_path: Path) -> List[Tuple[str, int]]:
"""Return [(key, occurrences), ...] for keys repeated inside the same object."""
duplicates: List[Tuple[str, int]] = []
def collect(pairs):
counts: Dict[str, int] = {}
for key, _ in pairs:
counts[key] = counts.get(key, 0) + 1
duplicates.extend((key, n) for key, n in counts.items() if n > 1)
return dict(pairs)
with open(file_path, "r") as f:
json.loads(f.read(), object_pairs_hook=collect)
return duplicates
def main() -> None:
repo_root = get_repo_root()
failures: List[str] = []
checked = 0
print("🔑 Checking hand-maintained JSON config for duplicate keys...\n")
for rel_path in FILES_TO_CHECK:
file_path = repo_root / rel_path
if not file_path.exists():
# A path that no longer exists means this check is silently protecting
# nothing, so say so instead of passing.
failures.append(f"{rel_path}: file not found at {file_path}")
continue
checked += 1
duplicates = find_duplicate_keys(file_path)
if duplicates:
for key, occurrences in duplicates:
failures.append(
f"{rel_path}: '{key}' is declared {occurrences} times inside the "
"same object; only the last one survives json.load()"
)
else:
print(f" ✅ {rel_path}")
if not checked:
# Scanning zero files must never look like success.
print("\n❌ No files were checked - FILES_TO_CHECK is empty or all paths are stale")
sys.exit(1)
if failures:
print("\n❌ Duplicate keys found:\n")
for line in failures:
print(f" - {line}")
print(
"\nMerge the duplicate objects into one, keeping every field that appears "
"in either copy."
)
sys.exit(1)
print(f"\n✅ {checked} file(s) checked, no duplicate keys found")
if __name__ == "__main__":
main()