Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6313adb
fix(cli): fail fast on unsupported onboarding hosts
ChunkyMonkey11 Apr 3, 2026
9c10484
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 3, 2026
b726114
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 3, 2026
48d534a
chore(host-support): simplify pre-20 EOL condition
ChunkyMonkey11 Apr 3, 2026
858d2c1
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 3, 2026
706f71b
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 3, 2026
4b081b2
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 4, 2026
11f0554
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 4, 2026
01484a1
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 4, 2026
30ab2e7
Merge upstream/main into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 4, 2026
70502d6
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 5, 2026
c7539c8
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 5, 2026
64e5370
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 6, 2026
35486fb
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 6, 2026
4b79606
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 6, 2026
307209b
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 6, 2026
f41d54e
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 6, 2026
fb7e9c6
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 7, 2026
c4180a4
Merge branch 'main' into feat/next-contribution-2026-04-02
ChunkyMonkey11 Apr 7, 2026
c0a7f4b
fix(cli): classify macOS as supported host OS
cv Apr 7, 2026
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
5 changes: 5 additions & 0 deletions bin/lib/host-support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

// Thin CJS shim — implementation lives in src/lib/host-support.ts
module.exports = require("../../dist/lib/host-support");
11 changes: 11 additions & 0 deletions bin/lib/onboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const {
getMemoryInfo,
planHostRemediation,
} = require("./preflight");
const { checkHostSupport } = require("./host-support");

// Typed modules (compiled from src/lib/*.ts → dist/lib/*.js)
const gatewayState = require("../../dist/lib/gateway-state");
Expand Down Expand Up @@ -1530,6 +1531,16 @@ function getNonInteractiveModel(providerKey) {
async function preflight() {
step(1, 8, "Preflight checks");

const hostSupport = checkHostSupport();
if (hostSupport.status === "ok") {
console.log(` ✓ ${hostSupport.message}`);
} else if (hostSupport.status === "warning") {
console.log(` ⚠ ${hostSupport.message}`);
} else {
console.error(` ${hostSupport.message}`);
process.exit(1);
}

const host = assessHost();

// Docker / runtime
Expand Down
149 changes: 149 additions & 0 deletions src/lib/host-support.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { describe, expect, it } from "vitest";
// Import through compiled dist output for consistent coverage attribution.
import {
checkHostSupport,
classifyLinuxHost,
classifyMacosHost,
parseOsRelease,
} from "../../dist/lib/host-support";

describe("parseOsRelease", () => {
it("parses quoted and unquoted values", () => {
const parsed = parseOsRelease([
'NAME="Ubuntu"',
"ID=ubuntu",
'VERSION_ID="24.04"',
].join("\n"));

expect(parsed).toEqual({ id: "ubuntu", versionId: "24.04" });
});

it("returns empty fields when ID/VERSION_ID are missing", () => {
const parsed = parseOsRelease("NAME=Ubuntu\nPRETTY_NAME=Ubuntu Linux");
expect(parsed).toEqual({ id: "", versionId: "" });
});
});

describe("classifyLinuxHost", () => {
it("marks Ubuntu 24.04 as supported", () => {
const result = classifyLinuxHost("ubuntu", "24.04");
expect(result.status).toBe("ok");
expect(result.code).toBe("SUPPORTED");
});

it("marks Ubuntu 22.04 as supported", () => {
const result = classifyLinuxHost("ubuntu", "22.04");
expect(result.status).toBe("ok");
expect(result.code).toBe("SUPPORTED");
});

it("marks Ubuntu 20.04 as near EOL warning", () => {
const result = classifyLinuxHost("ubuntu", "20.04");
expect(result.status).toBe("warning");
expect(result.code).toBe("NEAR_EOL");
});

it("marks Ubuntu 18.04 as EOL error", () => {
const result = classifyLinuxHost("ubuntu", "18.04");
expect(result.status).toBe("error");
expect(result.code).toBe("EOL");
});

it("marks unknown Linux distro as warning", () => {
const result = classifyLinuxHost("debian", "12");
expect(result.status).toBe("warning");
expect(result.code).toBe("UNSUPPORTED_OS");
});
});

describe("checkHostSupport", () => {
it("classifies unsupported platform as error", () => {
const result = checkHostSupport({ platform: "win32" });
expect(result.status).toBe("error");
expect(result.code).toBe("UNSUPPORTED_OS");
});

it("classifies linux from os-release data", () => {
const result = checkHostSupport({
platform: "linux",
readFileSyncImpl: () => 'ID=ubuntu\nVERSION_ID="24.04"\n',
});

expect(result.status).toBe("ok");
expect(result.code).toBe("SUPPORTED");
});

it("returns warning when /etc/os-release cannot be read", () => {
const result = checkHostSupport({
platform: "linux",
readFileSyncImpl: () => {
throw new Error("missing");
},
});

expect(result.status).toBe("warning");
expect(result.code).toBe("UNKNOWN_VERSION");
});

it("classifies macOS 14 as supported", () => {
const result = checkHostSupport({
platform: "darwin",
getMacosVersionImpl: () => "14.5",
});

expect(result.status).toBe("ok");
expect(result.code).toBe("SUPPORTED");
expect(result.message).toContain("macOS 14");
});

it("returns unknown-version warning when macOS version is unavailable", () => {
const result = checkHostSupport({
platform: "darwin",
getMacosVersionImpl: () => "",
});

expect(result.status).toBe("warning");
expect(result.code).toBe("UNKNOWN_VERSION");
});
});

describe("classifyMacosHost", () => {
it("marks macOS 15 (Sequoia) as supported", () => {
const result = classifyMacosHost("15.1");
expect(result.status).toBe("ok");
expect(result.code).toBe("SUPPORTED");
});

it("marks macOS 14 (Sonoma) as supported", () => {
const result = classifyMacosHost("14.5");
expect(result.status).toBe("ok");
expect(result.code).toBe("SUPPORTED");
});

it("marks macOS 13 (Ventura) as supported", () => {
const result = classifyMacosHost("13.0");
expect(result.status).toBe("ok");
expect(result.code).toBe("SUPPORTED");
});

it("marks macOS 12 (Monterey) as near EOL", () => {
const result = classifyMacosHost("12.7");
expect(result.status).toBe("warning");
expect(result.code).toBe("NEAR_EOL");
});

it("returns unknown-version for unparseable version", () => {
const result = classifyMacosHost("invalid");
expect(result.status).toBe("warning");
expect(result.code).toBe("UNKNOWN_VERSION");
});

it("returns unknown-version for empty string", () => {
const result = classifyMacosHost("");
expect(result.status).toBe("warning");
expect(result.code).toBe("UNKNOWN_VERSION");
});
});
Loading