/** * The version of the running build. * * Updates arrive as `git pull` (scripts/update-check.mjs), so the checkout's * HEAD commit *is* the version — there is no release number to bump and * nothing for anyone to forget. The commit time rides along because hashes * don't order: it is what lets the master say which of two different * versions is the stale one. * * Read once and cached: the update task restarts the process after every * pull, so HEAD cannot move under a running build — and when it briefly does * (pull landed, restart pending), the cached value still describes the code * that is actually executing. */ import { execFileSync } from 'node:child_process'; export interface BuildVersion { /** Short commit hash of HEAD, e.g. "c493796". */ commit: string; /** ISO commit time of HEAD — orders versions, which hashes cannot. */ time: string; } // Per process, not per bundle: instrumentation.ts and the route handlers load // their own copies of this module, and each would otherwise read HEAD at its own // first call — after an update's pull, a late first call reports code that isn't // running yet. const _g = globalThis as typeof globalThis & { __buildVersion?: BuildVersion | null }; /** null when this isn't a git checkout or git isn't installed — both mean * "no version to report", and the master shows the machine as an old build. */ export function getBuildVersion(): BuildVersion | null { if (_g.__buildVersion !== undefined) return _g.__buildVersion; try { const out = execFileSync('git', ['log', '-1', '--format=%h %cI'], { cwd: process.cwd(), encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], }).trim(); const [commit, time] = out.split(' '); _g.__buildVersion = commit && time ? { commit, time } : null; } catch { _g.__buildVersion = null; } return _g.__buildVersion; }