import { execSync } from "node:child_process"; import { createHash } from "node:crypto"; import { existsSync, readFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", ".."); describe("build manifest", () => { it("writes dist/.build-manifest.json with sourceSha, bundleSha256, builtAt", () => { const manifestPath = resolve(repoRoot, "dist/.build-manifest.json"); if (!existsSync(manifestPath)) { // Only build if manifest is missing (isolated test run). In CI turbo // already runs build before test, so this is skipped — avoiding a // race with the structural skill-baseline integrity test. execSync("pnpm run build", { stdio: "inherit", cwd: repoRoot }); } expect(existsSync(manifestPath)).toBe(true); const manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as { sourceSha: string; bundleSha256: string; builtAt: string; }; // sourceSha: a valid 40-char hex git sha (may differ from HEAD when // the build was cached by turbo from an earlier commit) expect(manifest.sourceSha).toMatch(/^[0-9a-f]{40}$/); // bundleSha256: matches sha256 of dist/cli/index.js const bundle = readFileSync(resolve(repoRoot, "dist/cli/index.js")); const expectedBundleSha = createHash("sha256").update(bundle).digest("hex"); expect(manifest.bundleSha256).toBe(expectedBundleSha); // builtAt: ISO-8601 timestamp parseable as a Date expect(() => new Date(manifest.builtAt).toISOString()).not.toThrow(); expect(manifest.builtAt).toMatch(/^\d{4}-\d{2}-\d{2}T/); }); });