import { readFile } from "node:fs/promises"; import { describe, expect, it } from "vitest"; async function repositoryFile(path: string): Promise { return readFile(new URL(`../${path}`, import.meta.url), "utf8"); } describe("production deployment contract", () => { it("defines a resilient two-replica web workload", async () => { const deployment = await repositoryFile("k8s/base/deployment.yaml"); expect(deployment).toContain("replicas: 2"); expect(deployment).toContain("maxSurge: 1"); expect(deployment).toContain("maxUnavailable: 0"); expect(deployment).toContain("path: /api/health?ready=1"); expect(deployment).toContain("path: /api/health"); expect(deployment).toContain("kubernetes.io/arch: arm64"); expect(deployment).toMatch( /requests:\s+cpu: 500m\s+memory: 1Gi\s+limits:\s+cpu: "1"\s+memory: 2Gi/u, ); expect(deployment).toContain("runAsNonRoot: true"); expect(deployment).toContain("runAsUser: 1000"); expect(deployment).toContain("runAsGroup: 1000"); expect(deployment).toContain("readOnlyRootFilesystem: true"); expect(deployment).toContain('drop: ["ALL"]'); }); it("exposes only the app through the requested edge-TLS host", async () => { const [service, ingress] = await Promise.all([ repositoryFile("k8s/base/service.yaml"), repositoryFile("k8s/base/ingress.yaml"), ]); expect(service).toContain("type: ClusterIP"); expect(service).toContain("port: 3000"); expect(service).toContain("targetPort: http"); expect(ingress).toContain("ingressClassName: traefik"); expect(ingress).toContain("host: guide.sudloh.com"); expect(ingress).toContain( 'traefik.ingress.kubernetes.io/read-timeout: "200"', ); expect(ingress).not.toContain("secretName:"); expect(ingress).not.toContain("router.tls"); }); it("keeps availability and scaling bounds explicit", async () => { const [hpa, pdb] = await Promise.all([ repositoryFile("k8s/base/hpa.yaml"), repositoryFile("k8s/base/pdb.yaml"), ]); expect(hpa).toContain("minReplicas: 2"); expect(hpa).toContain("maxReplicas: 6"); expect(hpa).toContain("averageUtilization: 70"); expect(hpa).toContain("name: memory"); expect(hpa).toContain("averageUtilization: 75"); expect(pdb).toContain("minAvailable: 1"); }); it("uses externally supplied secrets and does not provision data stores", async () => { const manifestPaths = [ "k8s/base/namespace.yaml", "k8s/base/configmap.yaml", "k8s/base/deployment.yaml", "k8s/base/worker-deployment.yaml", "k8s/base/discord-worker-deployment.yaml", "k8s/base/service.yaml", "k8s/base/ingress.yaml", "k8s/base/hpa.yaml", "k8s/base/pdb.yaml", "k8s/base/ci-rbac.yaml", "k8s/migration/job.yaml", ]; const manifests = ( await Promise.all(manifestPaths.map(repositoryFile)) ).join("\n---\n"); expect(manifests).toContain("name: buzz-sheet-env"); expect(manifests).not.toMatch(/kind: (Secret|StatefulSet|PersistentVolumeClaim)/u); expect(manifests).not.toContain("resources: [\"secrets\"]"); expect(manifests).not.toContain("kind: ClusterRole"); expect(manifests).not.toContain("kind: ClusterRoleBinding"); }); it("packages non-root Bun application and migration targets", async () => { const dockerfile = await repositoryFile("Dockerfile"); expect(dockerfile).toContain("FROM dependencies AS migration"); expect(dockerfile).toContain("FROM oven/bun:${BUN_VERSION} AS app"); expect(dockerfile.match(/^USER 1000:1000$/gmu)).toHaveLength(2); expect(dockerfile).toContain('ENTRYPOINT ["bun", "scripts/migrate.ts"]'); expect(dockerfile).toContain('CMD ["bun", "server.js"]'); expect(dockerfile).toContain("backend/discord.ts"); expect(dockerfile).toContain("./worker/discord.js"); }); it("verifies first, publishes immutable images, and migrates before rollout", async () => { const workflow = await repositoryFile(".gitea/workflows/ci.yml"); expect(workflow).toContain("bun install --frozen-lockfile"); expect(workflow).toContain("bun run test"); expect(workflow).toContain("bun run typecheck"); expect(workflow).toContain("bun run lint"); expect(workflow).toContain("kubectl kustomize k8s/"); expect(workflow).toContain("--target app"); expect(workflow).toContain("--target migration"); expect(workflow).not.toContain("platforms: linux/arm64"); expect(workflow).not.toMatch(/docker\/setup-qemu-action|docker\/setup-buildx-action|docker\/login-action/iu); expect(workflow).toContain( "registry.neko-piranha.ts.net/astral/buzz-sheet", ); expect(workflow).toContain("migrate-${{ gitea.sha }}"); expect(workflow).toContain("deployment/buzz-sheet-discord-worker"); const deleteMigrationJob = workflow.indexOf( 'delete job buzz-sheet-migrate --ignore-not-found', ); const createMigrationJob = workflow.indexOf( 'create --validate=false -f "$migration_manifest"', ); expect(deleteMigrationJob).toBeGreaterThan(-1); expect(deleteMigrationJob).toBeLessThan(createMigrationJob); expect(workflow.indexOf("condition=complete")).toBeLessThan( workflow.indexOf("set image"), ); expect(workflow).not.toMatch(/playwright|chromium/iu); }); it("mounts the deployment stream and offers a full reload for new releases", async () => { const [layout, notifier, route] = await Promise.all([ repositoryFile("app/layout.tsx"), repositoryFile("components/deployment-update-notifier.tsx"), repositoryFile("app/api/active/route.ts"), ]); expect(layout).toContain(" { it("documents every externally supplied production secret", async () => { const environmentExample = await repositoryFile(".env.example"); const requiredKeys = [ "DATABASE_URL", "BETTER_AUTH_URL", "BETTER_AUTH_SECRET", "REDIS_URL", "S3_ENDPOINT", "S3_BUCKET", "S3_ACCESS_KEY_ID", "S3_SECRET_ACCESS_KEY", "NEXT_SERVER_ACTIONS_ENCRYPTION_KEY", "NEXT_DEPLOYMENT_ID", "DISCORD_BOT_TOKEN", "DISCORD_CHANNEL_ID", "DISCORD_LOG_CHANNEL_ID", ]; for (const key of requiredKeys) { expect(environmentExample).toMatch(new RegExp(`^${key}=`, "mu")); } expect(environmentExample).toContain("BUZZ_DEMO_MODE=false"); }); it("runs Discord catalog sync as an isolated worker", async () => { const [deployment, rbac] = await Promise.all([ repositoryFile("k8s/base/discord-worker-deployment.yaml"), repositoryFile("k8s/base/ci-rbac.yaml"), ]); expect(deployment).toContain("name: buzz-sheet-discord-worker"); expect(deployment).toContain("type: Recreate"); expect(deployment).toContain('command: ["bun", "worker/discord.js"]'); expect(deployment).toContain("replicas: 1"); expect(deployment).toContain("readOnlyRootFilesystem: true"); expect(deployment).toContain('drop: ["ALL"]'); expect(rbac).toContain("buzz-sheet-discord-worker"); }); it("syncs only for new Discord version announcements", async () => { const worker = await repositoryFile("backend/discord.ts"); expect(worker).toContain("client.on(Events.MessageCreate, handleMessage)"); expect(worker).not.toContain("channel.messages.fetch"); expect(worker).not.toContain('source: "history"'); }); });