mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
`prisma generate` runs `npm install prisma@<version>` whenever the
prisma-client-py binary cache directory has no CLI entrypoint, pulling ~85 MB
of query and schema engines over the network. Every workflow pointed
PRISMA_BINARY_CACHE_DIR at `${{ runner.temp }}/prisma-cache`, which GitHub
wipes and recreates per job, so that cache was empty on every job of every
run and the download was never avoidable.
The download is normally a few seconds and occasionally minutes. On one
proxy-db run it took 5m18s on a single shard against 3.8s on its eleven
siblings, which pushed the job past its 15 minute timeout and cancelled a
shard whose tests were at 99% and all passing.
Leave PRISMA_BINARY_CACHE_DIR unset so the binaries land in the
prisma-client-py default, which is already keyed by prisma and engine
version, and restore both that path and the @prisma/engines staging cache
through a shared composite action.
Job timeouts also counted setup against the test budget. `timeout-minutes`
now bounds the pytest step, with a separate allowance for checkout,
dependency install, and client generation, so slow setup shows up as a slow
job instead of a cancelled test run.
check_prisma_binary_cache.py guards all three invariants: no workflow
reintroduces the override, every job that generates the client restores the
cache, and the version the action greps out of uv.lock still resolves.
132 lines
5.2 KiB
YAML
132 lines
5.2 KiB
YAML
name: "Mutation Test (manual)"
|
|
|
|
# Manually-triggered mutation testing. Runs mutmut against the scope
|
|
# configured in [tool.mutmut] in pyproject.toml (currently the
|
|
# litellm/proxy/management_endpoints/ folder). Intended cadence is roughly
|
|
# weekly — clicked from the Actions tab when someone wants a fresh report.
|
|
#
|
|
# Uploads a structured `mutation-report.md` (Meta ACH-style: original +
|
|
# mutated function with `# MUTANT START`/`# MUTANT END` delimiters + the
|
|
# existing tests + a task instruction) as a workflow artifact. Failures
|
|
# do not block anything because nothing depends on this workflow.
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: mutation-test-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
mutation:
|
|
name: Run mutmut
|
|
runs-on: ubuntu-latest
|
|
# Whole-folder mutation against ~15 files / ~7.5k LOC can take hours.
|
|
# 350 minutes is just under the GitHub-hosted job cap of 360 minutes.
|
|
timeout-minutes: 350
|
|
|
|
steps:
|
|
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Set up uv
|
|
uses: ./.github/actions/setup-uv-with-retries
|
|
with:
|
|
version: "0.10.9"
|
|
|
|
- name: Cache uv dependencies
|
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
with:
|
|
path: |
|
|
~/.cache/uv
|
|
.venv
|
|
key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-uv-
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
.github/scripts/uv_sync_with_retries.sh --frozen --group ci --group proxy-dev --extra google --extra proxy --extra semantic-router --extra saml
|
|
|
|
- name: Cache Prisma binaries
|
|
uses: ./.github/actions/cache-prisma-binaries
|
|
|
|
- name: Generate Prisma client
|
|
run: |
|
|
uv run --no-sync prisma generate --schema litellm/proxy/schema.prisma
|
|
|
|
# mutmut 3.x runs tests inside a `mutants/` sandbox where it injects
|
|
# mutation trampolines. uv installs the project as editable by default,
|
|
# which puts the original source dir on sys.path via a .pth file and
|
|
# shadows the sandbox copy — so tests would never exercise the mutated
|
|
# code. Reinstalling non-editable removes the .pth shadow.
|
|
- name: Reinstall litellm non-editable (so mutants/ is not shadowed)
|
|
run: |
|
|
uv pip uninstall litellm
|
|
uv pip install . --no-deps
|
|
|
|
# pytest-retry's pytest_configure hook crashes with
|
|
# `INTERNALERROR: no option named 'filtered_exceptions'` when invoked
|
|
# via mutmut's in-process pytest.main() call. The entry-point name
|
|
# doesn't normalize cleanly with `-p no:<name>`, so just remove the
|
|
# package outright. Reruns are wrong for mutation testing anyway —
|
|
# rerunning a "failed" mutant test would mask which mutants are killed.
|
|
- name: Remove pytest plugins that conflict with mutmut
|
|
run: |
|
|
uv pip uninstall pytest-retry || true
|
|
|
|
- name: Run mutmut
|
|
env:
|
|
# Make the mutants/ sandbox win over site-packages on sys.path so the
|
|
# trampolined files are imported instead of the installed copy.
|
|
PYTHONPATH: ${{ github.workspace }}/mutants
|
|
run: |
|
|
set -o pipefail
|
|
mkdir -p mutants
|
|
uv run --no-sync --with mutmut==3.5.0 mutmut run 2>&1 | tee mutmut-run.log
|
|
|
|
# Generate the structured report. The script embeds the enclosing
|
|
# function source for each survivor (via Python AST) and includes the
|
|
# existing test files, so an LLM agent has enough context to write
|
|
# killing tests without further file lookups. Modeled on Meta's ACH
|
|
# prompt template (arXiv 2501.12862).
|
|
- name: Generate detailed mutation report
|
|
if: always()
|
|
run: |
|
|
set +e
|
|
uv run --no-sync --with mutmut==3.5.0 mutmut export-cicd-stats > /dev/null 2>&1
|
|
uv run --no-sync --with mutmut==3.5.0 mutmut results > mutmut-results.txt 2>&1
|
|
uv run --no-sync python scripts/mutation_report.py
|
|
# The full report can be very long for big test files; the run-page
|
|
# summary cuts off at 1 MB. Append the head of the report (summary
|
|
# + survivor list) and link out to the artifact for the full body.
|
|
{
|
|
head -c 900000 mutation-report.md
|
|
echo ""
|
|
echo ""
|
|
echo "_Full report (with embedded function bodies and test files) is in the workflow artifact._"
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
- name: Upload mutmut artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
|
with:
|
|
name: mutmut-${{ github.run_id }}-${{ github.run_attempt }}
|
|
path: |
|
|
mutation-report.md
|
|
mutmut-results.txt
|
|
mutmut-run.log
|
|
mutants/mutmut-stats.json
|
|
mutants/mutmut-cicd-stats.json
|
|
mutants/litellm/proxy/management_endpoints/**/*.py
|
|
if-no-files-found: warn
|
|
retention-days: 14
|