mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-08 02:52:15 +00:00
fix(e2e): resolve mounted macOS desktop homes
This commit is contained in:
@@ -4,6 +4,7 @@ export * from "./env-limits.ts";
|
||||
export * from "./host-command.ts";
|
||||
export * from "./host-server.ts";
|
||||
export * from "./lane-runner.ts";
|
||||
export * from "./macos-users.ts";
|
||||
export * from "./package-artifact.ts";
|
||||
export * from "./parallels-vm.ts";
|
||||
export * from "./plugin-isolation.ts";
|
||||
|
||||
@@ -10,8 +10,10 @@ import {
|
||||
currentRunningSnapshotInfo,
|
||||
extractLastOpenClawVersionFromLog,
|
||||
makeTempDir,
|
||||
isLikelyMacosDesktopHome,
|
||||
packageBuildCommitFromTgz,
|
||||
packageVersionFromTgz,
|
||||
parseMacosDsclUserHomeLine,
|
||||
packOpenClaw,
|
||||
parseMode,
|
||||
parseProvider,
|
||||
@@ -690,10 +692,11 @@ exec node "$entry" ${argv}`,
|
||||
},
|
||||
).stdout.replaceAll("\r", "");
|
||||
for (const line of users.split("\n")) {
|
||||
const [user, home] = line.trim().split(/\s+/);
|
||||
const parsed = parseMacosDsclUserHomeLine(line);
|
||||
const user = parsed?.user;
|
||||
if (
|
||||
user &&
|
||||
home?.startsWith("/Users/") &&
|
||||
isLikelyMacosDesktopHome(parsed?.home) &&
|
||||
!user.startsWith("_") &&
|
||||
user !== "Shared" &&
|
||||
user !== ".localized"
|
||||
|
||||
13
scripts/e2e/parallels/macos-users.ts
Normal file
13
scripts/e2e/parallels/macos-users.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
// macOS user helpers support Parallels guest fallback discovery.
|
||||
export function parseMacosDsclUserHomeLine(line: string): { user: string; home: string } | null {
|
||||
const match = /^(\S+)\s+(.+?)\s*$/u.exec(line.replaceAll("\r", ""));
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return { user: match[1], home: match[2] };
|
||||
}
|
||||
|
||||
export function isLikelyMacosDesktopHome(home: string | undefined): boolean {
|
||||
const normalized = home?.trim();
|
||||
return Boolean(normalized) && /(?:^|\/)Users\/[^/]+$/u.test(normalized);
|
||||
}
|
||||
@@ -10,10 +10,12 @@ import {
|
||||
die,
|
||||
ensureValue,
|
||||
extractLastOpenClawVersionFromLog,
|
||||
isLikelyMacosDesktopHome,
|
||||
makeTempDir,
|
||||
packOpenClaw,
|
||||
packageBuildCommitFromTgz,
|
||||
packageVersionFromTgz,
|
||||
parseMacosDsclUserHomeLine,
|
||||
parsePlatformList,
|
||||
parseProvider,
|
||||
readPositiveIntEnv,
|
||||
@@ -1096,10 +1098,11 @@ export class NpmUpdateSmoke {
|
||||
{ check: false, quiet: true, timeoutMs: 30_000 },
|
||||
).stdout.replaceAll("\r", "");
|
||||
for (const line of users.split("\n")) {
|
||||
const [user, home] = line.trim().split(/\s+/);
|
||||
const parsed = parseMacosDsclUserHomeLine(line);
|
||||
const user = parsed?.user;
|
||||
if (
|
||||
user &&
|
||||
home?.startsWith("/Users/") &&
|
||||
isLikelyMacosDesktopHome(parsed?.home) &&
|
||||
!user.startsWith("_") &&
|
||||
user !== "Shared" &&
|
||||
user !== ".localized"
|
||||
|
||||
@@ -754,6 +754,52 @@ exit 1
|
||||
expect(script).toContain('"/usr/sbin/chown", sudoUser, scriptPath');
|
||||
});
|
||||
|
||||
it("selects macOS desktop users with homes on spaced mounted volumes", () => {
|
||||
const root = makeTempDir();
|
||||
const prlctlPath = path.join(root, "prlctl");
|
||||
writeFileSync(
|
||||
prlctlPath,
|
||||
`#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
args=" $* "
|
||||
if [[ "$args" == *" /usr/bin/stat -f %Su /dev/console"* ]]; then
|
||||
printf '%s\\n' 'loginwindow'
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$args" == *" /usr/bin/dscl . -list /Users NFSHomeDirectory"* ]]; then
|
||||
printf '%s\\n' '_daemon /var/root'
|
||||
printf '%s\\n' 'clawuser /Volumes/Macintosh HD/Users/clawuser'
|
||||
exit 0
|
||||
fi
|
||||
exit 7
|
||||
`,
|
||||
);
|
||||
chmodSync(prlctlPath, 0o755);
|
||||
|
||||
withEnv(
|
||||
{
|
||||
OPENAI_API_KEY: "test-key",
|
||||
PATH: `${root}${path.delimiter}${process.env.PATH ?? ""}`,
|
||||
},
|
||||
() => {
|
||||
const smoke = new NpmUpdateSmoke({
|
||||
...TEST_AUTH,
|
||||
json: false,
|
||||
packageSpec: "openclaw@latest",
|
||||
platforms: new Set<Platform>(["macos"]),
|
||||
provider: "openai",
|
||||
updateTarget: "local-main",
|
||||
});
|
||||
const resolveMacosDesktopUser = Reflect.get(
|
||||
smoke,
|
||||
"resolveMacosDesktopUser",
|
||||
) as () => string;
|
||||
|
||||
expect(resolveMacosDesktopUser.call(smoke)).toBe("clawuser");
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps spaces in macOS sudo fallback desktop homes", () => {
|
||||
const root = makeTempDir();
|
||||
const prlctlPath = path.join(root, "prlctl");
|
||||
|
||||
@@ -20,7 +20,9 @@ import { pathToFileURL } from "node:url";
|
||||
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
extractLastOpenClawVersionFromLog,
|
||||
isLikelyMacosDesktopHome,
|
||||
modelProviderConfigBatchJson,
|
||||
parseMacosDsclUserHomeLine,
|
||||
readPositiveIntEnv,
|
||||
resolveLatestVersion,
|
||||
resolveParallelsModelTimeoutSeconds,
|
||||
@@ -221,6 +223,15 @@ describe("Parallels smoke model selection", () => {
|
||||
let invalidWindowsAgentTimeoutResult: ReturnType<typeof spawnNodeEvalSync>;
|
||||
let invalidWindowsUpdateTimeoutResult: ReturnType<typeof spawnNodeEvalSync>;
|
||||
|
||||
it("parses macOS dscl user homes with spaces on mounted volumes", () => {
|
||||
expect(parseMacosDsclUserHomeLine("clawuser /Volumes/Macintosh HD/Users/clawuser")).toEqual({
|
||||
user: "clawuser",
|
||||
home: "/Volumes/Macintosh HD/Users/clawuser",
|
||||
});
|
||||
expect(isLikelyMacosDesktopHome("/Volumes/Macintosh HD/Users/clawuser")).toBe(true);
|
||||
expect(isLikelyMacosDesktopHome("/var/empty")).toBe(false);
|
||||
});
|
||||
|
||||
it("extracts the last OpenClaw version from a bounded log tail", async () => {
|
||||
const tempDir = mkdtempSync(join(tmpdir(), "openclaw-parallels-log-tail-"));
|
||||
const logPath = join(tempDir, "phase.log");
|
||||
|
||||
Reference in New Issue
Block a user