Add hybrid app version labels

This commit is contained in:
2026-05-07 15:17:31 +02:00
parent 1113fac144
commit 1d1f052d18
15 changed files with 158 additions and 11 deletions
+8 -2
View File
@@ -15,6 +15,8 @@ ARG VITE_OIDC_SCOPE=openid profile email
ARG VITE_OIDC_REDIRECT_URI=
ARG VITE_OIDC_POST_LOGOUT_REDIRECT_URI=
ARG VITE_DEV_API_PROXY_TARGET=http://backend:8000
ARG VITE_APP_VERSION=0.1.0
ARG VITE_APP_BUILD_INFO=dev
ENV VITE_API_URL=${VITE_API_URL} \
VITE_OIDC_ENABLED=${VITE_OIDC_ENABLED} \
@@ -23,7 +25,9 @@ ENV VITE_API_URL=${VITE_API_URL} \
VITE_OIDC_SCOPE=${VITE_OIDC_SCOPE} \
VITE_OIDC_REDIRECT_URI=${VITE_OIDC_REDIRECT_URI} \
VITE_OIDC_POST_LOGOUT_REDIRECT_URI=${VITE_OIDC_POST_LOGOUT_REDIRECT_URI} \
VITE_DEV_API_PROXY_TARGET=${VITE_DEV_API_PROXY_TARGET}
VITE_DEV_API_PROXY_TARGET=${VITE_DEV_API_PROXY_TARGET} \
VITE_APP_VERSION=${VITE_APP_VERSION} \
VITE_APP_BUILD_INFO=${VITE_APP_BUILD_INFO}
RUN npm run build
@@ -45,7 +49,9 @@ COPY frontend/ ./
ENV VITE_API_URL=/api \
VITE_OIDC_ENABLED=false \
VITE_DEV_API_PROXY_TARGET=http://backend:8000
VITE_DEV_API_PROXY_TARGET=http://backend:8000 \
VITE_APP_VERSION=0.1.0 \
VITE_APP_BUILD_INFO=dev
EXPOSE 5173
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "5173"]
+2 -1
View File
@@ -45,7 +45,7 @@ Output goes to `frontend/dist/`.
## Pages
- **Dashboard** (`/`) — Now playing, backend-collected per-machine monitoring table with 10-minute averages/min/max, library stats
- **Dashboard** (`/`) — Now playing, backend-collected per-machine monitoring table with 10-minute averages/min/max, library stats, frontend/backend version chips in the shell header
- **Monitoring** (`/monitoring`) — Per-machine CPU/IO wait/RAM/network/disk charts, collector controls, and backend-collected recent action history
- **Media** (`/media`) — Full-library table with sort/filter/search
- **Users** (`/users`) — Read-only Jellyfin user list with optional Jellyseerr enrichment
@@ -55,6 +55,7 @@ Output goes to `frontend/dist/`.
## Environment Variables
Set `VITE_API_URL` and any OIDC variables directly in your shell or Compose build args if the API is not at `http://localhost:8000`.
The frontend version defaults to the package.json version and can be overridden with `VITE_APP_VERSION` and `VITE_APP_BUILD_INFO` when you need explicit deployed labels.
```bash
VITE_API_URL=http://your-backend-host:8000
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "frontend",
"version": "0.0.0",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "frontend",
"version": "0.0.0",
"version": "0.1.0",
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "vite",
+23 -1
View File
@@ -5,7 +5,11 @@ import {
NavLink,
useLocation,
} from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
QueryClient,
QueryClientProvider,
useQuery,
} from "@tanstack/react-query";
import { ThemeProvider } from "@mui/material/styles";
import {
AppBar,
@@ -34,6 +38,8 @@ import { FileBrowser } from "./pages/FileBrowser";
import { Actions } from "./pages/Actions";
import { getAppTheme } from "./theme";
import { getOidcConfig, isOidcConfigured, setAccessToken } from "./auth";
import { fetchAppVersion } from "./api/client";
import { FRONTEND_VERSION_LABEL } from "./version";
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: 1, refetchOnWindowFocus: false } },
@@ -51,6 +57,12 @@ function Shell({
const location = useLocation();
const current = location.pathname;
const isMobile = useMediaQuery("(max-width: 900px)");
const { data: appVersion } = useQuery({
queryKey: ["app-version"],
queryFn: fetchAppVersion,
staleTime: 60 * 60 * 1000,
});
const backendLabel = appVersion?.backend_label || "…";
return (
<>
@@ -126,6 +138,16 @@ function Shell({
width: { xs: "100%", md: "auto" },
}}
>
<Chip
label={`FE ${FRONTEND_VERSION_LABEL}`}
variant="outlined"
sx={{ maxWidth: { xs: "100%", sm: 220 } }}
/>
<Chip
label={`BE ${backendLabel}`}
variant="outlined"
sx={{ maxWidth: { xs: "100%", sm: 220 } }}
/>
{authLabel && (
<Chip
label={authLabel}
+2
View File
@@ -12,6 +12,7 @@ import type {
NowPlayingSession,
MonitoringPollerStatus,
MonitoringOverviewResponse,
AppVersionInfo,
MonitoringStatus,
MonitoringMetrics,
DiskSpace,
@@ -165,6 +166,7 @@ export const fetchMonitoringMachines = () =>
get<MonitoringMachine[]>("/api/monitoring/machines");
export const fetchMonitoringPoller = () =>
get<MonitoringPollerStatus>("/api/monitoring/poller");
export const fetchAppVersion = () => get<AppVersionInfo>("/api/version");
export const fetchMonitoringOverview = () =>
get<MonitoringOverviewResponse>("/api/dashboard/monitoring");
export const fetchDashboardShortcuts = () =>
+7
View File
@@ -297,6 +297,13 @@ export interface MonitoringPollerStatus {
retention_days: number;
}
export interface AppVersionInfo {
app: string;
backend_version: string;
backend_build: string;
backend_label: string;
}
export interface MonitoringMachineOverview {
machine: MonitoringMachine;
status: string;
+19
View File
@@ -0,0 +1,19 @@
declare const __APP_VERSION__: string;
declare const __APP_BUILD_INFO__: string;
export const FRONTEND_VERSION = __APP_VERSION__;
export const FRONTEND_BUILD_INFO = __APP_BUILD_INFO__;
export function formatVersionLabel(version: string, buildInfo: string): string {
const trimmedVersion = version.trim() || "0.1.0";
const trimmedBuild = buildInfo.trim();
if (trimmedBuild && trimmedBuild !== "dev") {
return `${trimmedVersion}+${trimmedBuild}`;
}
return trimmedVersion;
}
export const FRONTEND_VERSION_LABEL = formatVersionLabel(
FRONTEND_VERSION,
FRONTEND_BUILD_INFO,
);
+11
View File
@@ -7,8 +7,19 @@ export default defineConfig(({ mode }) => {
process.env.VITE_DEV_API_PROXY_TARGET ||
env.VITE_DEV_API_PROXY_TARGET ||
"http://localhost:8000";
const appVersion =
env.VITE_APP_VERSION || process.env.npm_package_version || "0.1.0";
const appBuildInfo =
env.VITE_APP_BUILD_INFO ||
process.env.GIT_COMMIT ||
process.env.BUILD_COMMIT ||
"dev";
return {
define: {
__APP_VERSION__: JSON.stringify(appVersion),
__APP_BUILD_INFO__: JSON.stringify(appBuildInfo),
},
plugins: [react()],
server: {
proxy: {