Files
autofirmer-expanded/lib/version.ts
T
Brandon LiandClaude Fable 5 38a9c6c1b7 Report the running build's version to the master
The version is the checkout's HEAD commit (short hash + commit time),
read once at startup — updates arrive as `git pull`, so there is no
release number to bump. It rides on the socket hello, socket reports,
and the HTTP report fallback; the field is optional in the protocol so
older masters ignore it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-12 18:54:19 -05:00

44 lines
1.6 KiB
TypeScript

/**
* 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;
}
let cached: BuildVersion | null | undefined;
/** 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 (cached !== undefined) return cached;
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(' ');
cached = commit && time ? { commit, time } : null;
} catch {
cached = null;
}
return cached;
}