From f95862f92f547412906a532121b72dbf06648f30 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Thu, 30 May 2024 13:27:07 -0400 Subject: [PATCH] feat(repo): spin up .ts daemon when running tests that use daemon --- jest.preset.js | 1 + packages/cypress/src/plugins/plugin.ts | 1 + .../eslint/src/generators/init/init.spec.ts | 2 + packages/jest/src/plugins/plugin.spec.ts | 3 ++ packages/nx/src/daemon/client/client.ts | 53 +++++++++++-------- .../message-types/get-context-file-data.ts | 2 - .../daemon/server/handle-context-file-data.ts | 2 +- .../server/handle-get-files-in-directory.ts | 2 +- .../daemon/server/handle-request-file-data.ts | 10 ---- packages/nx/src/daemon/server/server.ts | 29 +++++----- .../plugins/isolation/plugin-pool.ts | 2 - packages/nx/src/utils/all-file-data.ts | 7 +-- packages/nx/src/utils/workspace-context.ts | 4 +- packages/playwright/src/plugins/plugin.ts | 6 +-- scripts/unit-test-setup.js | 3 ++ typedoc-theme/jest.config.ts | 2 + 16 files changed, 68 insertions(+), 61 deletions(-) delete mode 100644 packages/nx/src/daemon/server/handle-request-file-data.ts create mode 100644 scripts/unit-test-setup.js diff --git a/jest.preset.js b/jest.preset.js index 28490c0c213ff3..936907934abf20 100644 --- a/jest.preset.js +++ b/jest.preset.js @@ -12,4 +12,5 @@ module.exports = { coverageReporters: ['html'], maxWorkers: 1, testEnvironment: 'node', + globalSetup: '../../scripts/unit-test-setup.js', }; diff --git a/packages/cypress/src/plugins/plugin.ts b/packages/cypress/src/plugins/plugin.ts index 5313637d35abcd..7634b7f7695f03 100644 --- a/packages/cypress/src/plugins/plugin.ts +++ b/packages/cypress/src/plugins/plugin.ts @@ -210,6 +210,7 @@ async function buildCypressTargets( ? cypressConfig.e2e.excludeSpecPattern.map((p) => join(projectRoot, p)) : [join(projectRoot, cypressConfig.e2e.excludeSpecPattern)]; const specFiles = await globWithWorkspaceContext( + context.workspaceRoot, specPatterns, excludeSpecPatterns ); diff --git a/packages/eslint/src/generators/init/init.spec.ts b/packages/eslint/src/generators/init/init.spec.ts index bcf161b287aefb..140bb2aeb7b309 100644 --- a/packages/eslint/src/generators/init/init.spec.ts +++ b/packages/eslint/src/generators/init/init.spec.ts @@ -3,6 +3,7 @@ import 'nx/src/internal-testing-utils/mock-project-graph'; import { NxJsonConfiguration, readJson, Tree, updateJson } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { LinterInitOptions, lintInitGenerator } from './init'; +import { setWorkspaceRoot } from 'nx/src/utils/workspace-root'; describe('@nx/eslint:init', () => { let tree: Tree; @@ -10,6 +11,7 @@ describe('@nx/eslint:init', () => { beforeEach(() => { tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + setWorkspaceRoot(tree.root); options = { addPlugin: true, }; diff --git a/packages/jest/src/plugins/plugin.spec.ts b/packages/jest/src/plugins/plugin.spec.ts index f2e4a177a1cc3a..deb05e3817085c 100644 --- a/packages/jest/src/plugins/plugin.spec.ts +++ b/packages/jest/src/plugins/plugin.spec.ts @@ -3,6 +3,7 @@ import { join } from 'path'; import { createNodes } from './plugin'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; +import { setWorkspaceRoot } from 'nx/src/utils/workspace-root'; describe('@nx/jest/plugin', () => { let createNodesFunction = createNodes[1]; @@ -25,6 +26,8 @@ describe('@nx/jest/plugin', () => { configFiles: [], }; + setWorkspaceRoot(tempFs.tempDir); + await tempFs.createFiles({ 'proj/jest.config.js': `module.exports = {}`, 'proj/src/unit.spec.ts': '', diff --git a/packages/nx/src/daemon/client/client.ts b/packages/nx/src/daemon/client/client.ts index 0fb3fa08804af3..badc128325619d 100644 --- a/packages/nx/src/daemon/client/client.ts +++ b/packages/nx/src/daemon/client/client.ts @@ -4,7 +4,7 @@ import { readFileSync, statSync } from 'fs'; import { FileHandle, open } from 'fs/promises'; import { ensureDirSync, ensureFileSync } from 'fs-extra'; import { connect } from 'net'; -import { join } from 'path'; +import { extname, join } from 'path'; import { performance } from 'perf_hooks'; import { output } from '../../utils/output'; import { getFullOsSocketPath, killSocketOrPath } from '../socket-utils'; @@ -49,9 +49,6 @@ import { NxWorkspaceFiles } from '../../native'; const DAEMON_ENV_SETTINGS = { NX_PROJECT_GLOB_CACHE: 'false', NX_CACHE_PROJECTS_CONFIG: 'false', - - // Used to identify that the code is running in the daemon process. - NX_ON_DAEMON_PROCESS: 'true', }; export type UnregisterCallback = () => void; @@ -283,14 +280,9 @@ export class DaemonClient { return this.sendToDaemonViaQueue(message); } - getWorkspaceContextFileData( - globs: string[], - exclude?: string[] - ): Promise { + getWorkspaceContextFileData(): Promise { const message: HandleContextFileDataMessage = { type: GET_CONTEXT_FILE_DATA, - globs, - exclude, }; return this.sendToDaemonViaQueue(message); } @@ -478,18 +470,35 @@ export class DaemonClient { this._out = await open(DAEMON_OUTPUT_LOG_FILE, 'a'); this._err = await open(DAEMON_OUTPUT_LOG_FILE, 'a'); - const backgroundProcess = spawn( - process.execPath, - [join(__dirname, '../server/start.js')], - { - cwd: workspaceRoot, - stdio: ['ignore', this._out.fd, this._err.fd], - detached: true, - windowsHide: true, - shell: false, - env: { ...process.env, ...DAEMON_ENV_SETTINGS }, - } - ); + // This stuff is only hit during our unit tests, + // as the daemon server is typescript during their execution. + const isTypescript = extname(__filename) === '.ts'; + const workerExt = isTypescript ? 'ts' : 'js'; + + const args = [join(__dirname, `../server/start.${workerExt}`)]; + + // If the daemon is typescript, we need to add the ts-node/register to support it. + if (isTypescript) { + args.unshift('-r', 'ts-node/register'); + } + + const backgroundProcess = spawn(process.execPath, args, { + cwd: workspaceRoot, + stdio: ['ignore', this._out.fd, this._err.fd], + detached: true, + windowsHide: true, + shell: false, + env: { + ...process.env, + ...DAEMON_ENV_SETTINGS, + ...(isTypescript + ? { + // Ensures that the worker uses the same tsconfig as the main process + TS_NODE_PROJECT: join(__dirname, '../../../tsconfig.lib.json'), + } + : {}), + }, + }); backgroundProcess.unref(); /** diff --git a/packages/nx/src/daemon/message-types/get-context-file-data.ts b/packages/nx/src/daemon/message-types/get-context-file-data.ts index c804b93eaf340a..935f1cbb876091 100644 --- a/packages/nx/src/daemon/message-types/get-context-file-data.ts +++ b/packages/nx/src/daemon/message-types/get-context-file-data.ts @@ -2,8 +2,6 @@ export const GET_CONTEXT_FILE_DATA = 'GET_CONTEXT_FILE_DATA' as const; export type HandleContextFileDataMessage = { type: typeof GET_CONTEXT_FILE_DATA; - globs: string[]; - exclude?: string[]; }; export function isHandleContextFileDataMessage( diff --git a/packages/nx/src/daemon/server/handle-context-file-data.ts b/packages/nx/src/daemon/server/handle-context-file-data.ts index 24d9243d45c2a5..52468d72033d86 100644 --- a/packages/nx/src/daemon/server/handle-context-file-data.ts +++ b/packages/nx/src/daemon/server/handle-context-file-data.ts @@ -3,7 +3,7 @@ import { workspaceRoot } from '../../utils/workspace-root'; import { HandlerResult } from './server'; export async function handleContextFileData(): Promise { - const files = getAllFileDataInContext(workspaceRoot); + const files = await getAllFileDataInContext(workspaceRoot); return { response: JSON.stringify(files), description: 'handleContextFileData', diff --git a/packages/nx/src/daemon/server/handle-get-files-in-directory.ts b/packages/nx/src/daemon/server/handle-get-files-in-directory.ts index aa781ab77980b8..adcfe93f82c4e5 100644 --- a/packages/nx/src/daemon/server/handle-get-files-in-directory.ts +++ b/packages/nx/src/daemon/server/handle-get-files-in-directory.ts @@ -5,7 +5,7 @@ import { HandlerResult } from './server'; export async function handleGetFilesInDirectory( dir: string ): Promise { - const files = getFilesInDirectoryUsingContext(workspaceRoot, dir); + const files = await getFilesInDirectoryUsingContext(workspaceRoot, dir); return { response: JSON.stringify(files), description: 'handleNxWorkspaceFiles', diff --git a/packages/nx/src/daemon/server/handle-request-file-data.ts b/packages/nx/src/daemon/server/handle-request-file-data.ts deleted file mode 100644 index 2bfd24e7e16967..00000000000000 --- a/packages/nx/src/daemon/server/handle-request-file-data.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { getAllFileDataInContext } from '../../utils/workspace-context'; -import { workspaceRoot } from '../../utils/workspace-root'; - -export async function handleRequestFileData() { - const response = JSON.stringify(getAllFileDataInContext(workspaceRoot)); - return { - response, - description: 'handleRequestFileData', - }; -} diff --git a/packages/nx/src/daemon/server/server.ts b/packages/nx/src/daemon/server/server.ts index 6310c497c372d1..8590c6a0063d6c 100644 --- a/packages/nx/src/daemon/server/server.ts +++ b/packages/nx/src/daemon/server/server.ts @@ -26,7 +26,6 @@ import { handleRecordOutputsHash, } from './handle-outputs-tracking'; import { handleProcessInBackground } from './handle-process-in-background'; -import { handleRequestFileData } from './handle-request-file-data'; import { handleRequestProjectGraph } from './handle-request-project-graph'; import { handleRequestShutdown } from './handle-request-shutdown'; import { serverLogger } from './logger'; @@ -132,11 +131,12 @@ async function handleMessage(socket, data: string) { ); } - if (daemonIsOutdated()) { + const outdated = daemonIsOutdated(); + if (outdated) { await respondWithErrorAndExit( socket, - `Lock files changed`, - new Error('LOCK-FILES-CHANGED') + `Daemon outdated`, + new Error(outdated) ); } @@ -164,10 +164,6 @@ async function handleMessage(socket, data: string) { ); } else if (payload.type === 'HASH_TASKS') { await handleResult(socket, 'HASH_TASKS', () => handleHashTasks(payload)); - } else if (payload.type === 'REQUEST_FILE_DATA') { - await handleResult(socket, 'REQUEST_FILE_DATA', () => - handleRequestFileData() - ); } else if (payload.type === 'PROCESS_IN_BACKGROUND') { await handleResult(socket, 'PROCESS_IN_BACKGROUND', () => handleProcessInBackground(payload) @@ -274,11 +270,19 @@ function registerProcessTerminationListeners() { let existingLockHash: string | undefined; -function daemonIsOutdated(): boolean { - return nxVersionChanged() || lockFileHashChanged(); +function daemonIsOutdated(): string | null { + if (nxVersionChanged()) { + return 'NX_VERSION_CHANGED'; + } else if (lockFileHashChanged()) { + return 'LOCK_FILES_CHANGED'; + } + return null; } function nxVersionChanged(): boolean { + if (process.env.NX_SKIP_NX_VERSION_CHECK === 'true') { + return false; + } return nxVersion !== getInstalledNxVersion(); } @@ -332,10 +336,11 @@ const handleWorkspaceChanges: FileWatcherCallback = async ( try { resetInactivityTimeout(handleInactivityTimeout); - if (daemonIsOutdated()) { + const outdatedReason = daemonIsOutdated(); + if (outdatedReason) { await handleServerProcessTermination({ server, - reason: 'Lock file changed', + reason: outdatedReason, }); return; } diff --git a/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts b/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts index 64a86e394bbdae..ec404a4a6321d1 100644 --- a/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts +++ b/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts @@ -39,8 +39,6 @@ export function loadRemoteNxPlugin( : {}), }; - delete env.NX_ON_DAEMON_PROCESS; - const worker = fork(workerPath, [], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'], env, diff --git a/packages/nx/src/utils/all-file-data.ts b/packages/nx/src/utils/all-file-data.ts index 4a6a36271b7c7a..7ce3da07886b33 100644 --- a/packages/nx/src/utils/all-file-data.ts +++ b/packages/nx/src/utils/all-file-data.ts @@ -1,12 +1,7 @@ import { FileData } from '../config/project-graph'; -import { daemonClient } from '../daemon/client/client'; import { getAllFileDataInContext } from './workspace-context'; import { workspaceRoot } from './workspace-root'; export function allFileData(): Promise { - if (daemonClient.enabled()) { - return daemonClient.getAllFileData(); - } else { - return Promise.resolve(getAllFileDataInContext(workspaceRoot)); - } + return getAllFileDataInContext(workspaceRoot); } diff --git a/packages/nx/src/utils/workspace-context.ts b/packages/nx/src/utils/workspace-context.ts index 9640965e758f31..68ee35ee3633a7 100644 --- a/packages/nx/src/utils/workspace-context.ts +++ b/packages/nx/src/utils/workspace-context.ts @@ -81,7 +81,7 @@ export function updateFilesInContext( return workspaceContext?.incrementalUpdate(updatedFiles, deletedFiles); } -export function getAllFileDataInContext(workspaceRoot: string) { +export async function getAllFileDataInContext(workspaceRoot: string) { if (isOnDaemon() || !daemonClient.enabled()) { ensureContextAvailable(workspaceRoot); return workspaceContext.allFileData(); @@ -89,7 +89,7 @@ export function getAllFileDataInContext(workspaceRoot: string) { return daemonClient.getAllFileData(); } -export function getFilesInDirectoryUsingContext( +export async function getFilesInDirectoryUsingContext( workspaceRoot: string, dir: string ) { diff --git a/packages/playwright/src/plugins/plugin.ts b/packages/playwright/src/plugins/plugin.ts index 69d143a3560e56..7cc373d1747840 100644 --- a/packages/playwright/src/plugins/plugin.ts +++ b/packages/playwright/src/plugins/plugin.ts @@ -163,7 +163,7 @@ async function buildPlaywrightTargets( playwrightConfig.testMatch ??= '**/*.@(spec|test).?(c|m)[jt]s?(x)'; const dependsOn: TargetConfiguration['dependsOn'] = []; - forEachTestFile( + await forEachTestFile( (testFile) => { const relativeSpecFilePath = normalizePath( relative(projectRoot, testFile) @@ -210,7 +210,7 @@ async function buildPlaywrightTargets( return { targets, metadata }; } -function forEachTestFile( +async function forEachTestFile( cb: (path: string) => void, opts: { context: CreateNodesContext; @@ -218,7 +218,7 @@ function forEachTestFile( config: PlaywrightTestConfig; } ) { - const files = getFilesInDirectoryUsingContext( + const files = await getFilesInDirectoryUsingContext( opts.context.workspaceRoot, opts.path ); diff --git a/scripts/unit-test-setup.js b/scripts/unit-test-setup.js new file mode 100644 index 00000000000000..dbbd3e8ea52504 --- /dev/null +++ b/scripts/unit-test-setup.js @@ -0,0 +1,3 @@ +module.exports = () => { + process.env.NX_DAEMON = 'false'; +}; diff --git a/typedoc-theme/jest.config.ts b/typedoc-theme/jest.config.ts index 69cf4a39427b9c..9b0342cf74a083 100644 --- a/typedoc-theme/jest.config.ts +++ b/typedoc-theme/jest.config.ts @@ -14,5 +14,7 @@ export default { resolver: '../scripts/patched-jest-resolver.js', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], coverageDirectory: '../coverage/typedoc-theme', + globalSetup: null, + globalTeardown: null, preset: '../jest.preset.js', };