Skip to content

feat(ui): add upgrade banner with latest release changelog stats - #40429

Merged
litellm-stampbot merged 10 commits into
mainfrom
litellm_upgrade_banner_changelog_stats
Sep 21, 2026
Merged

litellm-stampbot merged 10 commits into
mainfrom
litellm_upgrade_banner_changelog_stats

Conversation

@litellm-stampbot

@litellm-stampbot litellm-stampbot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Admins have no in-product signal that a newer LiteLLM release exists
  • Release notes list how many features and fixes shipped, but nobody sees them

How it solves it:

  • New authenticated GET /get/latest_release_info reads the latest stable GitHub release
  • Release bullets are bucketed into new features, fixes, and other updates
  • Result is cached for an hour, failures for five minutes, one upstream fetch per cache miss
  • Admin UI shows a dismissible top banner when the running version is behind, for every dashboard role

User Flow

Before: an admin running an old proxy never learns a newer release exists

  1. They open http://localhost:3000/ and land on Virtual Keys with only the sidebar version badge v1.99.0
  2. They send GET http://localhost:4000/get/latest_release_info with the master key and get {"detail":"Not Found"} with status 404
  3. They have to visit GitHub releases by hand to find out v1.101.0 is out

After: the same admin sees the newer release and its changelog stats at the top of every dashboard page

  1. They open http://localhost:3000/ and a blue banner reads "The latest version is v1.101.0: 96 new features, 270 fixes, and 107 other updates" and "Your current version is v1.99.0", with v1.101.0 linking to the GitHub release
  2. GET http://localhost:4000/get/latest_release_info with the master key returns {"version":"1.101.0","new_features":96,"bug_fixes":270,"other_updates":107,"release_url":"https://github.com/BerriAI/litellm/releases/tag/v1.101.0"} with status 200
  3. They click the banner's Close button, the banner disappears, and it stays hidden after a reload for that release
  4. Without a key the same GET returns the usual 401 authentication error
  5. An internal user or viewer key gets the same 200, so non-admin dashboard users see the banner too

Relevant issues

Affected release

Linear ticket

Resolves LIT-7209
Closes LIT-7209

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Shared setup: Postgres plus the proxy started with PYTHONPATH=<checkout> python litellm/proxy/proxy_cli.py --config config.yaml --port 4000, config below. The Admin UI dev server is npm run dev in ui/litellm-dashboard on port 3000. For the UI case the installed package metadata was pointed at version 1.99.0 so the running proxy reports an older version than the live latest release (1.101.0). The live GitHub release body is byte-identical across arms; the only difference between arms is the checkout on PYTHONPATH

model_list:
  - model_name: gpt-4o-mini
    litellm_params:
      model: openai/gpt-4o-mini
      api_key: os.environ/OPENAI_API_KEY
general_settings:
  master_key: sk-1234
litellm_settings:
  telemetry: False

Before (ff7dc86)

Endpoint

  1. curl -s -w "\n%{http_code}\n" -H "Authorization: Bearer sk-1234" http://localhost:4000/get/latest_release_info
  2. {"detail":"Not Found"} then 404

Control leg (real provider call)

  1. curl -s -w "\n%{http_code}\n" -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" http://localhost:4000/chat/completions -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Reply with the single word ok"}],"max_tokens":5}'
  2. {"id":"chatcmpl-EPd0hZ6ct6bPuN5vFS2SOVWRyyEuf",...,"choices":[{"finish_reason":"stop","index":0,"message":{"content":"Ok.","role":"assistant",...}}],"usage":{"completion_tokens":2,"prompt_tokens":13,"total_tokens":15,...}} then 200

Admin UI

  1. Open http://localhost:3000/ after logging in at http://localhost:3000/login with the master key
  2. Virtual Keys page renders with no upgrade banner; only the sidebar badge shows v1.99.0

Unauthenticated

  1. curl -s -w "\n%{http_code}\n" http://localhost:4000/get/latest_release_info
  2. {"detail":"Not Found"} then 404

After (3777b0b)

