import { inject, injectable } from "@codemation/core"; import type { AppConfig } from "../presentation/config/AppConfig"; import { ApplicationTokens } from "../applicationTokens"; import type { ProcessRunner } from "../process/ProcessRunner.types"; @injectable() export class ServedCommitShaReader { private cached: Promise | undefined; constructor( @inject(ApplicationTokens.AppConfig) private readonly appConfig: AppConfig, @inject(ApplicationTokens.ProcessRunner) private readonly processRunner: ProcessRunner, ) {} async read(): Promise { this.cached ??= this.resolveSha(); return this.cached; } private resolveSha(): Promise { const fromEnv = this.appConfig.env.CODEMATION_COMMIT_SHA?.trim(); if (fromEnv) { return Promise.resolve(fromEnv); } return this.readFromGit(); } private readFromGit(): Promise { let child; try { child = this.processRunner.spawn("git", ["rev-parse", "HEAD"], { cwd: this.appConfig.consumerRoot, stdio: ["ignore", "pipe", "pipe"], }); } catch { return Promise.resolve(null); } return new Promise((resolve) => { let stdout = ""; child.stdout?.on("data", (chunk: Buffer | string) => { stdout += chunk.toString(); }); child.once("error", () => { resolve(null); }); child.once("close", (exitCode) => { if (exitCode === 0) { resolve(stdout.trim() || null); } else { resolve(null); } }); }); } }