fix(proxy): allow latest release info and reset banner dismissal
Some checks failed
LiteLLM Rust / rust-lint (push) Waiting to run
LiteLLM Rust / rust-test (push) Waiting to run
LiteLLM Rust / rust-wheel (push) Waiting to run
Terraform Provider / gofmt, vet, build, test (push) Waiting to run
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Waiting to run
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
kerry 2026-09-19 00:44:10 +00:00
parent 4036b769a9
commit 26bcc537a5
4 changed files with 39 additions and 3 deletions

View file

@ -633,6 +633,7 @@ class LiteLLMRoutes(enum.Enum):
"/v1/models",
"/sso/get/ui_settings",
"/get/user_banner",
"/get/latest_release_info",
]
# NOTE: ROUTES ONLY FOR MASTER KEY - only the Master Key should be able to Reset Spend

View file

@ -120,6 +120,33 @@ def test_user_banner_read_open_to_non_admin_roles(role):
)
@pytest.mark.parametrize(
"role",
[
LitellmUserRoles.INTERNAL_USER.value,
LitellmUserRoles.INTERNAL_USER_VIEW_ONLY.value,
],
)
def test_latest_release_info_read_open_to_non_admin_roles(role):
user_obj = LiteLLM_UserTable(
user_id="test_user",
user_email="test@example.com",
user_role=role,
)
valid_token = UserAPIKeyAuth(user_id="test_user", user_role=role)
request = MagicMock(spec=Request)
request.query_params = {}
RouteChecks.non_proxy_admin_allowed_routes_check(
user_obj=user_obj,
_user_role=role,
route="/get/latest_release_info",
request=request,
valid_token=valid_token,
request_data={},
)
def test_user_banner_update_rejected_for_non_admin():
"""Publishing the banner stays admin-only at the route layer."""
user_obj = LiteLLM_UserTable(

View file

@ -82,6 +82,14 @@ describe("UpgradeBannerView", () => {
render(<UpgradeBannerView currentVersion="1.102.0" latestRelease={{ ...RELEASE, version: "1.104.0" }} />);
expect(screen.getByRole("status")).toHaveTextContent("The latest version is v1.104.0");
});
it("shows a newer release after the current one was dismissed without remounting", () => {
const { rerender } = render(<UpgradeBannerView currentVersion="1.102.0" latestRelease={RELEASE} />);
fireEvent.click(screen.getByRole("button", { name: "Close" }));
expect(screen.queryByRole("status")).not.toBeInTheDocument();
rerender(<UpgradeBannerView currentVersion="1.102.0" latestRelease={{ ...RELEASE, version: "1.104.0" }} />);
expect(screen.getByRole("status")).toHaveTextContent("The latest version is v1.104.0");
});
});
describe("UpgradeBanner", () => {

View file

@ -34,20 +34,20 @@ export const describeRelease = ({ new_features, bug_fixes, other_updates }: Late
].join(", ");
export const UpgradeBannerView: React.FC<UpgradeBannerViewProps> = ({ currentVersion, latestRelease }) => {
const [locallyDismissed, setLocallyDismissed] = useState(false);
const [dismissedVersion, setDismissedVersion] = useState<string | null>(null);
if (!currentVersion || !latestRelease || !isNewerVersion(currentVersion, latestRelease.version)) {
return null;
}
const dismissKey = `${DISMISS_KEY_PREFIX}${latestRelease.version}`;
if (locallyDismissed || getLocalStorageItem(dismissKey) === "true") {
if (dismissedVersion === latestRelease.version || getLocalStorageItem(dismissKey) === "true") {
return null;
}
const handleClose = () => {
setLocalStorageItem(dismissKey, "true");
setLocallyDismissed(true);
setDismissedVersion(latestRelease.version);
};
return (