diff --git a/Makefile b/Makefile index dec853515b9..29a666513fe 100644 --- a/Makefile +++ b/Makefile @@ -239,6 +239,9 @@ lint-gate: $(LINT_DEP_INSTALL) $(LINT_DEP_BASE) check-circular-imports: $(LINT_DEP_INSTALL) cd litellm && $(UV_RUN) python ../tests/documentation_tests/test_circular_imports.py && cd .. +lint-code-quality: $(LINT_DEP_INSTALL) + $(UV_RUN) python scripts/code_quality_checks.py + check-import-safety: $(LINT_DEP_INSTALL) @$(UV_RUN) python -c "from litellm import *; print('[from litellm import *] OK! no issues!');" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1) @@ -246,7 +249,7 @@ check-import-safety: $(LINT_DEP_INSTALL) # green CI lint: it installs the same env (proxy-dev + generated Prisma client) and then # runs the diff-scoped ruff format check, whole-tree ruff check, the strict-rule / # type-discipline / basedpyright gates as a delta vs the base, then the circular-import -# and import-safety checks. Steps that compare against the base resolve it the same way CI +# and import-safety checks, plus the tests/code_coverage_tests scripts of its code-quality job. Steps that compare against the base resolve it the same way CI # does (merge-base with origin's current default branch). Setup (env sync, Prisma client, # base fetch) runs once up front; the checks themselves are independent, so a sub-make # fans them out with -j and the fast ones finish under basedpyright's shadow. @@ -257,7 +260,7 @@ lint-inner: lint-install @base_ref=$$($(RESOLVE_BASE)) && \ $(MAKE) BASE_REF="$$base_ref" -j $(LINT_JOBS) $(LINT_OUTPUT_SYNC) LINT_DEP_INSTALL= LINT_E2E_DEP_INSTALL= LINT_DEP_BASE= lint-checks -lint-checks: lint-format-check-changed lint-ruff lint-gate lint-type-discipline lint-test-quality lint-openapi-docs lint-basedpyright lint-e2e-basedpyright check-circular-imports check-import-safety +lint-checks: lint-format-check-changed lint-ruff lint-gate lint-type-discipline lint-test-quality lint-openapi-docs lint-basedpyright lint-e2e-basedpyright check-circular-imports check-import-safety lint-code-quality # Faster linting for local development (only checks changed code) lint-dev: lint-format-changed check-circular-imports check-import-safety diff --git a/scripts/code_quality_checks.py b/scripts/code_quality_checks.py new file mode 100644 index 00000000000..6d8316ed24d --- /dev/null +++ b/scripts/code_quality_checks.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +"""Run the tests/code_coverage_tests scripts that test-linting.yml's code-quality job runs. + +The list is read from the workflow itself, so a script added to that job runs under +`make lint` (and so `make check`) as soon as it lands, and a local pass means those +CI steps pass too. +""" + +import os +import re +import subprocess +import sys +from collections.abc import Mapping, Sequence +from concurrent.futures import ThreadPoolExecutor +from dataclasses import dataclass +from functools import partial +from pathlib import Path +from typing import Final + +import yaml +from pydantic import BaseModel, ConfigDict, Field + +REPO_ROOT: Final = Path(__file__).resolve().parent.parent +WORKFLOW: Final = REPO_ROOT / ".github" / "workflows" / "test-linting.yml" +JOB: Final = "code-quality" +SCRIPT_STEP: Final = re.compile(r"uv run --no-sync python (?P