Na aplikaci je videt, ktery build to je

Nasazena aplikace o dva commity pozadu funguje a vypada skoro stejne jako
nova. Bez oznaceni buildu se to nepozna a hleda se chyba tam, kde zadna
neni - prave to nas dnes stalo pul hodiny hadani, proc je na produkci
porad stary vzhled.

- oznaceni buildu v pate postranniho menu, pod tlacitkem Odhlasit se:
  verze, cas buildu a cislo commitu. Text jde oznacit jednim kliknutim.
- totez jako <meta name="app-build"> v hlavicce stranky. V JS balicku uz to
  je, ale ten se musi stahnout a rozbalit; meta znacka je videt na jeden
  curl bez prihlaseni, a presne to clovek potrebuje pri zjistovani, co bezi
  na produkci.
- hodnoty dosazuje Vite pri buildu (define a plugin build-stamp), takze
  neplati pro repozitar, ale pro ten konkretni balicek.
- .dockerignore uz nevylucuje .git/. Build z nej cte cislo commitu; bez nej
  by se poznal jen cas buildu, ne co v nem je. Do vysledneho image se .git
  nedostane, ten se sklada z ciste zakladni image a kopiruje se do nej jen
  dist, scripts a migrace.

Ve vyvoji se misto casu pise "vyvoj" - cas buildu by tam byl pokazde jiny
a nikomu by nic nerekl.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
JiriUhlir
2026-08-26 10:10:34 +02:00
co-authored by Claude Opus 5
parent 73e0ecca4f
commit 33b4a3fdd6
7 changed files with 195 additions and 3 deletions
@@ -27,6 +27,7 @@ import { EventToasts } from '@/components/dashboard/EventToasts';
import { LiveIndicator } from '@/components/dashboard/LiveIndicator';
import { Logo } from '@/components/layout/Logo';
import { cn } from '@/lib/cn';
import { buildInfo, versionLabel } from '@/config/version';
import { setActiveTenant, useActiveTenant } from '@/lib/tenant';
import { useApiQuery } from '@/lib/useApiQuery';
import type { Access } from '@/types/dashboard';
@@ -247,6 +248,18 @@ function DashboardShell() {
<LogOut className="size-4 shrink-0" />
Odhlásit se
</button>
{/*
Ktera verze zrovna bezi. Bez toho se nasazena aplikace nepozna od
stare: obojí funguje a vypada skoro stejne. Cas je z buildu, ne
z prohlizece.
*/}
<p
className="px-3.5 pt-2 font-mono text-[0.65rem] text-white/25 select-all"
title={`Sestaveno ${buildInfo.builtAt || 've vývoji'}`}
>
{versionLabel()}
</p>
</div>
</aside>
+46
View File
@@ -0,0 +1,46 @@
/**
* Ktera verze zrovna bezi.
*
* Hodnoty dosazuje Vite pri buildu (`define` ve `vite.config.ts`), takze
* neplati pro repozitar, ale **pro tenhle konkretni balicek** - presne to,
* co clovek potrebuje vedet, kdyz se diva na nasazenou aplikaci.
*
* Cas buildu je hlavni udaj: rozliseni na sekundy staci, aby se poznalo, ze
* nasazeni probehlo nebo neprobehlo. Commit je nepovinny, do image se `.git`
* nekopiruje.
*/
const info: { version: string; builtAt: string; commit: string } =
typeof __BUILD_INFO__ === 'undefined'
? { version: '0.0.0', builtAt: '', commit: '' }
: __BUILD_INFO__;
export const buildInfo = info;
/**
* Kratky popis verze pro patu postranniho menu.
*
* Ve vyvoji se cas buildu nepise: mel by tam kazdou minutu jiny a nikomu nic
* nerekne. Na nasazene aplikaci je naopak to hlavni.
*/
export function versionLabel(): string {
const parts = [`v${info.version}`];
if (import.meta.env.DEV) {
parts.push('vývoj');
} else if (info.builtAt) {
parts.push(
new Date(info.builtAt).toLocaleString('cs-CZ', {
day: 'numeric',
month: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
}),
);
}
if (info.commit) parts.push(info.commit);
return parts.join(' · ');
}
+6
View File
@@ -1,6 +1,12 @@
/// <reference types="vite/client" />
declare global {
/**
* Oznaceni buildu dosazene Vitem (`define` ve vite.config.ts).
* Ve vyvoji i v produkci existuje vzdy, jen s jinym obsahem.
*/
const __BUILD_INFO__: { version: string; builtAt: string; commit: string };
interface Window {
/**
* Prefix reverse proxy vlozeny serverem do index.html podle ROOT_PATH.