The endpoint, unauthenticated and cache legs below were re-captured on the tip 3777b0b after merging current main. The control leg, Admin UI and non-admin legs were captured on 26bcc53; the commits since then only merge main, swap a mutable Counter for a MappingProxyType, and annotate a test, none of which change those paths

Endpoint

  1. curl -s -w "\n%{http_code}\n" -H "Authorization: Bearer sk-1234" http://localhost:4000/get/latest_release_info
  2. {"version":"1.101.0","new_features":96,"bug_fixes":270,"other_updates":107,"release_url":"https://github.com/BerriAI/litellm/releases/tag/v1.101.0"} then 200

Control leg (real provider call)

  1. Same curl ... /chat/completions as Before
  2. 200 with a real chat.completion object

Admin UI

  1. Open http://localhost:3000/ after logging in at http://localhost:3000/login with the master key
  2. A blue banner sits above the page content: "The latest version is v1.101.0: 96 new features, 270 fixes, and 107 other updates" and "Your current version is v1.99.0"; v1.101.0 links to https://github.com/BerriAI/litellm/releases/tag/v1.101.0
  3. Click the Close button at the right end of the banner; the banner disappears
  4. Press F5; the page reloads and the banner stays hidden for release 1.101.0

Unauthenticated

  1. curl -s -w "\n%{http_code}\n" http://localhost:4000/get/latest_release_info
  2. {"error":{"message":"Authentication Error, No api key passed in.","type":"auth_error","param":"None","code":"401"}} then 401

