// @ts-nocheck import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; const dockerfile = readFileSync("Dockerfile", "utf8"); describe("Docker build cache", () => { it("installs frozen dependencies before copying application source", () => { const manifests = dockerfile.indexOf( "COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml* .npmrc* ./", ); const fetch = dockerfile.indexOf("pnpm fetch --ignore-scripts"); const install = dockerfile.indexOf("pnpm install --frozen-lockfile"); const source = dockerfile.indexOf("COPY . ."); expect(manifests).toBeGreaterThan(-1); expect(fetch).toBeGreaterThan(manifests); expect(install).toBeGreaterThan(fetch); expect(source).toBeGreaterThan(install); }); it("keeps dependency downloads in a lockfile-only cached layer", () => { expect(dockerfile).toContain("pnpm fetch --ignore-scripts"); expect(dockerfile).toContain( "pnpm install --frozen-lockfile --ignore-scripts --offline", ); }); it("ships standalone output without a redundant dependency pruning step", () => { expect(dockerfile).toContain("/app/.next/standalone ./"); expect(dockerfile).not.toContain("pnpm prune --prod"); expect(dockerfile).not.toContain("npm prune --production"); expect(dockerfile).not.toContain("yarn install --production"); }); }); it("passes a compiled release to both the application build and final image", () => { expect(dockerfile.indexOf("ARG NEXT_DEPLOYMENT_ID")).toBeGreaterThan( dockerfile.indexOf("COPY . ."), ); expect(dockerfile).toContain( 'LABEL org.opencontainers.image.revision="$NEXT_DEPLOYMENT_ID"', ); const pinnedNode = readFileSync(".nvmrc", "utf8").trim(); expect(dockerfile.split(`FROM node:${pinnedNode}-alpine`).length - 1).toBe(2); const compose = readFileSync("docker-compose.yml", "utf8"); // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose interpolation, not JavaScript. expect(compose).toContain("NEXT_DEPLOYMENT_ID: ${CMS_RELEASE:-unknown}"); }); it("builds with fixtures and excludes installation secrets from every stage", () => { const ignored = readFileSync(".dockerignore", "utf8"); expect(ignored).toMatch(/^\.env$/m); expect(ignored).toMatch(/^\.env\.\*$/m); expect(dockerfile).toContain("FROM migrations AS builder"); expect(dockerfile).toContain('HOTEL_NAME="Build fixture"'); expect(dockerfile).not.toMatch( /^ENV.*(?:AUTH_SECRET|DATABASE_URL|HOTEL_NAME)/m, ); expect(dockerfile).toContain('CMD ["node", "docker-start.mjs"]'); const updater = readFileSync("scripts/docker-update.sh", "utf8"); expect(updater).toContain("target=/app/.env,readonly"); expect(updater).toContain("--target migrations"); }); it("does not reference a container publication script", () => { expect(() => readFileSync("scripts/publish-container.sh", "utf8")).toThrow(); }); it("does not prerender installation metadata into a shared image", () => { for (const path of [ "src/app/robots.ts", "src/app/sitemap.ts", "src/app/manifest.ts", ]) { expect(readFileSync(path, "utf8")).toContain( 'export const dynamic = "force-dynamic"', ); } });