diff --git a/cli/README.md b/cli/README.md index c5003be..7895b6f 100644 --- a/cli/README.md +++ b/cli/README.md @@ -16,7 +16,7 @@ npm install -g @infosupport/huddle-cli huddle init ``` -Pulls `ghcr.io/infosupport/huddle:latest` and starts the container. Works with Docker and Podman: the runtime is detected automatically (Docker first, then Podman), or pick one explicitly with `huddle init --runtime ` or the `HUDDLE_RUNTIME` env var. If you run `huddle` while Huddle isn't running, you automatically get a hint to run this command. +Pulls `ghcr.io/infosupport/huddle:latest` and starts the container. Works with Docker, Podman and WSLc: the runtime is detected automatically (Docker first, then Podman, then WSLc), or pick one explicitly with `huddle init --runtime ` or the `HUDDLE_RUNTIME` env var. If you run `huddle` while Huddle isn't running, you automatically get a hint to run this command. ## Starting devcontainers diff --git a/cli/package-lock.json b/cli/package-lock.json index 4983000..b38fc76 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,13 @@ { "name": "@infosupport/huddle-cli", - "version": "1.0.1", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@infosupport/huddle-cli", - "version": "1.0.1", + "version": "1.2.0", + "license": "GPL-3.0-or-later", "bin": { "huddle": "dist/index.js" }, diff --git a/cli/src/index.ts b/cli/src/index.ts index a11464a..3133e1b 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -110,7 +110,7 @@ Usage: huddle experiment status Show the active channel and CLI version Init options: - --runtime Container runtime (default: auto-detected; + --runtime Container runtime (default: auto-detected; also via the HUDDLE_RUNTIME env var) --experiment Use the experimental build of issue (same as "huddle experiment use ") diff --git a/cli/src/runtime.ts b/cli/src/runtime.ts index 1bd35db..d140cc7 100644 --- a/cli/src/runtime.ts +++ b/cli/src/runtime.ts @@ -1,6 +1,6 @@ import { execSync } from 'child_process'; -export type RuntimeName = 'docker' | 'podman'; +export type RuntimeName = 'docker' | 'podman' | 'wslc'; export interface ContainerRuntime { name: RuntimeName; @@ -95,14 +95,14 @@ function buildRuntime(name: RuntimeName): ContainerRuntime { export function parseRuntimeName(value: string): RuntimeName { const normalized = value.toLowerCase().trim(); - if (normalized === 'docker' || normalized === 'podman') return normalized; - throw new Error(`Unknown container runtime: ${value}. Choose docker or podman.`); + if (normalized === 'docker' || normalized === 'podman' || normalized === 'wslc') return normalized; + throw new Error(`Unknown container runtime: ${value}. Choose docker, podman or wslc.`); } /** * Determines which container runtime to use. * An explicit choice (via --runtime or HUDDLE_RUNTIME) wins; otherwise it is - * auto-detected: Docker first, then Podman. + * auto-detected: Docker first, then Podman, then wslc. */ export function resolveRuntime(explicit?: string): ContainerRuntime { const requested = explicit ?? process.env.HUDDLE_RUNTIME; @@ -117,11 +117,11 @@ export function resolveRuntime(explicit?: string): ContainerRuntime { // Auto-detectie: kijk eerst achter het `docker`-commando (dat een Podman-shim // kan zijn), daarna naar `podman`. Zo wint een echte Docker-engine als die er // is, maar herkennen we Podman ook als het zich als `docker` voordoet. - const detected = detectEngine('docker') ?? detectEngine('podman'); + const detected = detectEngine('docker') ?? detectEngine('podman') ?? detectEngine('wslc'); if (detected) return buildRuntime(detected); throw new Error( - 'No working container runtime found. Install and start Docker or Podman,\n' + - 'or pick one explicitly with --runtime or the HUDDLE_RUNTIME env var.', + 'No working container runtime found. Install and start Docker, Podman or wslc,\n' + + 'or pick one explicitly with --runtime or the HUDDLE_RUNTIME env var.', ); } diff --git a/gateway/test/socket-proxy.test.ts b/gateway/test/socket-proxy.test.ts index 8d9bef3..07c8593 100644 --- a/gateway/test/socket-proxy.test.ts +++ b/gateway/test/socket-proxy.test.ts @@ -73,7 +73,11 @@ describe('withLabelFilter', () => { }); }); -describe('createContainerProxy socket-layout', () => { +// Deze tests binden een echte AF_UNIX-socket (server.listen op een pad). Dat is +// een Linux-primitief; de gateway draait in productie in een Linux-container. +// Op native Windows faalt de bind met EACCES, dus we slaan het blok daar over +// (draai de suite in WSL/Linux voor dekking). +describe.skipIf(process.platform === 'win32')('createContainerProxy socket-layout', () => { let createContainerProxy: typeof import('../src/socket-proxy').createContainerProxy; let dir: string; const servers: net.Server[] = []; @@ -120,6 +124,22 @@ describe('createContainerProxy socket-layout', () => { await connect(sockPath); await connect(path.join(dir, 'dc-c.sock')); }); +}); + +// De naam-guard staat los van het binden van een socket, dus deze test draait +// ook op native Windows (geen AF_UNIX-bind nodig — zie het blok hierboven). +describe('createContainerProxy naam-validatie', () => { + let createContainerProxy: typeof import('../src/socket-proxy').createContainerProxy; + let dir: string; + + beforeAll(async () => { + createContainerProxy = (await import('../src/socket-proxy')).createContainerProxy; + dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dc-sock-')); + }); + + afterAll(() => { + fs.rmSync(dir, { recursive: true, force: true }); + }); // containerName vloeit via path.join() in de socket-paden. De naam komt uit // huddle's eigen orchestratie, maar we dwingen de Docker-naamgrammatica