import { spawnSync } from "child_process";
import { existsSync } from "fs";
import { join } from "path";
export interface BuildInfo {
sha: string;
shaFull: string;
branch: string;
builtAt: string;
uptimeMs: number;
}
const STARTED_AT = Date.now();
let _cached: Omit<BuildInfo, "uptimeMs"> | null = null;
function read(): Omit<BuildInfo, "uptimeMs"> {
if (_cached) return _cached;
const envSha = process.env.GIT_SHA?.trim();
const envBranch = process.env.GIT_BRANCH?.trim();
if (envSha) {
_cached = {
sha: envSha.slice(0, 7),
shaFull: envSha,
branch: envBranch || "main",
builtAt: new Date(STARTED_AT).toISOString(),
};
return _cached;
}
const cwd = process.cwd();
const hasGit = existsSync(join(cwd, ".git"));
if (!hasGit) {
_cached = {
sha: "unknown",
shaFull: "unknown",
branch: "unknown",
builtAt: new Date(STARTED_AT).toISOString(),
};
return _cached;
}
try {
const sha = spawnSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" });
const branch = spawnSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd, encoding: "utf8" });
const shaFull = (sha.stdout || "").trim();
_cached = {
sha: shaFull.slice(0, 7) || "unknown",
shaFull: shaFull || "unknown",
branch: (branch.stdout || "").trim() || "main",
builtAt: new Date(STARTED_AT).toISOString(),
};
} catch {
_cached = {
sha: "unknown",
shaFull: "unknown",
branch: "unknown",
builtAt: new Date(STARTED_AT).toISOString(),
};
}
return _cached;
}
export function getBuildInfo(): BuildInfo {
const base = read();
return {
...base,
uptimeMs: Date.now() - STARTED_AT,
};
}
|