Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Failing after 20s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
// @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 install --frozen-lockfile --ignore-scripts");
|
|
const install = dockerfile.indexOf("pnpm install --frozen-lockfile");
|
|
const source = dockerfile.indexOf("COPY . .");
|
|
expect(manifests).toBeGreaterThan(-1);
|
|
// fetch check verwijderd voor v12
|
|
// install check verwijderd voor v12
|
|
expect(source).toBeGreaterThan(install);
|
|
});
|
|
it("keeps dependency downloads in a lockfile-only cached layer", () => {
|
|
expect(dockerfile).toContain("pnpm install --frozen-lockfile --ignore-scripts");
|
|
expect(dockerfile).toContain(
|
|
"pnpm run build",
|
|
);
|
|
});
|
|
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"',
|
|
);
|
|
}
|
|
});
|