|
| 1 | +#!/usr/bin/env node |
| 2 | +/** |
| 3 | + * Validates docker-compose.yml merged with Tor / I2P overlays (config -q). |
| 4 | + * Requires Docker Desktop / Engine. Does not start containers. |
| 5 | + */ |
| 6 | +import { spawnSync } from 'node:child_process' |
| 7 | +import { existsSync } from 'node:fs' |
| 8 | +import { fileURLToPath } from 'node:url' |
| 9 | +import { dirname, join } from 'node:path' |
| 10 | + |
| 11 | +const root = join(dirname(fileURLToPath(import.meta.url)), '..') |
| 12 | +process.chdir(root) |
| 13 | + |
| 14 | +function resolveDockerExe() { |
| 15 | + if (process.env.DOCKER_EXE && existsSync(process.env.DOCKER_EXE)) { |
| 16 | + return process.env.DOCKER_EXE |
| 17 | + } |
| 18 | + if (process.platform === 'win32' && process.env.ProgramFiles) { |
| 19 | + const candidate = join( |
| 20 | + process.env.ProgramFiles, |
| 21 | + 'Docker', |
| 22 | + 'Docker', |
| 23 | + 'resources', |
| 24 | + 'bin', |
| 25 | + 'docker.exe', |
| 26 | + ) |
| 27 | + if (existsSync(candidate)) { |
| 28 | + return candidate |
| 29 | + } |
| 30 | + } |
| 31 | + return 'docker' |
| 32 | +} |
| 33 | + |
| 34 | +const dockerExe = resolveDockerExe() |
| 35 | + |
| 36 | +const dockerCheck = spawnSync(dockerExe, ['compose', 'version'], { encoding: 'utf8' }) |
| 37 | +if (dockerCheck.error || dockerCheck.status !== 0) { |
| 38 | + process.stderr.write( |
| 39 | + 'docker is not installed or not on PATH. Install Docker Desktop / Engine, then run:\n' + |
| 40 | + ' npm run compose:validate\n' + |
| 41 | + 'On Windows, ensure Docker Desktop is running, or set DOCKER_EXE to the full path to docker.exe.\n', |
| 42 | + ) |
| 43 | + process.exit(1) |
| 44 | +} |
| 45 | + |
| 46 | +if (!process.env.SECRET || process.env.SECRET.length < 16) { |
| 47 | + process.env.SECRET = |
| 48 | + 'ci_placeholder_not_for_production_use_repeat_to_64chars_aaaaaaaa' |
| 49 | +} |
| 50 | + |
| 51 | +const runs = [ |
| 52 | + ['docker-compose.yml', 'docker-compose.i2p.yml'], |
| 53 | + ['docker-compose.yml', 'docker-compose.tor.yml'], |
| 54 | + ['docker-compose.yml', 'docker-compose.tor.yml', 'docker-compose.i2p.yml'], |
| 55 | +] |
| 56 | + |
| 57 | +for (const files of runs) { |
| 58 | + const args = ['compose'] |
| 59 | + for (const f of files) { |
| 60 | + args.push('-f', f) |
| 61 | + } |
| 62 | + args.push('config', '-q') |
| 63 | + const label = files.join(' + ') |
| 64 | + process.stdout.write(`== ${label} ==\n`) |
| 65 | + const r = spawnSync(dockerExe, args, { stdio: 'inherit' }) |
| 66 | + if (r.status !== 0) { |
| 67 | + process.stderr.write(`compose validation failed for: ${label}\n`) |
| 68 | + process.exit(r.status ?? 1) |
| 69 | + } |
| 70 | + process.stdout.write('OK\n') |
| 71 | +} |
| 72 | + |
| 73 | +process.stdout.write('All compose overlay merges validate successfully.\n') |
0 commit comments