fix(ui): make source builds deterministic (#121433)

This commit is contained in:
Peter Steinberger
2026-08-09 22:58:57 -07:00
committed by GitHub
parent b8f861364c
commit deb63f9db3
2 changed files with 25 additions and 33 deletions
+16 -17
View File
@@ -78,26 +78,28 @@ describe("Control UI Vite config", () => {
expect(readGitCommitTimestamp).toHaveBeenCalledWith("0123456789abcdef0123456789abcdef01234567");
});
it("falls back to Git and the current UTC time only when inputs are absent", () => {
expect(
resolveControlUiBuildInfo({
env: {},
now: () => new Date("2026-07-10T13:14:15.000Z"),
readGitCommit: () => "a".repeat(40),
readGitCommitTimestamp: () => null,
readGitBranch: () => null,
readGitDirty: () => null,
readPackageVersion: () => null,
}),
).toEqual({
it("keeps source-build identity stable when no build timestamp is provided", () => {
const sources = {
env: {},
readGitCommit: () => "a".repeat(40),
readGitCommitTimestamp: () => null,
readGitBranch: () => null,
readGitDirty: () => null,
readPackageVersion: () => null,
};
const first = resolveControlUiBuildInfo(sources);
const second = resolveControlUiBuildInfo(sources);
expect(first).toEqual(second);
expect(first).toEqual({
version: null,
commit: "a".repeat(40),
commitAt: null,
builtAt: "2026-07-10T13:14:15.000Z",
builtAt: null,
branch: null,
dirty: null,
release: false,
buildId: "aaaaaaaaaaaa-2026-07-10T13-14-15.000Z",
buildId: "aaaaaaaaaaaa",
});
});
@@ -182,7 +184,6 @@ describe("Control UI Vite config", () => {
expect(
resolveControlUiBuildInfo({
env: { GITHUB_SHA: "b".repeat(40) },
now: () => new Date("2026-07-10T13:14:15.000Z"),
readGitCommit,
readPackageVersion: () => null,
}),
@@ -191,7 +192,6 @@ describe("Control UI Vite config", () => {
expect(
resolveControlUiBuildInfo({
env: { GITHUB_SHA: "b".repeat(40) },
now: () => new Date("2026-07-10T13:14:15.000Z"),
readGitCommit: () => null,
readPackageVersion: () => null,
}).commit,
@@ -210,7 +210,6 @@ describe("Control UI Vite config", () => {
expect(
resolveControlUiBuildInfo({
env: { GIT_SHA: "A".repeat(40), GITHUB_SHA: "b".repeat(40) },
now: () => new Date("2026-07-10T13:14:15.000Z"),
readGitCommit,
readPackageVersion: () => null,
}).commit,
+9 -16
View File
@@ -151,7 +151,6 @@ function readGitDirty(): boolean | null {
type ControlUiBuildInfoSources = {
env?: NodeJS.ProcessEnv;
now?: () => Date;
readPackageVersion?: () => string | null;
readGitCommit?: () => string | null;
readGitCommitTimestamp?: (commit: string) => string | null;
@@ -159,19 +158,16 @@ type ControlUiBuildInfoSources = {
readGitDirty?: () => boolean | null;
};
function normalizeBuildTimestamp(value: string | undefined, now: () => Date): string | null {
function normalizeBuildTimestamp(value: string | undefined): string | null {
const explicit = value?.trim();
if (explicit) {
const timestamp = normalizeControlUiBuildInfo({ builtAt: explicit }).builtAt;
if (!timestamp) {
throw new Error(
"OPENCLAW_BUILD_TIMESTAMP must be a valid UTC ISO-8601 timestamp ending in Z",
);
}
return timestamp;
if (!explicit) {
return null;
}
const candidate = now();
return Number.isNaN(candidate.getTime()) ? null : candidate.toISOString();
const timestamp = normalizeControlUiBuildInfo({ builtAt: explicit }).builtAt;
if (!timestamp) {
throw new Error("OPENCLAW_BUILD_TIMESTAMP must be a valid UTC ISO-8601 timestamp ending in Z");
}
return timestamp;
}
export function resolveControlUiBuildInfo(
@@ -215,10 +211,7 @@ export function resolveControlUiBuildInfo(
commitAt: readCommitTimestamp(commit),
}).commitAt
: null;
const builtAt = normalizeBuildTimestamp(
env.OPENCLAW_BUILD_TIMESTAMP,
sources.now ?? (() => new Date()),
);
const builtAt = normalizeBuildTimestamp(env.OPENCLAW_BUILD_TIMESTAMP);
// Branch/dirty identity is advisory: the readers return null instead of
// throwing, so malformed environment or Git state never blocks a build.
// Tags must not be presented as branches in GitHub-built artifacts.