From c162363185ef299a618572436b341725033980a0 Mon Sep 17 00:00:00 2001 From: abdul712 Date: Tue, 19 May 2026 20:53:39 -0400 Subject: [PATCH] test: add local docker compose coverage --- packages/local-docker/docker-compose.test.ts | 76 ++++++++++++++++++++ packages/local-docker/docker-compose.yml | 4 +- packages/local-docker/package.json | 7 +- packages/local-docker/vitest.config.ts | 8 +++ pnpm-lock.yaml | 9 ++- 5 files changed, 99 insertions(+), 5 deletions(-) create mode 100644 packages/local-docker/docker-compose.test.ts create mode 100644 packages/local-docker/vitest.config.ts diff --git a/packages/local-docker/docker-compose.test.ts b/packages/local-docker/docker-compose.test.ts new file mode 100644 index 00000000000..18d43944ca4 --- /dev/null +++ b/packages/local-docker/docker-compose.test.ts @@ -0,0 +1,76 @@ +import { readFile } from "node:fs/promises"; +import { fileURLToPath } from "node:url"; +import { describe, expect, it } from "vitest"; +import { parse } from "yaml"; + +type ComposeService = { + container_name?: string; + image?: string; + build?: { + context?: string; + dockerfile?: string; + }; + ports?: Array; + volumes?: string[]; + depends_on?: string[]; + environment?: Record; +}; + +type ComposeFile = { + name?: string; + services?: Record; + volumes?: Record; +}; + +const composePath = fileURLToPath( + new URL("./docker-compose.yml", import.meta.url), +); + +async function readCompose() { + const source = await readFile(composePath, "utf8"); + return parse(source) as ComposeFile; +} + +describe("local Docker compose file", () => { + it("keeps the expected local development services wired", async () => { + const compose = await readCompose(); + + expect(compose.name).toBe("cap-so-dev"); + expect(Object.keys(compose.services ?? {}).sort()).toEqual([ + "cap-media-server", + "createbuckets", + "minio", + "ps-mysql", + ]); + + expect(compose.services?.["ps-mysql"]).toMatchObject({ + image: "mysql:8.0", + container_name: "mysql-primary-db", + }); + expect(compose.services?.["cap-media-server"]?.build).toEqual({ + context: "../..", + dockerfile: "apps/media-server/Dockerfile", + }); + expect(compose.services?.minio?.ports).toEqual(["9000:9000", "9001:9001"]); + expect(compose.services?.createbuckets?.depends_on).toEqual(["minio"]); + }); + + it("does not declare stale named volumes", async () => { + const compose = await readCompose(); + const declaredVolumes = new Set(Object.keys(compose.volumes ?? {})); + const usedNamedVolumes = new Set( + Object.values(compose.services ?? {}) + .flatMap((service) => service.volumes ?? []) + .map((volume) => volume.split(":")[0]) + .filter( + (source) => + source && + !source.startsWith(".") && + !source.startsWith("/") && + !source.startsWith("~"), + ), + ); + + expect([...declaredVolumes].sort()).toEqual([...usedNamedVolumes].sort()); + }); +}); diff --git a/packages/local-docker/docker-compose.yml b/packages/local-docker/docker-compose.yml index a42005a7b28..044bbb4089f 100644 --- a/packages/local-docker/docker-compose.yml +++ b/packages/local-docker/docker-compose.yml @@ -31,7 +31,7 @@ services: PORT: 3456 MEDIA_SERVER_WEBHOOK_SECRET: ${MEDIA_SERVER_WEBHOOK_SECRET:-local-media-server-secret} - # Local S3 Strorage + # Local S3 Storage minio: container_name: minio-storage image: "minio/minio:latest" @@ -62,5 +62,3 @@ services: " volumes: ps-mysql: - minio-data: - minio-certs: diff --git a/packages/local-docker/package.json b/packages/local-docker/package.json index a68d75430c9..8022a5d2e20 100644 --- a/packages/local-docker/package.json +++ b/packages/local-docker/package.json @@ -7,9 +7,14 @@ "dev": "pnpm docker:up", "docker:up": "docker compose up -d --wait", "docker:stop": "docker compose stop", - "docker:clean": "docker compose down -v" + "docker:clean": "docker compose down -v", + "test": "vitest run" }, "engines": { "node": ">=20" + }, + "devDependencies": { + "vitest": "~2.1.9", + "yaml": "^2.8.1" } } diff --git a/packages/local-docker/vitest.config.ts b/packages/local-docker/vitest.config.ts new file mode 100644 index 00000000000..ce63ad84542 --- /dev/null +++ b/packages/local-docker/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + include: ["**/*.test.ts"], + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2810356dc57..12cfb865d0d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1087,7 +1087,14 @@ importers: specifier: ^22.15.14 version: 22.15.14 - packages/local-docker: {} + packages/local-docker: + devDependencies: + vitest: + specifier: ~2.1.9 + version: 2.1.9(@types/node@22.15.17)(jsdom@26.1.0)(lightningcss@1.32.0)(terser@5.44.0) + yaml: + specifier: ^2.8.1 + version: 2.8.1 packages/sdk-embed: dependencies: