diff --git a/packages/@sanity/cli-test/scripts/copy-fixtures.ts b/packages/@sanity/cli-test/scripts/copy-fixtures.ts index e3c9b527c..3447e9489 100644 --- a/packages/@sanity/cli-test/scripts/copy-fixtures.ts +++ b/packages/@sanity/cli-test/scripts/copy-fixtures.ts @@ -6,7 +6,7 @@ // eslint-disable-next-line n/no-unsupported-features/node-builtins import {cp, mkdir, readFile, writeFile} from 'node:fs/promises' -import {dirname, join, resolve} from 'node:path' +import {basename, dirname, join, resolve} from 'node:path' import {parse as parseYaml} from 'yaml' @@ -89,7 +89,7 @@ async function copyFixtures() { // Copy the fixture, excluding node_modules, .turbo and (unless specified) dist directories await cp(sourceDir, targetDir, { filter: (src) => { - const name = src.split('/').pop() + const name = basename(src) return ( name !== 'node_modules' && name !== '.turbo' && diff --git a/packages/@sanity/cli-test/src/test/testFixture.ts b/packages/@sanity/cli-test/src/test/testFixture.ts index dd4a3a05a..eb089b365 100644 --- a/packages/@sanity/cli-test/src/test/testFixture.ts +++ b/packages/@sanity/cli-test/src/test/testFixture.ts @@ -155,8 +155,20 @@ export async function testFixture( const srcPath = join(srcNodeModules, entry.name) // Follow symlinks (e.g. pnpm's `node_modules/` → `.pnpm/...`) so // they get a 'dir' type on Windows — a file-typed symlink to a directory - // throws EPERM on stat. - const targetStats = entry.isSymbolicLink() ? await stat(srcPath) : entry + // throws EPERM on stat. Skip dangling symlinks: stat throws ENOENT when + // the target is missing (can happen with cross-OS turbo cache replay + // where Windows-absolute symlink targets don't resolve on Linux). + let targetStats: {isDirectory: () => boolean} + if (entry.isSymbolicLink()) { + try { + targetStats = await stat(srcPath) + } catch (err) { + if (err instanceof Error && 'code' in err && err.code === 'ENOENT') continue + throw err + } + } else { + targetStats = entry + } await symlink( srcPath, join(destNodeModules, entry.name),