ci: accept relocated cost map pins in trusted guards

This commit is contained in:
Devin AI 2026-11-10 19:49:08 +00:00
parent ee004427d7
commit 4ede030b08
2 changed files with 30 additions and 3 deletions

View file

@ -28,8 +28,13 @@ from typing import Final
COST_MAP_PATH: Final = "model_prices_and_context_window.json"
BACKUP_PATH: Final = "litellm/model_prices_and_context_window_backup.json"
PINS_PATH: Final = "ci_cd/cost_map_pins.json"
PINS_PATHS: Final = (
"litellm/scripts/ci_cd/cost_map_pins.json",
"scripts/ci_cd/cost_map_pins.json",
"ci_cd/cost_map_pins.json",
)
GUARDED_PATHS: Final = (COST_MAP_PATH, BACKUP_PATH)
CHECKED_PATHS: Final = (*GUARDED_PATHS, PINS_PATH)
CHECKED_PATHS: Final = (*GUARDED_PATHS, *PINS_PATHS)
BOT_BRANCH_PREFIX: Final = "litellm_cost_map_sync_"
PRICE_SYNC_BRANCH_PREFIX: Final = "litellm-providers/price-sync"
TARGET_ENV: Final = "COST_MAP_GUARD_TARGET"
@ -193,7 +198,7 @@ def _bot_failures(base: Snapshot, head_map: CostMap, changed_files: Sequence[str
def pin_author_failures(head_ref: str, author_type: str, changed_files: Sequence[str]) -> tuple[str, ...]:
if PINS_PATH not in changed_files:
if not any(path in changed_files for path in PINS_PATHS):
return ()
if head_ref.startswith(PRICE_SYNC_BRANCH_PREFIX):
return (f"price sync PRs may not change {PINS_PATH}; a pin moves only in a human PR with new evidence",)
@ -252,7 +257,10 @@ def _git(*args: str) -> str | None:
def snapshot(revision: str) -> Snapshot:
return Snapshot(*(_git("show", f"{revision}:{path}") or "" for path in CHECKED_PATHS))
return Snapshot(
*(_git("show", f"{revision}:{path}") or "" for path in GUARDED_PATHS),
next((text for path in PINS_PATHS if (text := _git("show", f"{revision}:{path}")) is not None), ""),
)
def merged_tree(merge_base: str, target: str, head: str) -> str | MergeFailed | None:

View file

@ -355,6 +355,25 @@ def test_checked_in_pins_hold_in_the_checked_in_cost_map() -> None:
assert guard.pin_failures(pins, cost_map) == ()
@pytest.mark.parametrize("pins_path", guard.PINS_PATHS)
@pytest.mark.parametrize("pins", (PINS, "", "not JSON"))
def test_relocated_pins_keep_the_same_validation(tmp_path: Path, pins_path: str, pins: str) -> None:
subprocess.run(("git", "init", "-q", str(tmp_path)), check=True)
base: Final = _commit(tmp_path, BASE_MAP, "base", pins=PINS)
destination: Final = tmp_path / pins_path
destination.parent.mkdir(parents=True, exist_ok=True)
(tmp_path / guard.PINS_PATH).rename(destination)
destination.write_text(pins)
head: Final = _git_commit(tmp_path, "relocate pins")
result: Final = _run_guard(tmp_path, base, head, "litellm_fix_pricing")
assert result.returncode == (0 if pins == PINS else 1), result.stdout + result.stderr
@pytest.mark.parametrize("pins_path", guard.PINS_PATHS)
def test_relocated_pins_cannot_be_changed_by_bots(pins_path: str) -> None:
assert guard.pin_author_failures("litellm_fix_pricing", "Bot", (pins_path,)) == (BOT_AUTHOR_PIN_FAILURE,)
def _commit(repo: Path, cost_map: dict[str, object], message: str, pins: str | None = None) -> str:
text = _serialize(cost_map)
pins_file = repo / guard.PINS_PATH