diff --git a/frontend/src/components/admin/VersionInfo.tsx b/frontend/src/components/admin/VersionInfo.tsx index 7063722f..653cac38 100644 --- a/frontend/src/components/admin/VersionInfo.tsx +++ b/frontend/src/components/admin/VersionInfo.tsx @@ -3,6 +3,7 @@ import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { Info, ArrowUpCircle } from 'lucide-react'; import { api } from '../../config/api'; +import { githubReleaseUrl as releaseUrl } from '../../utils/githubReleaseUrl'; import packageJson from '../../../package.json'; // Frontend version from package.json @@ -63,20 +64,48 @@ export const VersionInfo: React.FC = () => { {channelBadge}
-
Frontend: v{FRONTEND_VERSION}
+
+ Frontend:{' '} + + v{FRONTEND_VERSION} + +
{versionInfo && ( -
Backend: v{versionInfo.backend}
+
+ Backend:{' '} + + v{versionInfo.backend} + +
)}
- {updateInfo?.enabled && updateInfo?.updateAvailable && ( -
+ {updateInfo?.enabled && updateInfo?.updateAvailable && updateInfo.latest && ( + {t('admin.updates.updateAvailableShort', 'v{{version}} available', { - version: updateInfo.latest?.forChannel + version: updateInfo.latest.forChannel })} -
+ )} ); diff --git a/frontend/src/utils/__tests__/githubReleaseUrl.test.ts b/frontend/src/utils/__tests__/githubReleaseUrl.test.ts new file mode 100644 index 00000000..6a3afde0 --- /dev/null +++ b/frontend/src/utils/__tests__/githubReleaseUrl.test.ts @@ -0,0 +1,30 @@ +/** + * Regression coverage for the version → release-page URL template (#566). + * + * release-please tags every release as `vX.Y.Z[-beta.N]`. If anyone + * later refactors the helper (e.g. switches the prefix, the repo path, + * or strips the channel suffix), these assertions will fail loud + * instead of silently producing dead links in the admin sidebar. + */ +import { describe, expect, it } from 'vitest'; +import { githubReleaseUrl } from '../githubReleaseUrl'; + +describe('githubReleaseUrl', () => { + it('maps a stable version to its tag page', () => { + expect(githubReleaseUrl('3.55.0')).toBe( + 'https://github.com/the-luap/picpeak/releases/tag/v3.55.0', + ); + }); + + it('maps a beta version (with channel suffix) to its tag page', () => { + expect(githubReleaseUrl('3.55.0-beta.0')).toBe( + 'https://github.com/the-luap/picpeak/releases/tag/v3.55.0-beta.0', + ); + }); + + it('does not double-prefix the v when given a bare version', () => { + // Defensive — the helper is the single source of truth for the + // leading "v". Callers must pass the bare version string. + expect(githubReleaseUrl('3.55.0')).not.toContain('vv'); + }); +}); diff --git a/frontend/src/utils/githubReleaseUrl.ts b/frontend/src/utils/githubReleaseUrl.ts new file mode 100644 index 00000000..adaf6180 --- /dev/null +++ b/frontend/src/utils/githubReleaseUrl.ts @@ -0,0 +1,14 @@ +/** + * Build the GitHub release page URL for a given version string. + * + * Version strings already carry their channel suffix (e.g. `3.55.0` + * for stable, `3.55.0-beta.0` for beta). release-please tags every + * release as `vX.Y.Z[-beta.N]`, so a pure string template covers + * both channels without branching on the suffix. + * + * Used by the admin sidebar version display to deep-link to release + * notes for the running version (#566) and by the update-available + * indicator to link to the upgrade target's notes. + */ +export const githubReleaseUrl = (version: string): string => + `https://github.com/the-luap/picpeak/releases/tag/v${version}`;