mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 13:05:08 +00:00
246 lines
8.3 KiB
TypeScript
246 lines
8.3 KiB
TypeScript
import { spawnSync } from "node:child_process";
|
|
import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join, resolve } from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const ensureNodeScript = resolve(".github/actions/setup-pnpm-store-cache/ensure-node.sh");
|
|
|
|
function writeFakeNode(binDir: string, version: string) {
|
|
mkdirSync(binDir, { recursive: true });
|
|
const nodePath = join(binDir, "node");
|
|
writeFileSync(
|
|
nodePath,
|
|
`#!/usr/bin/env bash
|
|
if [[ "$1" == "-p" ]]; then
|
|
echo "${version}"
|
|
exit 0
|
|
fi
|
|
if [[ "$1" == "-v" ]]; then
|
|
echo "v${version}"
|
|
exit 0
|
|
fi
|
|
exit 0
|
|
`,
|
|
);
|
|
chmodSync(nodePath, 0o755);
|
|
return nodePath;
|
|
}
|
|
|
|
function runEnsureNode(root: string, requested: string, extraEnv: NodeJS.ProcessEnv = {}) {
|
|
const githubPath = join(root, "github-path");
|
|
const pathOverride = extraEnv.PATH;
|
|
const result = spawnSync(
|
|
"bash",
|
|
[
|
|
"-c",
|
|
[
|
|
"set -e",
|
|
...(pathOverride ? [`export PATH=${JSON.stringify(pathOverride)}`] : []),
|
|
`source "${ensureNodeScript}"`,
|
|
`openclaw_ensure_node "${requested}"`,
|
|
"command -v node",
|
|
"node -p 'process.versions.node'",
|
|
].join("; "),
|
|
],
|
|
{
|
|
encoding: "utf8",
|
|
env: {
|
|
...process.env,
|
|
GITHUB_PATH: githubPath,
|
|
...extraEnv,
|
|
},
|
|
},
|
|
);
|
|
return result;
|
|
}
|
|
|
|
function runVersionMatch(actual: string, requested: string) {
|
|
return spawnSync(
|
|
"bash",
|
|
[
|
|
"-c",
|
|
[
|
|
`source "${ensureNodeScript}"`,
|
|
`openclaw_node_version_matches "${actual}" "${requested}"`,
|
|
].join("; "),
|
|
],
|
|
{ encoding: "utf8", env: process.env },
|
|
);
|
|
}
|
|
|
|
describe("setup-pnpm-store-cache ensure-node", () => {
|
|
it("uses a matching active node", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "openclaw-ensure-node-"));
|
|
try {
|
|
const activeBin = join(root, "active", "bin");
|
|
const activeNode = writeFakeNode(activeBin, "24.15.0");
|
|
const result = runEnsureNode(root, "24.15.0", {
|
|
PATH: `${activeBin}:${process.env.PATH ?? ""}`,
|
|
RUNNER_TOOL_CACHE: join(root, "missing-toolcache"),
|
|
});
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout).toContain(`Using active Node 24.15.0 at ${activeNode}`);
|
|
expect(result.stdout.trim().endsWith("24.15.0")).toBe(true);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("repairs PATH from the toolcache when setup-node leaves an old node active", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "openclaw-ensure-node-"));
|
|
try {
|
|
const activeBin = join(root, "active", "bin");
|
|
writeFakeNode(activeBin, "20.20.0");
|
|
const toolcacheBin = join(root, "toolcache", "node", "24.15.0", "x64", "bin");
|
|
const toolcacheNode = writeFakeNode(toolcacheBin, "24.15.0");
|
|
const result = runEnsureNode(root, "24.15.0", {
|
|
PATH: `${activeBin}:${process.env.PATH ?? ""}`,
|
|
RUNNER_TOOL_CACHE: join(root, "toolcache"),
|
|
});
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout).toContain(`Using Node 24.15.0 from ${toolcacheNode}`);
|
|
expect(result.stdout).toContain(`${toolcacheNode}\n24.15.0`);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("normalizes Windows toolcache paths for Git Bash before prepending PATH", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "openclaw-ensure-node-"));
|
|
try {
|
|
const activeBin = join(root, "active", "bin");
|
|
writeFakeNode(activeBin, "22.22.3");
|
|
const toolcacheBin = join(root, "toolcache", "node", "24.15.0", "x64");
|
|
const toolcacheNode = writeFakeNode(toolcacheBin, "24.15.0");
|
|
const helperBin = join(root, "helpers");
|
|
mkdirSync(helperBin, { recursive: true });
|
|
const cygpath = join(helperBin, "cygpath");
|
|
writeFileSync(
|
|
cygpath,
|
|
`#!/usr/bin/env bash
|
|
if [[ "$1" == "-u" ]]; then
|
|
echo "${toolcacheBin}"
|
|
exit 0
|
|
fi
|
|
if [[ "$1" == "-w" ]]; then
|
|
echo "C:\\\\hostedtoolcache\\\\windows\\\\node\\\\24.15.0\\\\x64"
|
|
exit 0
|
|
fi
|
|
exit 1
|
|
`,
|
|
);
|
|
chmodSync(cygpath, 0o755);
|
|
const githubPath = join(root, "github-path");
|
|
const result = spawnSync(
|
|
"bash",
|
|
[
|
|
"-c",
|
|
[
|
|
"set -e",
|
|
`export PATH=${JSON.stringify(`${helperBin}:${activeBin}:${process.env.PATH ?? ""}`)}`,
|
|
`export GITHUB_PATH=${JSON.stringify(githubPath)}`,
|
|
`source "${ensureNodeScript}"`,
|
|
`openclaw_prepend_node_bin "C:\\\\hostedtoolcache\\\\windows/node/24.15.0/x64"`,
|
|
"command -v node",
|
|
"node -p 'process.versions.node'",
|
|
`cat "${githubPath}"`,
|
|
].join("; "),
|
|
],
|
|
{ encoding: "utf8", env: process.env },
|
|
);
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout).toContain(`${toolcacheNode}\n24.15.0`);
|
|
expect(result.stdout).toContain("C:\\hostedtoolcache\\windows\\node\\24.15.0\\x64");
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("repairs PATH from the container-mounted GitHub Actions toolcache", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "openclaw-ensure-node-"));
|
|
try {
|
|
const activeBin = join(root, "active", "bin");
|
|
writeFakeNode(activeBin, "20.20.0");
|
|
const toolcacheBin = join(root, "__t", "node", "24.99.99", "x64", "bin");
|
|
const toolcacheNode = writeFakeNode(toolcacheBin, "24.99.99");
|
|
const result = runEnsureNode(root, "24.99.99", {
|
|
PATH: `${activeBin}:${process.env.PATH ?? ""}`,
|
|
OPENCLAW_CONTAINER_TOOL_CACHE: join(root, "__t"),
|
|
RUNNER_TOOL_CACHE: join(root, "hostedtoolcache"),
|
|
});
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout).toContain(`Using Node 24.99.99 from ${toolcacheNode}`);
|
|
expect(result.stdout).toContain(`${toolcacheNode}\n24.99.99`);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("accepts major wildcard requests when selecting a toolcache node", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "openclaw-ensure-node-"));
|
|
try {
|
|
const activeBin = join(root, "active", "bin");
|
|
writeFakeNode(activeBin, "20.20.0");
|
|
const toolcacheBin = join(root, "toolcache", "node", "24.15.0", "x64", "bin");
|
|
writeFakeNode(toolcacheBin, "24.15.0");
|
|
const result = runEnsureNode(root, "24.x", {
|
|
PATH: `${activeBin}:${process.env.PATH ?? ""}`,
|
|
RUNNER_TOOL_CACHE: join(root, "toolcache"),
|
|
});
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout.trim().endsWith("24.15.0")).toBe(true);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("keeps the Node 22 wildcard at the supported minimum", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "openclaw-ensure-node-"));
|
|
try {
|
|
const activeBin = join(root, "active", "bin");
|
|
writeFakeNode(activeBin, "22.18.0");
|
|
const toolcacheBin = join(root, "toolcache", "node", "22.22.3", "x64", "bin");
|
|
const toolcacheNode = writeFakeNode(toolcacheBin, "22.22.3");
|
|
const result = runEnsureNode(root, "22.x", {
|
|
PATH: `${activeBin}:${process.env.PATH ?? ""}`,
|
|
RUNNER_TOOL_CACHE: join(root, "toolcache"),
|
|
});
|
|
|
|
expect(result.status).toBe(0);
|
|
expect(result.stdout).toContain(`Using Node 22.22.3 from ${toolcacheNode}`);
|
|
expect(result.stdout.trim().endsWith("22.22.3")).toBe(true);
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it("rejects Node 22 wildcard matches below the supported minimum", () => {
|
|
expect(runVersionMatch("22.18.0", "22.x").status).toBe(1);
|
|
expect(runVersionMatch("22.19.0", "22.x").status).toBe(0);
|
|
});
|
|
|
|
it("fails clearly when no matching node is available", () => {
|
|
const root = mkdtempSync(join(tmpdir(), "openclaw-ensure-node-"));
|
|
try {
|
|
const activeBin = join(root, "active", "bin");
|
|
writeFakeNode(activeBin, "20.20.0");
|
|
const result = runEnsureNode(root, "99.99.99", {
|
|
PATH: `${activeBin}:${process.env.PATH ?? ""}`,
|
|
RUNNER_TOOL_CACHE: join(root, "toolcache"),
|
|
});
|
|
|
|
expect(result.status).toBe(1);
|
|
expect(result.stdout).toContain("::error::Expected Node '99.99.99'");
|
|
expect(result.stdout).toContain("active node is '20.20.0'");
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
});
|