From 24a9670b063c4b4306929255dd2efc1c7a2c21a7 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 29 Oct 2024 14:36:11 +0100 Subject: [PATCH 1/5] fix: don't change the working directory when loading workspace projects --- .../src/node/workspace/resolveWorkspace.ts | 49 ++++++------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/packages/vitest/src/node/workspace/resolveWorkspace.ts b/packages/vitest/src/node/workspace/resolveWorkspace.ts index d62fbd6e2443..77dcd98aaa35 100644 --- a/packages/vitest/src/node/workspace/resolveWorkspace.ts +++ b/packages/vitest/src/node/workspace/resolveWorkspace.ts @@ -2,9 +2,8 @@ import type { Vitest } from '../core' import type { UserConfig, UserWorkspaceConfig, WorkspaceProjectConfiguration } from '../types/config' import type { WorkspaceProject } from '../workspace' import { existsSync, promises as fs } from 'node:fs' -import { isMainThread } from 'node:worker_threads' import fg from 'fast-glob' -import { dirname, relative, resolve } from 'pathe' +import { relative, resolve } from 'pathe' import { mergeConfig } from 'vite' import { configFiles as defaultConfigFiles } from '../../constants' import { initializeProject } from '../workspace' @@ -49,41 +48,25 @@ export async function resolveWorkspace( return acc }, {} as UserConfig) - const cwd = process.cwd() - const projects: WorkspaceProject[] = [] const fileProjects = [...configFiles, ...nonConfigDirectories] - try { - // we have to resolve them one by one because CWD should depend on the project - for (const filepath of fileProjects) { - // if file leads to the root config, then we can just reuse it because we already initialized it - if (vitest.server.config.configFile === filepath) { - const project = await vitest._createCoreProject() - projects.push(project) - continue - } - - const directory = filepath.endsWith('/') - ? filepath.slice(0, -1) - : dirname(filepath) - - if (isMainThread) { - process.chdir(directory) - } - projects.push( - await initializeProject( - filepath, - vitest, - { workspaceConfigPath, test: cliOverrides }, - ), - ) - } - } - finally { - if (isMainThread) { - process.chdir(cwd) + // we have to resolve them one by one because CWD should depend on the project + for (const filepath of fileProjects) { + // if file leads to the root config, then we can just reuse it because we already initialized it + if (vitest.server.config.configFile === filepath) { + const project = await vitest._createCoreProject() + projects.push(project) + continue } + + projects.push( + await initializeProject( + filepath, + vitest, + { workspaceConfigPath, test: cliOverrides }, + ), + ) } const projectPromises: Promise[] = [] From 29428220110a0aedaa1e82e2d34967d2d845ca28 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 29 Oct 2024 14:41:10 +0100 Subject: [PATCH 2/5] perf: resolve project in parallel, but limit concurrency --- .../src/node/workspace/resolveWorkspace.ts | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/packages/vitest/src/node/workspace/resolveWorkspace.ts b/packages/vitest/src/node/workspace/resolveWorkspace.ts index 77dcd98aaa35..0d17233505fd 100644 --- a/packages/vitest/src/node/workspace/resolveWorkspace.ts +++ b/packages/vitest/src/node/workspace/resolveWorkspace.ts @@ -2,6 +2,7 @@ import type { Vitest } from '../core' import type { UserConfig, UserWorkspaceConfig, WorkspaceProjectConfiguration } from '../types/config' import type { WorkspaceProject } from '../workspace' import { existsSync, promises as fs } from 'node:fs' +import { limitConcurrency } from '@vitest/runner/utils' import fg from 'fast-glob' import { relative, resolve } from 'pathe' import { mergeConfig } from 'vite' @@ -48,47 +49,40 @@ export async function resolveWorkspace( return acc }, {} as UserConfig) - const projects: WorkspaceProject[] = [] + const projectPromises: Promise[] = [] const fileProjects = [...configFiles, ...nonConfigDirectories] + const concurrent = limitConcurrency(5) - // we have to resolve them one by one because CWD should depend on the project for (const filepath of fileProjects) { // if file leads to the root config, then we can just reuse it because we already initialized it if (vitest.server.config.configFile === filepath) { - const project = await vitest._createCoreProject() - projects.push(project) + projectPromises.push(concurrent(() => vitest._createCoreProject())) continue } - projects.push( - await initializeProject( + projectPromises.push( + concurrent(() => initializeProject( filepath, vitest, { workspaceConfigPath, test: cliOverrides }, - ), + )), ) } - const projectPromises: Promise[] = [] - projectConfigs.forEach((options, index) => { - // we can resolve these in parallel because process.cwd() is not changed - projectPromises.push(initializeProject( + projectPromises.push(concurrent(() => initializeProject( index, vitest, mergeConfig(options, { workspaceConfigPath, test: cliOverrides }) as any, - )) + ))) }) // pretty rare case - the glob didn't match anything and there are no inline configs - if (!projects.length && !projectPromises.length) { + if (!projectPromises.length) { return [await vitest._createCoreProject()] } - const resolvedProjects = await Promise.all([ - ...projects, - ...projectPromises, - ]) + const resolvedProjects = await Promise.all(projectPromises) const names = new Set() // project names are guaranteed to be unique From 9ba07d25a2dd4082993b08c181ca2f601ffb551b Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 5 Nov 2024 10:47:40 +0100 Subject: [PATCH 3/5] test: remove cwd check --- test/workspaces/space_1/test/env-injected.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/workspaces/space_1/test/env-injected.spec.ts b/test/workspaces/space_1/test/env-injected.spec.ts index 6fb705198d2d..382c388c06ea 100644 --- a/test/workspaces/space_1/test/env-injected.spec.ts +++ b/test/workspaces/space_1/test/env-injected.spec.ts @@ -31,6 +31,9 @@ test('cwd is resolved correctly', () => { expect(process.env.ROOT_CWD_CONFIG).toBe(rootPath) expect(process.env.ROOT_CWD_SERVER).toBe(rootPath) - expect(process.env.SPACE_2_CWD_CONFIG).toBe(spaceRoot) - expect(process.env.SPACE_2_CWD_SERVER).toBe(spaceRoot) + + // ideally, it should be a `spaceRoot`, but support was reverted + // in https://github.com/vitest-dev/vitest/pull/6811 + expect(process.env.SPACE_2_CWD_CONFIG).toBe(rootPath) + expect(process.env.SPACE_2_CWD_SERVER).toBe(rootPath) }) From a1d4d170c2cc8ac7c51173ce21c762b67a908fe3 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 5 Nov 2024 11:19:34 +0100 Subject: [PATCH 4/5] fix: specify project root in the browser server --- packages/browser/src/node/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/browser/src/node/index.ts b/packages/browser/src/node/index.ts index 7d91208dee5b..028e18e433c5 100644 --- a/packages/browser/src/node/index.ts +++ b/packages/browser/src/node/index.ts @@ -41,6 +41,7 @@ export async function createBrowserServer( const vite = await createViteServer({ ...project.options, // spread project config inlined in root workspace config base: '/', + root: project.config.root, logLevel, customLogger: { ...logger, From e5d89975b3c037624ae4c95e3b06bbc8d58cf319 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 5 Nov 2024 12:02:00 +0100 Subject: [PATCH 5/5] chore: remove root --- packages/browser/src/node/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/browser/src/node/index.ts b/packages/browser/src/node/index.ts index 028e18e433c5..7d91208dee5b 100644 --- a/packages/browser/src/node/index.ts +++ b/packages/browser/src/node/index.ts @@ -41,7 +41,6 @@ export async function createBrowserServer( const vite = await createViteServer({ ...project.options, // spread project config inlined in root workspace config base: '/', - root: project.config.root, logLevel, customLogger: { ...logger,