Non-admin role

  1. KEY=$(curl -s -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" -d '{"user_role":"internal_user_viewer"}' http://localhost:4000/key/generate | python3 -c "import sys,json;print(json.load(sys.stdin)['key'])")
  2. curl -s -w "\nHTTP %{http_code}\n" -H "Authorization: Bearer $KEY" http://localhost:4000/get/latest_release_info
  3. On the previous revision of this branch (4036b76) this returned {"error":{"message":"Authentication Error, Only proxy admin can be used to generate, delete, update info for new keys/users/teams. Route=/get/latest_release_info. ...","type":"auth_error","param":"None","code":"401"}} then HTTP 401
  4. On this revision the same key gets HTTP 200. In that capture the body was null because this box had exhausted the anonymous GitHub API rate limit; the admin curl above shows the populated body

Cache

  1. for i in 1 2 3; do curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" -H "Authorization: Bearer sk-1234" http://localhost:4000/get/latest_release_info; done
  2. On the tip the second call after the populated 200 above completed in 0.00 s of wall time with status 200; the proxy log shows a single upstream GitHub request

Type

🆕 New Feature

Caveats (if any)

Low

  • Counts come from the GitHub release body, so they are only as good as the release notes
  • The banner compares major.minor.patch only; dev or rc builds with other suffixes never show it
  • Prebuilt UI bundle under litellm/proxy/_experimental/out is rebuilt by the scheduled automation, not in this PR
  • The Analyze (python) CodeQL check is red on this PR and on main (run for 6ef7b86 fails the same way): the LogInjection.ql query exceeds its 2 GiB result-set limit. It is not a required check and there are zero github-advanced-security review threads on this PR

Review taxonomy audit (A-BB) on the current diff: A1 not applicable, the cache holds a value owned by GitHub and is refreshed by TTL only. B1 fixed, concurrent cache misses now share one fetch under an asyncio.Lock. H4 and T16 fixed, as any casts in the banner test replaced by typed partial results. T5 fixed, localStorage is cleared after each test. L6 fixed, the banner is announced with role="status" instead of an assertive alert. F3 not applicable, the endpoint has no sibling surfaces. H7 not applicable, see the prebuilt bundle caveat above. D2 fixed after Bugbot flagged it, the route is on LiteLLMRoutes.info_routes like /get/user_banner so non-admin roles are not rejected. A2 fixed after Bugbot flagged it, the banner tracks the dismissed version instead of a boolean so a later release shows again without a remount

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Link to Devin session: https://app.devin.ai/sessions/4662d75ea19f45658bcfcc67efa8b322
Open in Devin Desktop: https://app.devin.ai/desktop/session/4662d75ea19f45658bcfcc67efa8b322?variant=devin

Adds GET /get/latest_release_info, which fetches the latest stable GitHub
release once per hour per worker and buckets its PR bullets by conventional
commit prefix into new features, fixes, and other updates. The Admin UI
compares the running proxy version to that release and shows a dismissible
top banner with the stat line when the proxy is behind. Dismissal is stored
per release version in localStorage so the banner returns for the next one.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@CLAassistant

CLAassistant commented Sep 9, 2026 •

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
0 out of 2 committers have signed the CLA.

❌ Kerry Lu
❌ kerry-berri


Kerry Lu seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codspeed

codspeed Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing litellm_upgrade_banner_changelog_stats (9611af7) with main (42519a7)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (18f77e9) during the generation of this report, so 42519a7 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@codecov

codecov Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.62366% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...roxy/ui_crud_endpoints/latest_release_endpoints.py 94.50% 5 Missing ⚠️

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the latest test-only change is a justified lint annotation, and no outstanding correctness or rule-compliance issues remain.

Findings

  1. P1 Release totals omit changes ▶
  2. P2 Concurrent misses duplicate fetches ▶

Summary

Adds an authenticated latest-release endpoint and a dashboard upgrade banner showing changelog statistics, with caching, concurrent-fetch coalescing, version-aware dismissal, and coverage for parsing, authorization, caching, and UI behavior.

  • The change since the previous review only adds an explanatory lint-gate annotation to the non-admin route test.
  • The annotation accurately describes the test’s observable and does not change its execution or assertions.
  • Both previous findings are fixed: unprefixed release bullets are counted, and concurrent cache misses share one upstream fetch.

Reviews (6) · Last reviewed commit: "test(proxy): document why the release in..."

Comment thread litellm/proxy/ui_crud_endpoints/latest_release_endpoints.py Outdated
Comment thread litellm/proxy/ui_crud_endpoints/latest_release_endpoints.py Outdated
Use Annotated[..., Depends(...)] instead of a call in the default value
to clear the B008 ruff budget. Extract an inline test object over the
no-large-inline-object-arg eslint budget. Mock UpgradeBanner in the
layout test, matching the other top banners, since it now renders through
react-query hooks that need a QueryClientProvider the test doesn't set up.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@yuneng-berri
yuneng-berri deleted the branch main September 13, 2026 04:51
@yuneng-berri yuneng-berri reopened this Sep 13, 2026
@devin-ai-integration
devin-ai-integration Bot changed the base branch from litellm_internal_staging to main September 19, 2026 00:05
…latest release fetches

Unprefixed release bullets now count as other_updates, concurrent cache misses share one upstream GitHub request through an injected asyncio.Lock, and the dashboard upgrade banner is announced as status rather than alert

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@litellm-stampbot

Copy link
Copy Markdown
Contributor Author

@greptileai

@litellm-stampbot

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread litellm/proxy/ui_crud_endpoints/latest_release_endpoints.py
Comment thread ui/litellm-dashboard/src/components/UpgradeBanner.tsx
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@litellm-stampbot

Copy link
Copy Markdown
Contributor Author

@greptileai

@litellm-stampbot

Copy link
Copy Markdown
Contributor Author

bugbot run

@greptile-apps

greptile-apps Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 26bcc53. Configure here.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

@greptileai please re-review at a36a62a: merged current main into the branch, feature diff is unchanged.

…lets

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

@greptileai please review ea04267: count_release_bullets now returns an immutable mapping to clear the LIT002 lint gate.

… raising

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

@greptileai please review 3777b0b: test-only change, the route check test now carries a test-quality-ok reason for the lint gate.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

bugbot run please re-review the current tip 3777b0b; the commits since your last pass merge main and adjust lint-only code.

This branch is waiting to be deployed

1 waiting deployment
e2e-changed — 9611af78 Waiting Sep 21, 2026 by devin-ai-integration[bot] via oauth #122
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants