import { readFile } from "node:fs/promises"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; import { parse } from "yaml"; interface ComposeService { environment?: Record; healthcheck?: unknown; image?: string; ports?: string[]; volumes?: string[]; } interface ComposeDocument { services?: Record; volumes?: Record; } interface PackageDocument { scripts?: Record; } interface WorkflowJob { needs?: string; steps?: WorkflowStep[]; "timeout-minutes"?: number; } interface WorkflowStep { run?: string; uses?: string; } interface TurboDocument { tasks?: Record; } interface WorkspaceDocument { packages?: string[]; } const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); describe("development infrastructure", () => { it("has valid, local-only, version-pinned Compose services", async () => { const source = await readFile( path.join(repositoryRoot, "infrastructure", "compose.yaml"), "utf8", ); const compose = parse(source) as ComposeDocument; const postgres = compose.services?.postgres; const objectStorage = compose.services?.["object-storage"]; expect(postgres?.image).toBe("postgres:18.4-alpine3.24"); expect(objectStorage?.image).toBe("chrislusf/seaweedfs:4.28"); expect(postgres?.healthcheck).toBeDefined(); expect(objectStorage?.healthcheck).toBeDefined(); expect(postgres?.environment?.POSTGRES_INITDB_ARGS).toContain("--auth-host=scram-sha-256"); for (const service of [postgres, objectStorage]) { expect(service).toBeDefined(); expect(service?.image).not.toMatch(/:latest$/u); expect(service?.ports?.every((port) => port.startsWith("127.0.0.1:"))).toBe(true); expect(service?.volumes?.length).toBeGreaterThan(0); } expect(compose.volumes).toHaveProperty("postgres-data"); expect(compose.volumes).toHaveProperty("object-storage-data"); }); it("has a parseable CI workflow with static and live infrastructure gates", async () => { const source = await readFile( path.join(repositoryRoot, ".github", "workflows", "ci.yml"), "utf8", ); const workflow = parse(source) as { jobs?: Record; name?: string; }; const verify = workflow.jobs?.verify; const infrastructure = workflow.jobs?.["infrastructure-smoke"]; const migration = workflow.jobs?.["migration-smoke"]; const commands = verify?.steps?.flatMap((step) => step.run ?? []) ?? []; const infrastructureCommands = infrastructure?.steps?.flatMap((step) => step.run ?? []) ?? []; const migrationCommands = migration?.steps?.flatMap((step) => step.run ?? []) ?? []; const verifyActions = verify?.steps?.flatMap((step) => step.uses ?? []) ?? []; const migrationActions = migration?.steps?.flatMap((step) => step.uses ?? []) ?? []; expect(workflow.name).toBe("CI"); expect(verify).toBeDefined(); expect(commands).toContain("pnpm install --frozen-lockfile"); expect(commands).toContain("pnpm ci:verify"); expect(infrastructureCommands).toContain("bash scripts/smoke-infrastructure.sh"); expect(migration?.needs).toBe("verify"); expect(migration?.["timeout-minutes"]).toBe(15); expect(migrationActions).toEqual(verifyActions); expect(migrationCommands).toContain("pnpm install --frozen-lockfile"); expect(migrationCommands).toContain("pnpm test:migrations:integration"); }); it("routes containerized S3 smoke checks through the isolated Compose network", async () => { const source = await readFile( path.join(repositoryRoot, "scripts", "smoke-infrastructure.sh"), "utf8", ); const helper = await readFile( path.join(repositoryRoot, "scripts", "lib", "compose-job-network.sh"), "utf8", ); expect(source).toContain('source "$repository_root/scripts/lib/compose-job-network.sh"'); expect(source).toContain(`compose_job_network_connect object-storage "\${compose[@]}"`); expect(source).toContain('s3_endpoint="http://object-storage:8333"'); expect(source).toContain('s3_endpoint="http://127.0.0.1:$s3_port"'); expect(source).not.toContain("0.0.0.0:${S3_PORT"); expect(source.indexOf("compose_job_network_disconnect")).toBeLessThan( source.indexOf(`"\${compose[@]}" down`), ); expect(helper).toContain("[[ ! -f /.dockerenv ]]"); expect(helper).toContain('"$@" ps -q "$service"'); expect(helper).toContain("docker inspect"); expect(helper).toContain("docker network connect"); expect(helper).toContain("docker network disconnect"); }); it("provisions isolated PostgreSQL for the live migration suite", async () => { const packageSource = await readFile(path.join(repositoryRoot, "package.json"), "utf8"); const packageDocument = JSON.parse(packageSource) as PackageDocument; const source = await readFile( path.join(repositoryRoot, "scripts", "test-migrations-integration.sh"), "utf8", ); expect(packageDocument.scripts?.["test:migrations:integration"]).toBe( "pnpm build && bash scripts/test-migrations-integration.sh", ); expect(source).toContain('source "$repository_root/scripts/lib/compose-job-network.sh"'); expect(source).toContain('export POSTGRES_PORT="0"'); // Both live services come from the repository's own pinned Compose file, so the integration // suites exercise exactly what a developer runs locally (ADR 0030 added the object-storage half). expect(source).toContain("up --detach --wait --wait-timeout 180 postgres object-storage"); expect(source).toContain(`compose_job_network_connect postgres "\${compose[@]}"`); expect(source).toContain(`compose_job_network_connect object-storage "\${compose[@]}"`); // The storage suite receives an endpoint and the same credentials the service was started with, // and never a hardcoded host. expect(source).toContain("EKKLESIA_TEST_STORAGE_ENDPOINT="); expect(source).toContain("EKKLESIA_TEST_STORAGE_ACCESS_KEY="); expect(source).toContain('database_host="postgres"'); expect(source).toContain('database_port="5432"'); expect(source).toContain('database_host="127.0.0.1"'); expect(source).toContain( 'EKKLESIA_MIGRATION_TEST_DATABASE_URL="postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$database_host:$database_port/$POSTGRES_DB"', ); expect(source).toContain("--config vitest.migrations.integration.config.ts"); expect(source).not.toContain("0.0.0.0"); expect(source).not.toContain('compose[@]}" logs'); expect(source.indexOf("compose_job_network_disconnect")).toBeLessThan( source.indexOf("down --volumes --remove-orphans"), ); }); it("includes every official platform layer in the workspace", async () => { const source = await readFile(path.join(repositoryRoot, "pnpm-workspace.yaml"), "utf8"); const workspace = parse(source) as WorkspaceDocument; expect(workspace.packages).toEqual( expect.arrayContaining([ "apps/*", "builders/*", "core", "modules/*", "surfaces/*", "templates/*", ]), ); }); it("dispatches root and future package quality tasks through Turborepo", async () => { const packageSource = await readFile(path.join(repositoryRoot, "package.json"), "utf8"); const doctorSource = await readFile( path.join(repositoryRoot, "scripts", "run-doctor.ts"), "utf8", ); const turboSource = await readFile(path.join(repositoryRoot, "turbo.json"), "utf8"); const packageDocument = JSON.parse(packageSource) as PackageDocument; const turboDocument = JSON.parse(turboSource) as TurboDocument; expect(packageDocument.scripts?.lint).toBe("turbo run lint lint:root"); expect(packageDocument.scripts?.test).toBe("turbo run test test:root"); expect(packageDocument.scripts?.typecheck).toBe("turbo run typecheck typecheck:root"); expect(packageDocument.scripts?.["modules:validate"]).toBe( "turbo run build && node core/dist/cli/validate-modules.js", ); expect(packageDocument.scripts?.doctor).toBe("node scripts/run-doctor.ts"); expect(doctorSource).toContain('runCommand("turbo", ["run", "build"])'); expect(doctorSource).toContain('path.join(repositoryRoot, "core", "dist", "cli", "doctor.js")'); expect(packageDocument.scripts?.verify).toContain("pnpm modules:validate"); expect(turboDocument.tasks).toHaveProperty("//#lint:root"); expect(turboDocument.tasks).toHaveProperty("//#test:root"); expect(turboDocument.tasks).toHaveProperty("//#typecheck:root"); }); });