fix: make windows CI path handling deterministic

This commit is contained in:
Peter Steinberger
2026-02-22 22:34:42 +00:00
parent 3b0e62d5bf
commit 84e5ab598a
3 changed files with 59 additions and 18 deletions

View File

@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { fileURLToPath, URL } from "node:url";
import { isNotFoundPathError, isPathInside } from "../infra/path-guards.js";
const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
@@ -85,10 +85,18 @@ export async function resolveSandboxedMediaSource(params: {
}
let candidate = raw;
if (/^file:\/\//i.test(candidate)) {
try {
candidate = fileURLToPath(candidate);
} catch {
throw new Error(`Invalid file:// URL for sandboxed media: ${raw}`);
const workspaceMappedFromUrl = mapContainerWorkspaceFileUrl({
fileUrl: candidate,
sandboxRoot: params.sandboxRoot,
});
if (workspaceMappedFromUrl) {
candidate = workspaceMappedFromUrl;
} else {
try {
candidate = fileURLToPath(candidate);
} catch {
throw new Error(`Invalid file:// URL for sandboxed media: ${raw}`);
}
}
}
const containerWorkspaceMapped = mapContainerWorkspacePath({
@@ -113,6 +121,34 @@ export async function resolveSandboxedMediaSource(params: {
return sandboxResult.resolved;
}
function mapContainerWorkspaceFileUrl(params: {
fileUrl: string;
sandboxRoot: string;
}): string | undefined {
let parsed: URL;
try {
parsed = new URL(params.fileUrl);
} catch {
return undefined;
}
if (parsed.protocol !== "file:") {
return undefined;
}
// Sandbox paths are Linux-style (/workspace/*). Parse the URL path directly so
// Windows hosts can still accept file:///workspace/... media references.
const normalizedPathname = decodeURIComponent(parsed.pathname).replace(/\\/g, "/");
if (
normalizedPathname !== SANDBOX_CONTAINER_WORKDIR &&
!normalizedPathname.startsWith(`${SANDBOX_CONTAINER_WORKDIR}/`)
) {
return undefined;
}
return mapContainerWorkspacePath({
candidate: normalizedPathname,
sandboxRoot: params.sandboxRoot,
});
}
function mapContainerWorkspacePath(params: {
candidate: string;
sandboxRoot: string;