Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
159 commits
Select commit Hold shift + click to select a range
273855b
fix(responses-bridge): map system-only chat request to system input i…
milan-berri Jun 6, 2026
d61f774
feat(bedrock): forward strict and additionalProperties to Converse to…
mateo-berri Jun 6, 2026
aeb55e7
fix(mcp): highlight MCP cards red when the logged-in user is missing …
mateo-berri Jun 6, 2026
f31d059
feat(ui): add budget duration to edit team member form (#29717)
ryan-crabbe-berri Jun 7, 2026
7bfce05
fix(ui): make workflow runs page fill full width (#29868)
yuneng-berri Jun 7, 2026
13924fa
feat: standardize rate limit errors with category, rate_limit_type, m…
mateo-berri Jun 7, 2026
3448bf7
fix(ui): default guardrails page to first tab for admins, not submitt…
yuneng-berri Jun 7, 2026
118176f
refactor(bedrock): build Converse toolSpec via a BedrockToolSpec dict…
mateo-berri Jun 7, 2026
5e2db7e
feat(litellm): add models and repository layers (#29686)
yassin-berriai Jun 7, 2026
aaf1e24
feat(ui): include internal routes in the dashboard's generated OpenAP…
ryan-crabbe-berri Jun 7, 2026
f5b11b7
feat(proxy): publish /v2/model/info in Swagger OpenAPI spec (#29900)
Sameerlite Jun 8, 2026
ff6cea4
refactor(ui): single source of truth for migrated-page routing (#29949)
ryan-crabbe-berri Jun 8, 2026
26fe26a
fix(ui/model-hub): render provider icons on the public model hub (#29…
yuneng-berri Jun 8, 2026
47b383d
fix(ui): keep create guardrail modal open on outside click (#29871)
yuneng-berri Jun 8, 2026
728f057
fix(ui): label default key type as "Full Access" on key edit page (#2…
yuneng-berri Jun 8, 2026
1afc41c
fix(ui): unify migrated-route URLs and migrate the API Reference page…
ryan-crabbe-berri Jun 8, 2026
1528f43
fix(mcp): let non-creator users OAuth into OBO-mode MCP servers from …
tin-berri Jun 8, 2026
32c88ca
Litellm oss staging 080626 (#29932)
Sameerlite Jun 8, 2026
dfb68a2
feat(galileo): add health check support for UI callback test (#29908)
Sameerlite Jun 8, 2026
69a7bdb
fix(model-management): allow deleting a BYOK model after its team is …
yuneng-berri Jun 8, 2026
a7ecf6b
feat(jwt-auth): opt-in fallback to DB team on unresolved JWT claim (#…
milan-berri Jun 8, 2026
9ccda11
fix(team_endpoints): don't block /team/update on unchanged team budge…
milan-berri Jun 8, 2026
1c881ee
fix(fireworks): enable tool calling for glm-5p1 in model cost map (#2…
milan-berri Jun 8, 2026
dfd6cbc
fix(vertex): propagate Vertex AI metadata in streaming success callba…
Sameerlite Jun 8, 2026
f59e4eb
fix(ui): show team projects to internal users (#28855)
milan-berri Jun 8, 2026
bac2590
build(deps): bump pyjwt to 2.13.0 and ws override to 8.20.1 (#29982)
yuneng-berri Jun 8, 2026
c24a360
fix(team-management): delete a team's BYOK models when the team is de…
yuneng-berri Jun 8, 2026
411bd3d
feat(vantage): include organization metadata in FOCUS Tags export (#2…
milan-berri Jun 8, 2026
1bbaf1c
fix(guardrails): read CrowdStrike AIDR identity from both metadata ba…
yuneng-berri Jun 9, 2026
92817cb
changing expires_in default to use actual slack return details (#29951)
tin-berri Jun 9, 2026
424db6a
feat(azure_ai): add MAI-Image-2.5 image generation support (#29688)
Sameerlite Jun 9, 2026
51ba6e3
fix(mcp): load MCP tool configuration tools via the OBO/passthrough-a…
tin-berri Jun 9, 2026
d84499e
fix(team): reserve team budget raises for proxy admins on /team/updat…
milan-berri Jun 9, 2026
6ae8a50
test(ui): data-driven App Router migration E2E smoke (default + serve…
ryan-crabbe-berri Jun 9, 2026
fe60f9d
fix(proxy): extend response headers hook to streaming, TTS, image gen…
michelligabriele Jun 9, 2026
38edf24
chore(ui): remove dead App Router route stubs under (dashboard) (#30045)
ryan-crabbe-berri Jun 9, 2026
d8fe091
fix(ui/mcp): reset OAuth state on create-server modal close so a prio…
tin-berri Jun 9, 2026
5b7063d
fix(mcp): allow team access-group grants in OAuth authorize/token acc…
tin-berri Jun 9, 2026
5052215
docs(security): require a reproduction video for vulnerability report…
yuneng-berri Jun 9, 2026
2481761
feat(ui): add admin flag to disable in-product UI nudges for everyone…
ryan-crabbe-berri Jun 10, 2026
9e0d92c
chore(ui): remove dead dashboard files and unused dependencies (#30047)
ryan-crabbe-berri Jun 10, 2026
2cd7e87
fix(proxy): authorize batch files using upload target_model_names (LI…
Sameerlite Jun 10, 2026
e15b37a
Add Claude Fable 5 across Anthropic, Bedrock, Vertex AI, and Azure AI…
mateo-berri Jun 10, 2026
2fe9fed
fix(caching): restore stored prompt_tokens on embedding cache hits in…
michelligabriele Jun 10, 2026
3b40ac9
Litellm oss 090626 (#30021)
Sameerlite Jun 10, 2026
f9293d4
fix(proxy): self-heal startup/reload prisma reads on engine disconnec…
michelligabriele Jun 10, 2026
a75ed00
chore(ui): make knip recognize .mjs scripts and openapi-typescript (#…
ryan-crabbe-berri Jun 10, 2026
410b892
fix(register_model): preserve built-in cache pricing when registering…
yassin-berriai Jun 10, 2026
a4a3348
[internal copy of #28007] Fix/gcp model garden streaming (#28363)
mateo-berri Jun 10, 2026
20e453f
feat(cli): per-agent `lite claude` / `codex` / `opencode` commands th…
mateo-berri Jun 10, 2026
7899463
fix(callbacks): forward callback_settings to callback initializers an…
yuneng-berri Jun 10, 2026
1436ee9
fix(mcp): drop orphaned per-user credential rows when an MCP server i…
tin-berri Jun 10, 2026
3bd3951
fix(proxy): recover from cached-plan errors by reconnecting the Prism…
yassin-berriai Jun 10, 2026
dff25fe
feat(proxy): add option to disable server-side prepared statements fo…
yassin-berriai Jun 10, 2026
b301d30
fix(release): stop backport releases from overwriting the latest badg…
yuneng-berri Jun 10, 2026
ba72ccf
feat: add conventional commits and coding guidelines (#30159)
mateo-berri Jun 10, 2026
da9d64b
fix(proxy): return 5xx on DB infra errors during auth; reserve 401 fo…
yassin-berriai Jun 10, 2026
496f5b9
fix(ui): dev server 404s on migrated-page links because uiBase hardco…
ryan-crabbe-berri Jun 11, 2026
4def691
refactor(ui): consolidate dashboard to one shell in the (dashboard) l…
ryan-crabbe-berri Jun 11, 2026
6068bb7
fix(proxy): align /v1/model/info with router deployments (#30025)
Sameerlite Jun 11, 2026
4a3860d
fix: completion_cost AttributeError on streaming Anthropic web_search…
ishaan-berri Jun 11, 2026
7a96b34
[internal copy of #30137] perf(realtime): eliminate redundant per-fra…
mateo-berri Jun 11, 2026
49ca04d
feat(bedrock): aws_bedrock_project_id for bedrock-mantle project / wo…
mateo-berri Jun 11, 2026
0d120de
chore(hooks): enforce Conventional Commits and Conventional Branches …
ryan-crabbe-berri Jun 11, 2026
012d9f6
feat(rate-limiter): allow opting out of v3 TPM reservation and Redis …
yassin-berriai Jun 11, 2026
a992ed1
feat(spend_logs): opt-in native Postgres partitioning for SpendLogs r…
yassin-berriai Jun 11, 2026
530c0b2
feat(ui): migrate playground to path routing and colocate its files (…
ryan-crabbe-berri Jun 11, 2026
a2c916f
feat(ui): migrate projects and access-groups to path routes (#30226)
ryan-crabbe-berri Jun 11, 2026
8e12d42
fix(proxy): coalesce NULL rollup metrics in aggregated daily-activity…
michelligabriele Jun 11, 2026
1828a7c
fix(passthrough): resolve costing model when body model is unknown (#…
yassin-berriai Jun 11, 2026
3ad385a
feat(ui): migrate budgets, workflows, and guardrails-monitor to path …
ryan-crabbe-berri Jun 11, 2026
2d576b5
feat(ui): migrate mcp-servers, search-tools, tag-management, vector-s…
ryan-crabbe-berri Jun 12, 2026
250d8d2
fix(a2a): forward agent_extra_headers through completion bridge (#28277)
mateo-berri Jun 12, 2026
c30297e
fix(gemini-live): forward audio buffer commit and correct Vertex PCM …
Sameerlite Jun 12, 2026
9ddf053
fix(proxy): skip double-wrapping unified batch output file ids on ret…
Sameerlite Jun 12, 2026
cfcdf87
feat: litellm oss 110626 (#30202)
Sameerlite Jun 12, 2026
1fd8ab4
fix(docker): copy only runtime artifacts into the final image (#30243)
yuneng-berri Jun 12, 2026
7519e37
feat(proxy): enforce key/team guardrails on bedrock passthrough route…
Sameerlite Jun 12, 2026
87cf67e
feat(gemini): forward web search tools in image generation (#30119)
Sameerlite Jun 12, 2026
680f3ff
fix: bedrock mantle fixes (#30083)
Sameerlite Jun 12, 2026
41801d6
feat(proxy): add require_managed_files setting for file uploads (#30186)
Sameerlite Jun 12, 2026
02bce7b
fix(mcp): honor server_id for REST tool calls with shared upstream UR…
Sameerlite Jun 12, 2026
ccc20b1
fix(responses): presidio PII masking for Azure WebSocket and streamin…
Sameerlite Jun 12, 2026
e8e5b47
feat(passthrough): add configurable pass-through request timeouts (#3…
Sameerlite Jun 12, 2026
729b005
fix(google_genai): preserve complete SSE events in Vertex/Gemini imag…
Sameerlite Jun 12, 2026
7d1f68e
fix(proxy): populate access_via_team_ids on /v1/model/info (#30274)
Sameerlite Jun 12, 2026
079c136
chore(oss): litellm oss staging 120626 (#30292)
Sameerlite Jun 12, 2026
2893f9b
feat(ui): migrate policies, guardrails, prompts, tool-policies, and s…
ryan-crabbe-berri Jun 12, 2026
4030182
feat(ui): migrate caching, cost-tracking, transform-request, ui-theme…
ryan-crabbe-berri Jun 12, 2026
76b4c4b
fix(ui): gate dashboard layout on ui config load so deep links work u…
ryan-crabbe-berri Jun 12, 2026
d258e02
feat(ui): cut admin-panel, logging-and-alerts, model-hub-table, and u…
ryan-crabbe-berri Jun 12, 2026
f49707b
fix(otel): cap metric attribute cardinality with include/exclude list…
yassin-berriai Jun 13, 2026
5047eaf
fix(proxy): return deprecated-key lookup result directly in get_data …
yuneng-berri Jun 13, 2026
d96ab46
chore(deps): bump vitest, brace-expansion, pypdf and tornado (#30220)
yuneng-berri Jun 13, 2026
e5a3083
refactor(ui): remove unreachable /chat page (#30178)
ryan-crabbe-berri Jun 13, 2026
8b9a90e
feat(ui): migrate agents and router-settings to path routes (#30323)
ryan-crabbe-berri Jun 13, 2026
6f8e6ad
feat: strengthen coding conventions in CLAUDE.md (#30333)
mateo-berri Jun 13, 2026
0dc203b
feat(ui): cut the users page over to the /ui/users path route (#30334)
ryan-crabbe-berri Jun 13, 2026
c90eb7e
feat: ruff strict-rule suppressions baseline gate (#30303)
ryan-crabbe-berri Jun 13, 2026
ec9353c
feat(guardrails): add Cisco AI Defense integration (#28249) (#30338)
yassin-berriai Jun 13, 2026
1fab5c4
chore(ui): remove dead UI components unreferenced by any page (#30340)
ryan-crabbe-berri Jun 13, 2026
a519a37
ci: add osv-scanner lockfile scan workflow (#30222)
yuneng-berri Jun 13, 2026
3b84150
fix(otel): record full error message on standard exception event in o…
yassin-berriai Jun 13, 2026
82d9f27
test(fireworks): mock whisper transcription tests instead of live cal…
yuneng-berri Jun 13, 2026
2fad75f
build(ui): pin esbuild to 0.28.1 via overrides (#30390)
yuneng-berri Jun 13, 2026
685ec00
feat(ui): cut the organizations page over to the /ui/organizations pa…
ryan-crabbe-berri Jun 13, 2026
df92c7f
fix(proxy): support SMTP implicit SSL (port 465) (#30395)
yuneng-berri Jun 13, 2026
2655d1d
fix(mcp): default Linear MCP registry entry to streamable HTTP (#30396)
ryan-crabbe-berri Jun 13, 2026
e6423d3
fix(ui): stop Virtual Keys page from infinite render loop (#30397)
ryan-crabbe-berri Jun 15, 2026
4f54f99
fix(streaming): guard raise_on_model_repetition against empty choices…
shivamrawat1 Jun 15, 2026
45d5153
feat(otel-v2): emit the 6 gen_ai.client.* metrics at parity with v1 (…
yassin-berriai Jun 15, 2026
039a2d8
fix(mcp): drop phantom 401 span on delegated OAuth2 tool calls (#30494)
ryan-crabbe-berri Jun 16, 2026
5c41aab
feat(ui): cut the teams page over to the /ui/teams path route (#30343)
ryan-crabbe-berri Jun 16, 2026
fc9d789
fix(integrations): cap Anthropic cache_control injection at 4 blocks …
shivamrawat1 Jun 16, 2026
9514e55
chore(codecov): add Batches, Videos, and Realtime components (#30517)
Sameerlite Jun 16, 2026
bed6ce8
test(batches): move orphan tests into tests/test_litellm for CI cover…
Sameerlite Jun 16, 2026
4faeabc
fix(guardrails): run pre_call hook once for model-level guardrails (#…
yassin-berriai Jun 16, 2026
9fa74ad
fix(guardrails): stop re-initializing DB guardrails on every poll (#3…
yassin-berriai Jun 16, 2026
816fca9
chore(oss): litellm oss staging 150626 (#30463)
Sameerlite Jun 16, 2026
9c775e7
ci(lint): add blanket-noqa, dataclass-default, and unused-noqa Ruff r…
mateo-berri Jun 16, 2026
d0c2e87
ci: ratchet lint and type-check gates (ruff preview, ANN, mypy, based…
mateo-berri Jun 16, 2026
902122a
fix(proxy): allow internal roles to access vector store CRUD routes (…
shivamrawat1 Jun 16, 2026
b8b0d45
fix(otel): stamp gen_ai.input/output.messages on v2 spans (#30548)
yassin-berriai Jun 16, 2026
f444539
fix(otel): export v2 gen_ai client metrics to the configured meter pr…
yassin-berriai Jun 16, 2026
ead8a70
fix(bedrock): preserve cache_control for ARN models in /v1/messages a…
mateo-berri Jun 16, 2026
38a9a60
fix: greatly increase slack (#30563)
mateo-berri Jun 16, 2026
96b9437
fix(budget): recompute budget_reset_at when budget_duration changes o…
yassin-berriai Jun 16, 2026
27c1dfb
fix(otel): accept UPPER_SNAKE_CASE OTEL_INSTRUMENTATION_GENAI_CAPTURE…
yassin-berriai Jun 16, 2026
5a62806
chore(lint): remove PLR0915 too-many-statements ruff rule (#30574)
ryan-crabbe-berri Jun 16, 2026
be4fa70
ci(lint): ratcheted type-discipline gate (mutable collections, casts,…
mateo-berri Jun 16, 2026
cd26f7d
feat(proxy): add verification_uri_complete to CLI SSO device flow (#3…
yassin-berriai Jun 17, 2026
1ccc1e5
chore: litellm oss staging160626 (#30527)
Sameerlite Jun 17, 2026
b5fcd85
fix(guardrails): return 400 not 500 when AIM blocks a request (#30573)
ryan-crabbe-berri Jun 17, 2026
17b8871
ci(lint): grandfather any-discipline with a per-file ratchet budget (…
mateo-berri Jun 17, 2026
cf2db41
fix(audio): don't override explicit response_format with verbose_json…
mateo-berri Jun 17, 2026
b638bc2
fix(anthropic): price and surface response service_tier in cost track…
mateo-berri Jun 17, 2026
cee6c9c
feat: add dev and wildcard proxy configs for local testing (#30556)
mateo-berri Jun 17, 2026
60f4c01
fix(proxy): list public team model name in /v1/models (#30588)
ishaan-berri Jun 17, 2026
b8d79d1
ci: drop mypy entirely, standardize type checking on basedpyright (#3…
mateo-berri Jun 17, 2026
78a7d0b
feat(guardrails): surface OpenAI moderation violation_categories on g…
yassin-berriai Jun 17, 2026
6c8b60d
fix(proxy): resolve list files credentials from team BYOK deployments…
shivamrawat1 Jun 17, 2026
39ab43c
feat(proxy): add --max_requests_before_restart_jitter to stagger work…
yassin-berriai Jun 17, 2026
c51ba34
fix(health): correct bedrock embedding health checks (#30583)
mateo-berri Jun 17, 2026
654e354
test: harden remaining pass-through CI flakes (image-gen spend poll, …
mateo-berri Jun 17, 2026
4ccc323
test(pass_through): harden vertex spendlog poll against transient emp…
mateo-berri Jun 17, 2026
43dadc5
fix(cost): stop non-string service_tier from silently dropping cost t…
mateo-berri Jun 17, 2026
ba29657
feat(proxy): warn at startup when custom_auth skips common_checks enf…
tin-berri Jun 17, 2026
187b205
fix(pod_lock): release cron lock by matching async_set_cache JSON enc…
yassin-berriai Jun 18, 2026
556e8f8
ci: run a local fake OpenAI endpoint instead of the shared Railway mo…
mateo-berri Jun 18, 2026
9b1c1e9
ci(windows): pin uv to Python 3.11 so it ignores the preinstalled 3.1…
mateo-berri Jun 18, 2026
d97b17b
feat(ui): migrate models page to App Router path route (#30677)
ryan-crabbe-berri Jun 18, 2026
e568d8b
refactor(ui): remove orphaned pass-through-settings route (#30692)
ryan-crabbe-berri Jun 18, 2026
e122dac
fix(cost): stop non-string response service_tier from dropping cost t…
yuneng-berri Jun 18, 2026
669ddc1
feat(agent-shin): automated PR/issue triage, low-quality auto-close, …
mateo-berri Jun 18, 2026
e33e291
chore: litellm oss 170626 (#30637)
Sameerlite Jun 18, 2026
a9e651d
fix(bedrock_mantle): add SigV4 fallback to chat completions auth (#30…
mateo-berri Jun 18, 2026
fb34c18
feat(search): add TinyFish as search provider (#30634)
simantak-dabhade Jun 18, 2026
382d78e
feat(ui): migrate old usage report to App Router path route (#30694)
ryan-crabbe-berri Jun 18, 2026
a8b94b9
fix(proxy): enforce budgets against authoritative DB spend when the c…
yassin-berriai Jun 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
161 changes: 160 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,26 @@ commands:
done
echo "record/replay proxy did not become ready" >&2
exit 1
start_fake_openai_endpoint:
description: "Start the canned OpenAI mock (tests/_fake_openai_endpoint_server.py) on host port 8190 and wait until healthy. Models whose api_base points here (via FAKE_OPENAI_API_BASE) get well-formed chat/text/embedding responses with realistic usage, so the E2E run neither pays for nor depends on the live provider. A request whose model is '429' returns HTTP 429 for rate-limit/cooldown tests. Run after uv deps are synced."
steps:
- run:
name: Start fake OpenAI endpoint
background: true
command: |
uv run --no-sync python tests/_fake_openai_endpoint_server.py --host 0.0.0.0 --port 8190
- run:
name: Wait for fake OpenAI endpoint
command: |
for i in $(seq 1 30); do
if curl -sf http://localhost:8190/health >/dev/null 2>&1; then
echo "fake OpenAI endpoint is up"
exit 0
fi
sleep 1
done
echo "fake OpenAI endpoint did not become ready" >&2
exit 1
setup_litellm_enterprise_pip:
steps:
- run:
Expand Down Expand Up @@ -168,6 +188,8 @@ jobs:
name: win/default
shell: powershell.exe
working_directory: ~/project
environment:
UV_PYTHON: "3.11"
steps:
- checkout
- run:
Expand Down Expand Up @@ -200,7 +222,7 @@ jobs:
if (-not (Select-String -Path $PROFILE -SimpleMatch $uvBin -Quiet)) {
Add-Content -Path $PROFILE -Value "`$env:Path = `"$uvBin;`$env:Path`""
}
uv sync --frozen --group dev --python (Get-Command python).Source
uv sync --frozen --group dev --python 3.11
- run:
name: Run Windows-specific test
command: |
Expand Down Expand Up @@ -594,6 +616,8 @@ jobs:
working_directory: ~/project
resource_class: large
parallelism: 4
environment:
FAKE_OPENAI_API_BASE: http://127.0.0.1:8190
steps:
- checkout
- setup_google_dns
Expand All @@ -609,6 +633,7 @@ jobs:
paths:
- ~/.cache/uv
key: v1-uv-cache-{{ checksum "uv.lock" }}
- start_fake_openai_endpoint
# Run pytest and generate JUnit XML report
- setup_litellm_enterprise_pip
- run:
Expand Down Expand Up @@ -1549,6 +1574,7 @@ jobs:
name: Install Dependencies
command: |
uv sync --frozen --all-groups --all-extras --python 3.12
- start_fake_openai_endpoint
- start_postgres:
db_name: litellm_test
- attach_workspace:
Expand Down Expand Up @@ -1586,6 +1612,7 @@ jobs:
-e DATABASE_URL="postgresql://postgres:postgres@host.docker.internal:5432/litellm_test" \
-e DEFAULT_NUM_WORKERS_LITELLM_PROXY=1 \
-e DISABLE_SCHEMA_UPDATE="True" \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
--name my-app \
--add-host=host.docker.internal:host-gateway \
-v $(pwd)/litellm/proxy/example_config_yaml/bad_schema.prisma:/app/schema.prisma \
Expand Down Expand Up @@ -1648,13 +1675,15 @@ jobs:
zstd -d litellm-docker-database.tar.zst --stdout | docker load
docker tag litellm-docker-database:ci my-app:latest
- start_openai_record_replay_proxy
- start_fake_openai_endpoint
- run:
name: Run Docker container
command: |
docker run -d \
-p 4000:4000 \
-e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \
-e USE_PRISMA_MIGRATE=True \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e AZURE_API_KEY=$AZURE_API_KEY \
-e REDIS_HOST=$REDIS_HOST \
-e REDIS_PASSWORD=$REDIS_PASSWORD \
Expand Down Expand Up @@ -1817,6 +1846,7 @@ jobs:
zstd -d litellm-docker-database.tar.zst --stdout | docker load
docker images | grep litellm-docker-database
- start_openai_record_replay_proxy
- start_fake_openai_endpoint
- run:
name: Run Docker container
# intentionally give bad redis credentials here
Expand All @@ -1830,6 +1860,7 @@ jobs:
-e REDIS_PORT=$REDIS_PORT \
-e LITELLM_MASTER_KEY="sk-1234" \
-e OPENAI_API_KEY=$OPENAI_API_KEY \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e LITELLM_LICENSE=$LITELLM_LICENSE \
-e OTEL_EXPORTER="in_memory" \
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
Expand Down Expand Up @@ -1889,6 +1920,7 @@ jobs:
-e REDIS_PORT=$REDIS_PORT \
-e LITELLM_MASTER_KEY="sk-1234" \
-e OPENAI_API_KEY=$OPENAI_API_KEY \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e LITELLM_LICENSE="bad-license" \
--add-host host.docker.internal:host-gateway \
--name my-app-3 \
Expand Down Expand Up @@ -1938,6 +1970,7 @@ jobs:
uv sync --frozen --all-groups --all-extras --python 3.12
- start_postgres
- start_redis
- start_fake_openai_endpoint
- attach_workspace:
at: ~/project
- run:
Expand All @@ -1961,6 +1994,7 @@ jobs:
-e REDIS_PORT=6379 \
-e LITELLM_MASTER_KEY="sk-1234" \
-e OPENAI_API_KEY=$OPENAI_API_KEY \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e LITELLM_LICENSE=$LITELLM_LICENSE \
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
Expand Down Expand Up @@ -2020,6 +2054,7 @@ jobs:
command: |
uv sync --frozen --all-groups --all-extras --python 3.12
- start_postgres
- start_fake_openai_endpoint
- attach_workspace:
at: ~/project
- run:
Expand All @@ -2039,6 +2074,7 @@ jobs:
-e REDIS_PASSWORD=$REDIS_PASSWORD \
-e REDIS_PORT=$REDIS_PORT \
-e LITELLM_MASTER_KEY="sk-1234" \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e LITELLM_LICENSE=$LITELLM_LICENSE \
-e USE_DDTRACE=True \
-e DD_API_KEY=$DD_API_KEY \
Expand All @@ -2060,6 +2096,7 @@ jobs:
-e REDIS_PASSWORD=$REDIS_PASSWORD \
-e REDIS_PORT=$REDIS_PORT \
-e LITELLM_MASTER_KEY="sk-1234" \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e LITELLM_LICENSE=$LITELLM_LICENSE \
-e USE_DDTRACE=True \
-e DD_API_KEY=$DD_API_KEY \
Expand Down Expand Up @@ -2112,6 +2149,7 @@ jobs:
command: |
uv sync --frozen --all-groups --all-extras --python 3.12
- start_postgres
- start_fake_openai_endpoint
- attach_workspace:
at: ~/project
- run:
Expand All @@ -2129,6 +2167,7 @@ jobs:
-e DATABASE_URL=postgresql://postgres:postgres@host.docker.internal:5432/circle_test \
-e STORE_MODEL_IN_DB="True" \
-e LITELLM_MASTER_KEY="sk-1234" \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e LITELLM_LICENSE=$LITELLM_LICENSE \
--add-host host.docker.internal:host-gateway \
--name my-app \
Expand Down Expand Up @@ -2187,6 +2226,7 @@ jobs:
command: |
docker build -t my-app:latest -f docker/build_from_pip/Dockerfile.build_from_pip .
- start_postgres
- start_fake_openai_endpoint
- run:
name: Run Docker container
# intentionally give bad redis credentials here
Expand All @@ -2200,6 +2240,7 @@ jobs:
-e REDIS_PORT=$REDIS_PORT \
-e LITELLM_MASTER_KEY="sk-1234" \
-e OPENAI_API_KEY=$OPENAI_API_KEY \
-e FAKE_OPENAI_API_BASE=http://host.docker.internal:8190 \
-e LITELLM_LICENSE=$LITELLM_LICENSE \
-e OTEL_EXPORTER="in_memory" \
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
Expand Down Expand Up @@ -2690,6 +2731,122 @@ jobs:
path: ui/litellm-dashboard/playwright-report
destination: e2e-playwright-report

e2e_ui_testing_server_root_path:
docker:
- image: cimg/python:3.12-browsers@sha256:b432899af01c9a311bf74f4f22e9ada2e5306d4b1b4383f8d29e1228a5844ef2
auth:
username: ${DOCKERHUB_USERNAME}
password: ${DOCKERHUB_PASSWORD}
- image: cimg/postgres:16.0@sha256:b125148bc76e8e8eee5eb3ad6020a3a14110a14e8192f1c645128afebe2e2f84
environment:
POSTGRES_USER: e2euser
POSTGRES_PASSWORD: e2epassword
POSTGRES_DB: litellm_e2e
resource_class: large
working_directory: ~/project
environment:
DATABASE_URL: "postgresql://e2euser:e2epassword@localhost:5432/litellm_e2e"
CI: "true"
# The whole job exercises the proxy mounted under a prefix. SERVER_ROOT_PATH
# is read both by the proxy at boot (to rewrite the built UI bundle in place)
# and by migration.serverRootPath.config.ts, which refuses to run without it.
SERVER_ROOT_PATH: "/litellm"
steps:
- checkout
- setup_google_dns
- install_uv
- restore_cache:
keys:
- v1-uv-cache-{{ checksum "uv.lock" }}
- run:
name: Install Python dependencies
command: |
uv sync --frozen --all-groups --all-extras --python 3.12
uv run --no-sync python -m prisma generate --schema litellm/proxy/schema.prisma
- save_cache:
key: v1-uv-cache-{{ checksum "uv.lock" }}
paths:
- ~/.cache/uv
- restore_cache:
keys:
- ui-e2e-node-deps-v2-{{ checksum "ui/litellm-dashboard/package-lock.json" }}
- run:
name: Install Node dependencies and Playwright
command: |
cd ui/litellm-dashboard
npm ci
npx playwright install chromium
- save_cache:
key: ui-e2e-node-deps-v2-{{ checksum "ui/litellm-dashboard/package-lock.json" }}
paths:
- ui/litellm-dashboard/node_modules
- ~/.cache/ms-playwright
- run:
name: Build UI from source
command: |
cd ui/litellm-dashboard
npm run build
rm -rf ../../litellm/proxy/_experimental/out
mv out ../../litellm/proxy/_experimental/out
find ../../litellm/proxy/_experimental/out -name '*.html' ! -name 'index.html' | while read -r f; do
d="${f%.html}"; mkdir -p "$d"; mv "$f" "$d/index.html"
done
- wait_for_service:
url: tcp://localhost:5432
timeout: "30"
- run:
name: Push Prisma schema
command: uv run --no-sync python -m prisma db push --schema litellm/proxy/schema.prisma --accept-data-loss
- run:
name: Seed database
command: |
PGPASSWORD=e2epassword psql -h localhost -p 5432 -U e2euser -d litellm_e2e \
-f ui/litellm-dashboard/e2e_tests/fixtures/seed.sql
- run:
name: Start mock LLM server
command: uv run --no-sync python ui/litellm-dashboard/e2e_tests/fixtures/mock_llm_server/server.py
background: true
- run:
name: Start LiteLLM proxy under a server root path
environment:
LITELLM_MASTER_KEY: "sk-1234"
MOCK_LLM_URL: "http://127.0.0.1:8090/v1"
DISABLE_SCHEMA_UPDATE: "true"
# Output flows to this step's own log, so a boot crash is visible here
# rather than swallowed by a downstream readiness probe.
command: |
LITELLM_LICENSE="$LITELLM_LICENSE" \
uv run --no-sync python -m litellm.proxy.proxy_cli \
--config ui/litellm-dashboard/e2e_tests/fixtures/config.yml \
--port 4000
background: true
- run:
name: Wait for prefixed proxy to be ready
command: |
for i in $(seq 1 60); do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 -H "Authorization: Bearer sk-1234" http://127.0.0.1:4000/litellm/health 2>/dev/null || true)
if [ "$HTTP_CODE" = "200" ]; then
echo "Prefixed proxy is ready"
exit 0
fi
sleep 2
done
echo "Prefixed proxy failed to start; see the 'Start LiteLLM proxy under a server root path' step for the boot log"
exit 1
- run:
name: Run migration smoke under SERVER_ROOT_PATH
command: |
cd ui/litellm-dashboard
LITELLM_LICENSE="$LITELLM_LICENSE" \
npx playwright test --config e2e_tests/migration.serverRootPath.config.ts
no_output_timeout: 10m
- store_artifacts:
path: ui/litellm-dashboard/test-results
destination: e2e-server-root-path-test-results
- store_artifacts:
path: ui/litellm-dashboard/playwright-report
destination: e2e-server-root-path-playwright-report

build_docker_database_image:
machine:
image: ubuntu-2204:2024.04.1
Expand Down Expand Up @@ -2795,6 +2952,8 @@ workflows:
filters: *main_branches
- e2e_ui_testing:
filters: *main_branches
- e2e_ui_testing_server_root_path:
filters: *main_branches
- build_and_test:
requires:
- build_docker_database_image
Expand Down
75 changes: 75 additions & 0 deletions .githooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
#
# commit-msg — enforce Conventional Commits 1.0.0
# https://www.conventionalcommits.org/en/v1.0.0/
#
# Subject format: <type>(<scope>)!: <description>
# - <type> must be one of the angular types (feat, fix, ...)
# - (<scope>) is optional
# - ! is optional and marks a breaking change
# - <description> is mandatory and must be non-empty
#
# Bypass: commit with --no-verify.
# Merge, revert, fixup!, squash!, and amend! messages are passed through.

set -eu

COMMIT_MSG_FILE="${1:-}"
if [ -z "$COMMIT_MSG_FILE" ] || [ ! -f "$COMMIT_MSG_FILE" ]; then
echo "commit-msg: missing commit message file" >&2
exit 1
fi

# First non-comment, non-empty line is the subject.
subject=""
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
''|'#'*) continue ;;
esac
subject="$line"
break
done < "$COMMIT_MSG_FILE"

if [ -z "$subject" ]; then
echo "commit-msg: empty commit message" >&2
exit 1
fi

# Pass-through commits generated by git itself.
case "$subject" in
"Merge "*|"Revert \""*|"fixup! "*|"squash! "*|"amend! "*)
exit 0
;;
esac

ALLOWED_TYPES="feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert"
# Description must not start with an uppercase letter — kept in sync with the
# subjectPattern in .github/workflows/conventional-commits.yml so the local
# hook is the strictly tighter of the two gates. (Without this guard, a commit
# like "feat: Add thing" passes locally but fails the PR-title CI check.)
PATTERN="^(${ALLOWED_TYPES})(\([^)]+\))?!?: [^A-Z].*"

if printf '%s' "$subject" | grep -Eq "$PATTERN"; then
exit 0
fi

cat >&2 <<EOF
✗ Commit message does not follow Conventional Commits.

Got: $subject

Expected: <type>(<scope>)!: <description>
(description must start with a lowercase letter)

Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
Examples:
feat(router): add weighted round-robin strategy
fix(bedrock): decouple STS region from aws_region_name
chore(deps): bump black to 26.3.1
refactor!: drop Python 3.8 support

See https://www.conventionalcommits.org/en/v1.0.0/

To bypass (use sparingly): git commit --no-verify
EOF
exit 1
Loading
Loading