Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <docker|podman>` 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 <docker|podman|wslc>` 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

Expand Down
5 changes: 3 additions & 2 deletions cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Usage:
huddle experiment status Show the active channel and CLI version

Init options:
--runtime <docker|podman> Container runtime (default: auto-detected;
--runtime <docker|podman|wslc> Container runtime (default: auto-detected;
also via the HUDDLE_RUNTIME env var)
--experiment <nr> Use the experimental build of issue <nr>
(same as "huddle experiment use <nr>")
Expand Down
14 changes: 7 additions & 7 deletions cli/src/runtime.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-detect includes detectEngine('wslc'), but detectEngine never returns wslc (only podman or docker), so wslc cannot be auto-selected despite the new detection chain.

Details

✨ AI Reasoning
​The change aims to include a third runtime in auto-detection. However, the detection helper only ever maps a reachable command to one of two engine names. As a result, adding the third command to the fallback chain cannot actually select that third runtime in auto-detect mode. This creates a direct contradiction between the documented/advertised behavior and what this control flow can produce.

🔧 How do I fix it?
Trace execution paths carefully. Ensure precondition checks happen before using values, validate ranges before checking impossible conditions, and don't check for states that the code has already ruled out.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

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 <docker|podman> 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 <docker|podman|wslc> or the HUDDLE_RUNTIME env var.',
);
}
22 changes: 21 additions & 1 deletion gateway/test/socket-proxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = [];
Expand Down Expand Up @@ -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
Expand Down
Loading