import { describe, expect, test } from "bun:test"; import { createBuildJob } from "../../server/build-job"; import type { BuildSpec } from "../../shared/build-protocol"; function spec(architecture: "arm64" | "amd64"): BuildSpec { return { architecture, image: "registry.example.com/kuber/demo-web:latest", context: "apps/web", dockerfile: "docker/Web.Dockerfile", target: "production", buildArgs: ["NODE_ENV=production"], workspace: `sha256:${"a".repeat(64)}`, }; } describe("BuildKit Job generation", () => { test.each(["arm64", "amd64"] as const)( "generates a rootless %s job", (architecture) => { const job = createBuildJob({ name: `build-${architecture}`, namespace: "kuber-system", spec: spec(architecture), workspaceClaimName: "build-workspaces", workspaceSubPath: "snapshot", cacheImage: "registry.example.com/cache/demo-web", registrySecretName: "registry-auth", nodeSelector: { "kubernetes.io/arch": "wrong", pool: "builders" }, }); const jobSpec = job.spec as any; const pod = jobSpec.template.spec; const container = pod.containers[0]; expect(pod.nodeSelector["kubernetes.io/arch"]).toBe(architecture); expect(pod.nodeSelector.pool).toBe("builders"); expect(pod.automountServiceAccountToken).toBe(false); expect(pod.securityContext).toMatchObject({ runAsNonRoot: true, runAsUser: 1000, seccompProfile: { type: "Unconfined" }, }); expect(container.securityContext).toEqual({ runAsNonRoot: true, runAsUser: 1000, allowPrivilegeEscalation: true, seccompProfile: { type: "Unconfined" }, appArmorProfile: { type: "Unconfined" }, }); expect(container.env).toContainEqual({ name: "BUILDKITD_FLAGS", value: "--oci-worker-no-process-sandbox", }); expect(container.args).toContain(`--opt=platform=linux/${architecture}`); expect(container.args).toContain( "--import-cache=type=registry,ref=registry.example.com/cache/demo-web", ); expect(container.args).toContain( "--export-cache=type=registry,ref=registry.example.com/cache/demo-web,mode=max", ); expect(container.args).toContain( "--output=type=image,name=registry.example.com/kuber/demo-web:latest,push=true", ); expect(container.volumeMounts).toContainEqual({ name: "workspace", mountPath: "/workspace", readOnly: true, subPath: "snapshot", }); expect(pod.volumes).toContainEqual({ name: "registry-auth", secret: { secretName: "registry-auth", items: [{ key: ".dockerconfigjson", path: "config.json" }], }, }); expect( jobSpec.template.metadata.annotations[ "container.apparmor.security.beta.kubernetes.io/buildkit" ], ).toBe("unconfined"); }, ); test("uses pushImage for output when set", () => { const job = createBuildJob({ name: "build-push", namespace: "default", spec: spec("amd64"), workspaceClaimName: "workspace", cacheImage: "registry.example.com/cache/demo-web", pushImage: "internal.registry:5000/kuber/demo-web:latest", }); const container = (job.spec as any).template.spec.containers[0]; expect(container.args).toContain( "--output=type=image,name=internal.registry:5000/kuber/demo-web:latest,push=true", ); expect(container.args).not.toContainEqual( expect.stringContaining("--output=type=image,name=registry.example.com"), ); }); test("adds insecure flags when configured", () => { const job = createBuildJob({ name: "build-insecure", namespace: "default", spec: spec("amd64"), workspaceClaimName: "workspace", cacheImage: "internal.registry:5000/cache/demo-web", pushImage: "internal.registry:5000/kuber/demo-web:latest", pushRegistryInsecure: true, cacheRegistryInsecure: true, }); const container = (job.spec as any).template.spec.containers[0]; expect(container.args).toContain( "--import-cache=type=registry,ref=internal.registry:5000/cache/demo-web,registry.insecure=true", ); expect(container.args).toContain( "--export-cache=type=registry,ref=internal.registry:5000/cache/demo-web,mode=max,registry.insecure=true", ); expect(container.args).toContain( "--output=type=image,name=internal.registry:5000/kuber/demo-web:latest,push=true,registry.insecure=true", ); }); test("no insecure flags when not configured", () => { const job = createBuildJob({ name: "build-secure", namespace: "default", spec: spec("amd64"), workspaceClaimName: "workspace", cacheImage: "registry.example.com/cache/demo-web", }); const container = (job.spec as any).template.spec.containers[0]; for (const arg of container.args) { expect(arg).not.toContain("registry.insecure"); } }); test("rejects traversal and invalid Kubernetes names", () => { expect(() => createBuildJob({ name: "Invalid_Name", namespace: "default", spec: spec("arm64"), workspaceClaimName: "workspace", cacheImage: "cache", }), ).toThrow("DNS label"); expect(() => createBuildJob({ name: "valid", namespace: "default", spec: { ...spec("arm64"), context: "../outside" }, workspaceClaimName: "workspace", cacheImage: "cache", }), ).toThrow("safe workspace-relative"); expect(() => createBuildJob({ name: "valid", namespace: "default", spec: spec("arm64"), workspaceClaimName: "workspace", workspaceSubPath: "../outside", cacheImage: "cache", }), ).toThrow("Workspace subPath"); }); });