Skip to content
Merged
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 src/lib/agent/base-image-hermes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import path from "node:path";
import { beforeEach, describe, expect, it, vi } from "vitest";

import { makeAgent, withMockedDocker } from "../../../test/helpers/base-image-test-harness";
import { dockerRunCommandBetween } from "../../../test/helpers/hermes-dockerfile-run";
import { dockerRunCommandBetween } from "../../../test/helpers/dockerfile-run-shell";

describe("agent base image provisioning", () => {
beforeEach(() => {
Expand Down
53 changes: 0 additions & 53 deletions test/helpers/base-apt-security-functions.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,6 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";

export function dockerRunCommandBetween(
dockerfile: string,
startMarker: string,
endMarker: string,
): string {
const start = dockerfile.indexOf(startMarker);
const end = dockerfile.indexOf(endMarker, start);
if (start === -1 || end === -1 || end <= start) {
throw new Error(`Expected Dockerfile block between ${startMarker} and ${endMarker}`);
}
const runIndex = dockerfile.indexOf("RUN ", start);
if (runIndex === -1 || runIndex > end) {
throw new Error(`Expected RUN instruction after ${startMarker}`);
}
const runLines: string[] = [];
for (const line of dockerfile.slice(runIndex, end).split("\n")) {
runLines.push(line);
if (!line.trimEnd().endsWith("\\")) {
break;
}
}
const lastLine = runLines[runLines.length - 1]?.trimEnd() ?? "";
if (lastLine.endsWith("\\")) {
throw new Error(`Expected complete RUN instruction before ${endMarker}`);
}
return runLines
.join("\n")
.trim()
.replace(/^RUN\s+/, "")
.replace(/\\\n/g, " ");
}

export function runLoggedDockerShell(command: string, tmp: string, functionDefs: string[]) {
const logPath = path.join(tmp, "calls.log");
const script = [
"#!/usr/bin/env bash",
"set -euo pipefail",
`call_log=${JSON.stringify(logPath)}`,
...functionDefs,
command,
].join("\n");
const scriptPath = path.join(tmp, "run-docker-block.sh");
fs.writeFileSync(scriptPath, script, { mode: 0o700 });
return spawnSync("bash", [scriptPath], {
encoding: "utf-8",
timeout: 15000,
});
}

type DebianArchitecture = "amd64" | "arm64";

export const BASE_APT_SECURITY_HASHES: Record<
Expand Down
96 changes: 96 additions & 0 deletions test/helpers/dockerfile-run-shell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import type { SpawnSyncReturns } from "node:child_process";
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";

const DEFAULT_SHELL_TIMEOUT_MS = 5000;
const CHOWN_LOGGER = 'chown() { printf "chown %s\\n" "$*" >> "$call_log"; }';

export interface LoggedDockerShellOptions {
readonly env?: Record<string, string | undefined>;
readonly timeoutMs?: number;
}

export interface LoggedDockerShellResult {
readonly calls: string;
readonly result: SpawnSyncReturns<string>;
}

export function dockerRunCommandBetween(
dockerfile: string,
startMarker: string,
endMarker: string,
): string {
const start = dockerfile.indexOf(startMarker);
const end = dockerfile.indexOf(endMarker, start);
if (start === -1 || end === -1 || end <= start) {
throw new Error(`Expected Dockerfile block between ${startMarker} and ${endMarker}`);
}
const runIndex = dockerfile.indexOf("RUN ", start);
if (runIndex === -1 || runIndex > end) {
throw new Error(`Expected RUN instruction after ${startMarker}`);
}
const blockLines = dockerfile.slice(runIndex, end).split("\n");
const finalLineIndex = blockLines.findIndex((line) => !line.trimEnd().endsWith("\\"));
if (finalLineIndex === -1) {
throw new Error(`Expected complete RUN instruction before ${endMarker}`);
}
return blockLines
.slice(0, finalLineIndex + 1)
.join("\n")
.trim()
.replace(/^RUN\s+/, "")
.replace(/\\\n/g, " ");
}

function shellEnvironment(
overrides: Record<string, string | undefined> | undefined,
): NodeJS.ProcessEnv | undefined {
if (overrides === undefined) {
return undefined;
}
const childEnv = { ...process.env };
for (const [key, value] of Object.entries(overrides)) {
if (value === undefined) {
delete childEnv[key];
} else {
childEnv[key] = value;
}
}
return childEnv;
}

export function runLoggedDockerShell(
command: string,
tmp: string,
functionDefs: readonly string[] = [],
options: LoggedDockerShellOptions = {},
): LoggedDockerShellResult {
const logPath = path.join(tmp, "calls.log");
fs.rmSync(logPath, { force: true });
const script = [
"#!/usr/bin/env bash",
"set -euo pipefail",
`call_log=${JSON.stringify(logPath)}`,
...functionDefs,
command,
].join("\n");
const scriptPath = path.join(tmp, "run-docker-block.sh");
fs.writeFileSync(scriptPath, script, { mode: 0o700 });
const result = spawnSync("bash", [scriptPath], {
encoding: "utf-8",
env: shellEnvironment(options.env),
timeout: options.timeoutMs ?? DEFAULT_SHELL_TIMEOUT_MS,
});
const calls = fs.existsSync(logPath) ? fs.readFileSync(logPath, "utf-8") : "";
return { calls, result };
}

export function runDockerShell(command: string, sandboxRoot: string): LoggedDockerShellResult {
return runLoggedDockerShell(command.replaceAll("/sandbox", sandboxRoot), sandboxRoot, [
CHOWN_LOGGER,
]);
}
53 changes: 0 additions & 53 deletions test/helpers/hermes-dockerfile-run.ts

This file was deleted.

30 changes: 1 addition & 29 deletions test/hermes-dashboard-provisioning.test.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,16 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import type { SpawnSyncReturns } from "node:child_process";
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";

import { dockerRunCommandBetween } from "./helpers/hermes-dockerfile-run";
import { dockerRunCommandBetween, runLoggedDockerShell } from "./helpers/dockerfile-run-shell";

const ROOT = path.resolve(import.meta.dirname, "..");
const HERMES_DOCKERFILE = path.join(ROOT, "agents", "hermes", "Dockerfile");

interface LoggedDockerShellResult {
calls: string;
result: SpawnSyncReturns<string>;
}

function runLoggedDockerShell(
command: string,
tmp: string,
functionDefs: string[] = [],
): LoggedDockerShellResult {
const logPath = path.join(tmp, "calls.log");
fs.rmSync(logPath, { force: true });
const script = [
"#!/usr/bin/env bash",
"set -euo pipefail",
`call_log=${JSON.stringify(logPath)}`,
...functionDefs,
command,
].join("\n");
const scriptPath = path.join(tmp, "run-docker-block.sh");
fs.writeFileSync(scriptPath, script, { mode: 0o700 });
const result = spawnSync("bash", [scriptPath], { encoding: "utf-8", timeout: 5000 });
const calls = fs.existsSync(logPath) ? fs.readFileSync(logPath, "utf-8") : "";
return { result, calls };
}

function dashboardBuildCommand(hermesRoot: string, rootCache: string): string {
const dockerfile = fs.readFileSync(HERMES_DOCKERFILE, "utf-8");
return dockerRunCommandBetween(
Expand Down
2 changes: 1 addition & 1 deletion test/hermes-doctor-config-hash.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { dockerRunCommandBetween, runDockerShell } from "./helpers/hermes-dockerfile-run";
import { dockerRunCommandBetween, runDockerShell } from "./helpers/dockerfile-run-shell";

const ROOT = path.resolve(import.meta.dirname, "..");
const HERMES_DOCKERFILE = path.join(ROOT, "agents", "hermes", "Dockerfile");
Expand Down
2 changes: 1 addition & 1 deletion test/hermes-final-image-layout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { requireSingleReviewedDockerfileRunCommand } from "./helpers/dockerfile-run-commands";
import { dockerRunCommandBetween, runDockerShell } from "./helpers/hermes-dockerfile-run";
import { dockerRunCommandBetween, runDockerShell } from "./helpers/dockerfile-run-shell";
import { expectManagedBootstrapNativeImageContract } from "./support/managed-bootstrap-image-contract";

const ROOT = path.resolve(import.meta.dirname, "..");
Expand Down
24 changes: 1 addition & 23 deletions test/hermes-mcp-runtime-capability.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,11 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { dockerRunCommandBetween } from "./helpers/dockerfile-run-shell";

const ROOT = path.resolve(import.meta.dirname, "..");
const HERMES_DOCKERFILE = path.join(ROOT, "agents", "hermes", "Dockerfile");

function dockerRunCommandBetween(
dockerfile: string,
startMarker: string,
endMarker: string,
): string {
const start = dockerfile.indexOf(startMarker);
const end = dockerfile.indexOf(endMarker, start);
expect(start, `Expected Dockerfile start marker ${startMarker}`).toBeGreaterThanOrEqual(0);
expect(end, `Expected Dockerfile end marker ${endMarker}`).toBeGreaterThan(start);
const runIndex = dockerfile.indexOf("RUN ", start);
expect(runIndex, `Expected RUN instruction after ${startMarker}`).toBeGreaterThanOrEqual(start);
expect(runIndex, `Expected RUN instruction before ${endMarker}`).toBeLessThan(end);
const blockLines = dockerfile.slice(runIndex, end).split("\n");
const runEnd = blockLines.findIndex((line) => !line.trimEnd().endsWith("\\"));
expect(runEnd, `Expected complete RUN instruction before ${endMarker}`).toBeGreaterThanOrEqual(0);
const runLines = blockLines.slice(0, runEnd + 1);
return runLines
.join("\n")
.trim()
.replace(/^RUN\s+/, "")
.replace(/\\\n/g, " ");
}

function runHermesMcpClientImportValidation({
mcpAvailable,
httpAvailable,
Expand Down
2 changes: 1 addition & 1 deletion test/hermes-runtime-api-key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import path from "node:path";
import { describe, expect, it } from "vitest";

import { shellQuote } from "../src/lib/core/shell-quote";
import { dockerRunCommandBetween } from "./helpers/hermes-dockerfile-run";
import { dockerRunCommandBetween } from "./helpers/dockerfile-run-shell";

const START_SCRIPT = path.join(import.meta.dirname, "..", "agents", "hermes", "start.sh");
const HERMES_DOCKERFILE = path.join(import.meta.dirname, "..", "agents", "hermes", "Dockerfile");
Expand Down
25 changes: 13 additions & 12 deletions test/sandbox-base-runtime-tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import {
BASE_APT_SECURITY_FUNCTIONS,
dockerRunCommandBetween,
runLoggedDockerShell,
} from "./helpers/base-apt-security-functions";
import { BASE_APT_SECURITY_FUNCTIONS } from "./helpers/base-apt-security-functions";
import { dockerRunCommandBetween, runLoggedDockerShell } from "./helpers/dockerfile-run-shell";
import { stageFixedParser, useRealPatchedParser } from "./helpers/python-parser-security-fixture";

const ROOT = path.resolve(import.meta.dirname, "..");
Expand Down Expand Up @@ -53,13 +50,17 @@ function runBaseAptLayer(prefix: string) {
.replaceAll("/usr/local/bin/python", fakePythonLink)
.replaceAll("/usr/bin/python3", pythonShim)
.replaceAll("/usr/lib/python3.13/html/parser.py", fixedParser);
const result = runLoggedDockerShell(command, tmp, [
'apt-get() { printf "apt-get %s\\n" "$*" >> "$call_log"; }',
'install() { [[ "$#" -eq 8 && "$1" == "-d" && "$2" == "-o" && "$3" == "root" && "$4" == "-g" && "$5" == "root" && "$6" == "-m" && "$7" == "0755" ]] || return 64; mkdir -p "$8"; }',
'chown() { [[ "$#" -eq 2 && "$1" == "root:root" ]] || return 64; }',
...useRealPatchedParser(BASE_APT_SECURITY_FUNCTIONS, pythonShim),
]);
const calls = fs.readFileSync(path.join(tmp, "calls.log"), "utf-8");
const { calls, result } = runLoggedDockerShell(
command,
tmp,
[
'apt-get() { printf "apt-get %s\\n" "$*" >> "$call_log"; }',
'install() { [[ "$#" -eq 8 && "$1" == "-d" && "$2" == "-o" && "$3" == "root" && "$4" == "-g" && "$5" == "root" && "$6" == "-m" && "$7" == "0755" ]] || return 64; mkdir -p "$8"; }',
'chown() { [[ "$#" -eq 2 && "$1" == "root:root" ]] || return 64; }',
...useRealPatchedParser(BASE_APT_SECURITY_FUNCTIONS, pythonShim),
],
{ timeoutMs: 15_000 },
);
return { calls, fakePythonLink, pythonShim, result };
}

Expand Down
Loading
Loading