diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 96adf3fb..38d1b9b6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -74,6 +74,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - name: Validate compose contracts + run: | + docker compose -f docker-compose.yml -f docker-compose.prod.yml config > /dev/null + docker compose -f docker-compose.example.yml config > /dev/null + - name: Setup Node.js uses: actions/setup-node@v4 with: diff --git a/services/edge-broker/test/config.test.mjs b/services/edge-broker/test/config.test.mjs index 44d32ead..1783b44b 100644 --- a/services/edge-broker/test/config.test.mjs +++ b/services/edge-broker/test/config.test.mjs @@ -1,42 +1,42 @@ import test from "node:test"; import assert from "node:assert/strict"; import { existsSync, readFileSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; -function readExistingSource(relativePath) { - const sourceUrl = new URL(relativePath, import.meta.url); - if (!existsSync(sourceUrl)) { - return ""; - } +const testDirectory = path.dirname(fileURLToPath(import.meta.url)); +const repoRoot = path.resolve(testDirectory, "../../.."); - return readFileSync(sourceUrl, "utf8"); +function readRequiredSource(...pathSegments) { + const sourcePath = path.resolve(repoRoot, ...pathSegments); + assert.equal(existsSync(sourcePath), true, `Expected config fixture to exist: ${sourcePath}`); + return readFileSync(sourcePath, "utf8"); } -function readExistingSources(relativePaths) { - return relativePaths - .map((relativePath) => readExistingSource(relativePath)) - .filter(Boolean) - .join("\n"); -} - -const composeSource = readExistingSources([ - "../../../docker-compose.yml", - "../../../docker-compose.prod.yml", -]); -const traefikSource = readExistingSources([ - "../../../services/traefik/traefik.yml", - "../../../services/traefik/traefik.prod.yml", -]); +const baseComposeSource = readRequiredSource("docker-compose.yml"); +const exampleComposeSource = readRequiredSource("docker-compose.example.yml"); +const traefikSource = [ + readRequiredSource("services", "traefik", "traefik.yml"), + readRequiredSource("services", "traefik", "traefik.prod.yml"), +].join("\n"); test("traefik does not expose a dedicated public edge broker port", () => { assert.doesNotMatch(traefikSource, /edge-broker:\s*\n\s*address:\s*":4300"/); }); -test("docker compose exposes the edge broker service on port 4300", () => { - assert.match(composeSource, /\bedge-broker:\b/); - assert.match(composeSource, /edge-broker:\s*\n[\s\S]*?\n\s+ports:\s*\n\s+- "4300:4300"/); +test("base docker compose exposes the edge broker service on port 4300", () => { + assert.match(baseComposeSource, /\bedge-broker:\b/); + assert.match(baseComposeSource, /edge-broker:\s*\n[\s\S]*?\n\s+ports:\s*\n\s+- "4300:4300"/); +}); + +test("example docker compose exposes the edge broker service on port 4300", () => { + assert.match(exampleComposeSource, /\bedge-broker:\b/); + assert.match(exampleComposeSource, /edge-broker:\s*\n[\s\S]*?\n\s+ports:\s*\n\s+- "4300:4300"/); }); test("php services receive broker websocket environment defaults", () => { - assert.match(composeSource, /EDGE_BROKER_URL:\s*\$\{EDGE_BROKER_URL:-http:\/\/edge-broker:4300\}/); - assert.match(composeSource, /EDGE_BROKER_SHARED_SECRET:\s*\$\{EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev\}/); + for (const composeSource of [baseComposeSource, exampleComposeSource]) { + assert.match(composeSource, /EDGE_BROKER_URL:\s*\$\{EDGE_BROKER_URL:-http:\/\/edge-broker:4300\}/); + assert.match(composeSource, /EDGE_BROKER_SHARED_SECRET:\s*\$\{EDGE_BROKER_SHARED_SECRET:-truckwash-edge-dev\}/); + } });