import { describe, expect, test } from "bun:test"; import { BUILD_RECORD_API_VERSION, BuildStoreConflictError, MemoryBuildStore, type BuildRecord, } from "../../server/build-store"; import { BUILD_PROTOCOL_VERSION, type BuildRequest, type Sha256Digest, } from "../../shared/build-protocol"; const workspace = `sha256:${"a".repeat(64)}` as Sha256Digest; function build(id: string, imageKey = "project\0service\0image"): BuildRecord { const request: BuildRequest = { version: BUILD_PROTOCOL_VERSION, id, project: "project", service: "service", spec: { architecture: "amd64", image: "registry.test/app:latest", context: ".", buildArgs: [], workspace, }, }; const status = { version: BUILD_PROTOCOL_VERSION, id, state: "queued" as const, createdAt: "2026-09-02T00:00:00.000Z", }; return { apiVersion: BUILD_RECORD_API_VERSION, kind: "BuildRecord", metadata: { name: id, resourceVersion: "1", creationTimestamp: status.createdAt, labels: {}, }, spec: { request, imageKey, jobName: `job-${id}`, workspaceSubPath: id }, status: { ...status, logBytes: 0, logOffset: 0, nextSequence: 1, events: [{ type: "status", status }], }, }; } describe("build store", () => { test("atomically enforces idempotency and one active image build", async () => { const store = new MemoryBuildStore(); expect((await store.createBuild(build("one"))).created).toBe(true); expect((await store.createBuild(build("one"))).created).toBe(false); await expect( store.createBuild(build("one", "different-key")), ).rejects.toBeInstanceOf(BuildStoreConflictError); await expect(store.createBuild(build("two"))).rejects.toBeInstanceOf( BuildStoreConflictError, ); const first = (await store.getBuild("one"))!; const digest = `sha256:${"b".repeat(64)}` as Sha256Digest; first.metadata.resourceVersion = "2"; Object.assign(first.status, { state: "succeeded", digest, finishedAt: first.status.createdAt, }); await store.replaceBuild(first, "1"); expect((await store.createBuild(build("two"))).created).toBe(true); const changed = (await store.getBuild("one"))!; changed.metadata.resourceVersion = "3"; changed.status.digest = `sha256:${"c".repeat(64)}`; await expect(store.replaceBuild(changed, "2")).rejects.toThrow("immutable"); }); test("optimistically updates resumable upload records without leaking mutable data", async () => { const store = new MemoryBuildStore(); const digest = `sha256:${"d".repeat(64)}` as Sha256Digest; const upload = { apiVersion: BUILD_RECORD_API_VERSION, kind: "BuildUpload" as const, metadata: { name: "upload", resourceVersion: "1", creationTimestamp: "now", }, spec: { digest, size: 3 }, status: { offset: 0, data: new Uint8Array() }, }; await store.createUpload(upload); upload.status.data = Buffer.from("mutated"); expect((await store.getUpload(digest))?.status.data.byteLength).toBe(0); const next = (await store.getUpload(digest))!; next.metadata.resourceVersion = "2"; next.status = { offset: 3, data: Buffer.from("abc") }; await store.replaceUpload(next, "1"); await expect(store.replaceUpload(next, "1")).rejects.toBeInstanceOf( BuildStoreConflictError, ); }); });