fix(web): show semver on monitoring from legacy /v1/version
CI / changes (push) Successful in 7s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Failing after 35s
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / release (push) Has been skipped
CI / changes (push) Successful in 7s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Failing after 35s
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / release (push) Has been skipped
На проде API отдаёт только api_version и git_sha=unknown без поля version; карточка показывала SHA вместо semver. Общий хелпер version-info.ts: version → api_version, placeholder SHA не в заголовке. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/** Ответ GET /v1/version (см. docs/openapi.yaml VersionInfo). */
|
||||
export type VersionInfo = {
|
||||
version?: string;
|
||||
api_version?: string;
|
||||
git_sha?: string;
|
||||
build_time?: string;
|
||||
};
|
||||
|
||||
const PLACEHOLDER_SHA = new Set(['', 'unknown']);
|
||||
|
||||
function nonEmptyString(value: unknown): string {
|
||||
if (typeof value === 'string') {
|
||||
const s = value.trim();
|
||||
return s;
|
||||
}
|
||||
if (value == null) return '';
|
||||
return String(value).trim();
|
||||
}
|
||||
|
||||
/** Semver или legacy api_version; пустая строка, если полей нет. */
|
||||
export function resolveVersionString(info: VersionInfo | null | undefined): string {
|
||||
if (!info) return '';
|
||||
return nonEmptyString(info.version) || nonEmptyString(info.api_version);
|
||||
}
|
||||
|
||||
/** Короткий git SHA; пусто для placeholder «unknown». */
|
||||
export function resolveGitSha(info: VersionInfo | null | undefined): string {
|
||||
if (!info) return '';
|
||||
const sha = nonEmptyString(info.git_sha);
|
||||
if (!sha || PLACEHOLDER_SHA.has(sha.toLowerCase())) return '';
|
||||
return sha;
|
||||
}
|
||||
|
||||
/** Заголовок карточки «Версия» на /monitoring. */
|
||||
export function formatVersionHeadline(info: VersionInfo | null | undefined): string {
|
||||
if (!info) return '—';
|
||||
const ver = resolveVersionString(info);
|
||||
const sha = resolveGitSha(info);
|
||||
if (ver && sha) return `${ver} (${sha.slice(0, 12)})`;
|
||||
if (ver) return ver;
|
||||
if (sha) return sha.slice(0, 12);
|
||||
return '—';
|
||||
}
|
||||
|
||||
/** Подпись в сайдбаре (v1.2.3). */
|
||||
export function formatVersionSidebarLabel(info: VersionInfo | null | undefined): string | null {
|
||||
const ver = resolveVersionString(info);
|
||||
return ver ? `v${ver}` : null;
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { apiJSON } from '$lib/api/client.js';
|
||||
|
||||
type VersionInfo = {
|
||||
version?: string;
|
||||
api_version?: string;
|
||||
};
|
||||
import {
|
||||
formatVersionSidebarLabel,
|
||||
type VersionInfo
|
||||
} from '$lib/api/version-info.js';
|
||||
|
||||
let label = $state<string | null>(null);
|
||||
|
||||
@@ -13,11 +12,7 @@
|
||||
void (async () => {
|
||||
try {
|
||||
const info = await apiJSON<VersionInfo>('/v1/version');
|
||||
const ver =
|
||||
(typeof info.version === 'string' && info.version) ||
|
||||
(typeof info.api_version === 'string' && info.api_version) ||
|
||||
'';
|
||||
label = ver ? `v${ver}` : null;
|
||||
label = formatVersionSidebarLabel(info);
|
||||
} catch {
|
||||
label = null;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { apiJSON, apiFetch } from '$lib/api/client.js';
|
||||
import type { BirdStatus, JobsResponse } from '$lib/api/types.js';
|
||||
import {
|
||||
formatVersionHeadline,
|
||||
resolveVersionString,
|
||||
type VersionInfo
|
||||
} from '$lib/api/version-info.js';
|
||||
import { Badge } from '$lib/components/ui/badge/index.js';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import {
|
||||
@@ -21,12 +26,6 @@
|
||||
import PageHeader from '$lib/ui/app/page-header/page-header.svelte';
|
||||
|
||||
type ReadyStatus = { status: string; checks?: Record<string, unknown> };
|
||||
type VersionInfo = {
|
||||
version?: string;
|
||||
git_sha?: string;
|
||||
build_time?: string;
|
||||
[k: string]: unknown;
|
||||
};
|
||||
type JobsKpi = { running: number; failed: number; total: number };
|
||||
|
||||
let health = $state<{ ok: boolean; status?: string; error?: string } | null>(null);
|
||||
@@ -98,16 +97,16 @@
|
||||
return `${bird.bgp_established}/${bird.bgp_sessions_total}`;
|
||||
});
|
||||
|
||||
const versionText = $derived.by(() => {
|
||||
if (!version) return '—';
|
||||
const ver =
|
||||
(typeof version.version === 'string' && version.version) ||
|
||||
(typeof version.api_version === 'string' && version.api_version) ||
|
||||
'';
|
||||
const sha =
|
||||
typeof version.git_sha === 'string' && version.git_sha ? version.git_sha : 'unknown';
|
||||
if (ver) return `${ver} (${sha.slice(0, 12)})`;
|
||||
return sha.slice(0, 12);
|
||||
const versionText = $derived(formatVersionHeadline(version));
|
||||
|
||||
const versionFooter = $derived.by(() => {
|
||||
if (!version) return '';
|
||||
const parts: string[] = [];
|
||||
const ver = resolveVersionString(version);
|
||||
if (ver) parts.push(`version: ${ver}`);
|
||||
if (version.git_sha) parts.push(`git_sha: ${version.git_sha}`);
|
||||
if (version.build_time) parts.push(`build: ${version.build_time}`);
|
||||
return parts.join(' · ');
|
||||
});
|
||||
|
||||
async function load() {
|
||||
@@ -263,10 +262,8 @@
|
||||
</div>
|
||||
{#if versionError}
|
||||
<p class="mt-2 text-xs text-destructive">{versionError}</p>
|
||||
{:else if version}
|
||||
<p class="mt-2 truncate text-xs text-muted-foreground">
|
||||
api_version: {String(version.api_version ?? 'unknown')}
|
||||
</p>
|
||||
{:else if versionFooter}
|
||||
<p class="mt-2 truncate text-xs text-muted-foreground">{versionFooter}</p>
|
||||
{/if}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user