Some checks failed
Build pull request / Build pull request (pull_request) Has been cancelled
Soul found: explicit sha stamped clean over a different HEAD; status failure returned the bare explicit sha; an archive inside another repo got that repo's verdict; the temp regex let any untracked .mjs pass. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
56 lines
2.6 KiB
JavaScript
56 lines
2.6 KiB
JavaScript
// The commit a bundle was built from, stamped into its index.html as <meta name="build-sha">, so a built
|
|
// folder says what it is without a build log: `grep -o 'build-sha" content="[^"]*' dist/index.html`.
|
|
// Where git governs the tree (REPO_DIR is a repository root) git decides: HEAD, suffixed -dirty when the tree has
|
|
// uncommitted changes, or `<BUILD_SHA>-mismatch` when an explicit BUILD_SHA names a different commit, so a stamp
|
|
// never vouches for code it does not hold; a git failure there is 'unknown'. Where git does not govern (a source
|
|
// archive), a full-sha BUILD_SHA stands, else 'unknown'.
|
|
import { execFileSync } from 'child_process';
|
|
import { dirname, resolve } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const REPO_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
|
// Vite writes vite.config.js.timestamp-*.mjs next to the config while it loads it; that file is the
|
|
// build's own, not source, so an UNTRACKED one must not mark the tree dirty. A tracked file of that name,
|
|
// or any other change, still does. Filtering status lines (not a pathspec) is what keeps it untracked-only.
|
|
const VITE_TEMP = /^\?\? (?:.*\/)?vite\.config\.[a-z]+\.timestamp-\d+-[0-9a-f]+\.mjs$/;
|
|
|
|
export const gitIn =
|
|
(cwd) =>
|
|
(...args) =>
|
|
execFileSync('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
|
|
const FULL_SHA = /^[0-9a-f]{40}$/;
|
|
|
|
export const readBuildSha = (env = process.env, run = gitIn(REPO_DIR)) => {
|
|
const fromEnv = (env.BUILD_SHA ?? '').trim();
|
|
const explicit = FULL_SHA.test(fromEnv) ? fromEnv : null;
|
|
// Git governs this tree only when REPO_DIR is its root: a source archive unpacked inside some other
|
|
// repository has no git of its own, and that repository's HEAD says nothing about it.
|
|
let governed;
|
|
try {
|
|
governed = run('rev-parse', '--show-prefix').trim() === '';
|
|
} catch {
|
|
governed = false;
|
|
}
|
|
if (!governed) return explicit ?? 'unknown';
|
|
// Git governs and answers: from here a failure is 'unknown', never the bare explicit sha.
|
|
try {
|
|
const head = run('rev-parse', 'HEAD').trim();
|
|
if (!FULL_SHA.test(head)) return 'unknown';
|
|
if (explicit && explicit !== head) return `${explicit}-mismatch`;
|
|
const dirty = run('status', '--porcelain', '-uall', '--', '.')
|
|
.split('\n')
|
|
.some((l) => l.trim() !== '' && !VITE_TEMP.test(l));
|
|
return dirty ? `${head}-dirty` : head;
|
|
} catch {
|
|
return 'unknown';
|
|
}
|
|
};
|
|
|
|
export const buildShaPlugin = (sha = readBuildSha()) => ({
|
|
name: 'ratatoskr-build-sha',
|
|
transformIndexHtml: () => [
|
|
{ tag: 'meta', attrs: { name: 'build-sha', content: sha }, injectTo: 'head-prepend' },
|
|
],
|
|
});
|