diff --git a/.github/workflows/pr-preview-build.yml b/.github/workflows/pr-preview-build.yml index 0c302b5..468bab6 100644 --- a/.github/workflows/pr-preview-build.yml +++ b/.github/workflows/pr-preview-build.yml @@ -126,6 +126,7 @@ jobs: mkdir -p "$artifact_directory" docker buildx build \ + --build-arg "RENTNERPROXY_BUILD_VERSION=$IMMUTABLE_TAG" \ --file source/docker/production/Dockerfile \ --label 'org.opencontainers.image.title=RentnerProxy PR Preview' \ --label 'org.opencontainers.image.description=Unreviewed pull request preview for testing only.' \ diff --git a/.github/workflows/release-pipeline.yml b/.github/workflows/release-pipeline.yml index eee0967..2f0e365 100644 --- a/.github/workflows/release-pipeline.yml +++ b/.github/workflows/release-pipeline.yml @@ -330,6 +330,7 @@ jobs: with: cache-from: type=gha,scope=release-${{ inputs.channel }} cache-to: type=gha,mode=max,scope=release-${{ inputs.channel }} + build-args: RENTNERPROXY_BUILD_VERSION=${{ inputs.release_tag }} context: source file: source/docker/production/Dockerfile labels: ${{ steps.metadata.outputs.labels }} diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index be0ef60..c8c29c3 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -9,7 +9,8 @@ RUN bun install --frozen-lockfile FROM web-dependencies AS web-build COPY . . -RUN bun run build:web \ +ARG RENTNERPROXY_BUILD_VERSION +RUN RENTNERPROXY_BUILD_VERSION="$RENTNERPROXY_BUILD_VERSION" bun run build:web \ && bun build web/src/db/migrate.ts --target=bun --outfile=/build/migrate.js FROM oven/bun:1.4.2@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895 AS web-runtime diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile index 64b5b21..3a121bf 100644 --- a/docker/web/Dockerfile +++ b/docker/web/Dockerfile @@ -7,7 +7,8 @@ RUN bun install --frozen-lockfile FROM dependencies AS build COPY . . -RUN bun run build:web +ARG RENTNERPROXY_BUILD_VERSION +RUN RENTNERPROXY_BUILD_VERSION="$RENTNERPROXY_BUILD_VERSION" bun run build:web RUN bun build web/src/db/migrate.ts --target=bun --outfile=/build/migrate.js FROM oven/bun:1.4.2@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895 AS runtime diff --git a/web/src/config/version.config.ts b/web/src/config/version.config.ts new file mode 100644 index 0000000..8344ff2 --- /dev/null +++ b/web/src/config/version.config.ts @@ -0,0 +1,4 @@ +declare const RENTNERPROXY_BUILD_VERSION: string + +export const APP_VERSION = + typeof RENTNERPROXY_BUILD_VERSION === 'string' ? RENTNERPROXY_BUILD_VERSION : '0.0.0-dev' diff --git a/web/src/features/ApplicationVersion/Hooks/useApplicationVersionLogic.ts b/web/src/features/ApplicationVersion/Hooks/useApplicationVersionLogic.ts new file mode 100644 index 0000000..f795eb3 --- /dev/null +++ b/web/src/features/ApplicationVersion/Hooks/useApplicationVersionLogic.ts @@ -0,0 +1,14 @@ +import { useQuery } from '@tanstack/react-query' + +import { getApplicationUpdateHandler } from '../server' + +export default function useApplicationVersionLogic() { + return useQuery({ + queryKey: ['application-update'], + queryFn: () => getApplicationUpdateHandler(), + staleTime: 60 * 60 * 1000, + refetchInterval: 60 * 60 * 1000, + refetchIntervalInBackground: false, + retry: false, + }) +} diff --git a/web/src/features/ApplicationVersion/server.ts b/web/src/features/ApplicationVersion/server.ts new file mode 100644 index 0000000..423fd87 --- /dev/null +++ b/web/src/features/ApplicationVersion/server.ts @@ -0,0 +1,11 @@ +import { createServerFn } from '@tanstack/react-start' + +import { PERMISSIONS } from '../../config/permissions.config' +import { APP_VERSION } from '../../config/version.config' +import { requirePermissionService } from '../../server/Auth/Access/authorization.service' +import { getAvailableUpdate } from '../../server/Updates/releases.service' + +export const getApplicationUpdateHandler = createServerFn({ method: 'GET' }).handler(async () => { + await requirePermissionService(PERMISSIONS.APP_ACCESS) + return { latestVersion: await getAvailableUpdate(APP_VERSION) } +}) diff --git a/web/src/language/Locales/de.json b/web/src/language/Locales/de.json index 4a84bba..84b3466 100644 --- a/web/src/language/Locales/de.json +++ b/web/src/language/Locales/de.json @@ -49,7 +49,9 @@ "certificates": "Zertifikate", "accessPolicies": "Zugriffsrichtlinien", "proxyAccessLogs": "Zugriffsprotokolle", - "auditLogs": "Audit-Protokoll" + "auditLogs": "Audit-Protokoll", + "systemVersion": "Systemversion {{version}}", + "updateAvailable": "Update verfügbar auf Version {{version}}" }, "language": { "title": "Sprache", diff --git a/web/src/language/Locales/en.json b/web/src/language/Locales/en.json index 3437e71..d2538e0 100644 --- a/web/src/language/Locales/en.json +++ b/web/src/language/Locales/en.json @@ -49,7 +49,9 @@ "certificates": "Certificates", "accessPolicies": "Access policies", "proxyAccessLogs": "Access logs", - "auditLogs": "Audit log" + "auditLogs": "Audit log", + "systemVersion": "System version {{version}}", + "updateAvailable": "Update available to version {{version}}" }, "language": { "title": "Language", diff --git a/web/src/language/Locales/es.json b/web/src/language/Locales/es.json index 5cbcc90..d4909f6 100644 --- a/web/src/language/Locales/es.json +++ b/web/src/language/Locales/es.json @@ -49,7 +49,9 @@ "certificates": "Certificados", "accessPolicies": "Políticas de acceso", "proxyAccessLogs": "Registros de acceso", - "auditLogs": "Registro de auditoría" + "auditLogs": "Registro de auditoría", + "systemVersion": "Versión del sistema {{version}}", + "updateAvailable": "Actualización disponible a la versión {{version}}" }, "language": { "title": "Idioma", diff --git a/web/src/language/Locales/fr.json b/web/src/language/Locales/fr.json index f11c988..73a1572 100644 --- a/web/src/language/Locales/fr.json +++ b/web/src/language/Locales/fr.json @@ -49,7 +49,9 @@ "certificates": "Certificats", "accessPolicies": "Politiques d’accès", "proxyAccessLogs": "Journaux d’accès", - "auditLogs": "Journal d’audit" + "auditLogs": "Journal d’audit", + "systemVersion": "Version du système {{version}}", + "updateAvailable": "Mise à jour disponible vers la version {{version}}" }, "language": { "title": "Langue", diff --git a/web/src/layout/Components/ApplicationShell/Components/ApplicationVersion.tsx b/web/src/layout/Components/ApplicationShell/Components/ApplicationVersion.tsx new file mode 100644 index 0000000..6d5ae37 --- /dev/null +++ b/web/src/layout/Components/ApplicationShell/Components/ApplicationVersion.tsx @@ -0,0 +1,36 @@ +import { ArrowUp } from 'lucide-react' + +import { APP_VERSION } from '../../../../config/version.config' +import useTranslationStore from '../../../../language/useTranslationStore' +import { Tooltip } from '../../../../shared/Tooltip' +import useApplicationVersionLogic from '../../../../features/ApplicationVersion/Hooks/useApplicationVersionLogic' + +export default function ApplicationVersion() { + const { t } = useTranslationStore() + const { data } = useApplicationVersionLogic() + const updateLabel = t('shell.updateAvailable', { version: data?.latestVersion }) + + return ( +