From ab2318b5953098ee5513026ed7bece9dcc303035 Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Fri, 16 Feb 2024 00:21:51 -0500 Subject: [PATCH] feat(core): run commands directly --- docs/generated/devkit/Task.md | 18 ++ e2e/nx-misc/src/extras.test.ts | 6 + e2e/nx-run/src/run.test.ts | 1 + e2e/webpack/src/webpack.test.ts | 1 - packages/nx/src/config/task-graph.ts | 8 + .../run-commands/run-commands.impl.ts | 200 +++++++++++++----- .../tasks-runner/create-task-graph.spec.ts | 42 ++++ .../nx/src/tasks-runner/create-task-graph.ts | 6 +- .../src/tasks-runner/default-tasks-runner.ts | 1 - .../forked-process-task-runner.ts | 4 +- .../nx/src/tasks-runner/task-orchestrator.ts | 70 ++++-- 11 files changed, 281 insertions(+), 76 deletions(-) diff --git a/docs/generated/devkit/Task.md b/docs/generated/devkit/Task.md index 686bac2a5e6f20..bc638023fc5a91 100644 --- a/docs/generated/devkit/Task.md +++ b/docs/generated/devkit/Task.md @@ -8,9 +8,11 @@ A representation of the invocation of an Executor - [cache](../../devkit/documents/Task#cache): boolean - [endTime](../../devkit/documents/Task#endtime): number +- [executor](../../devkit/documents/Task#executor): string - [hash](../../devkit/documents/Task#hash): string - [hashDetails](../../devkit/documents/Task#hashdetails): Object - [id](../../devkit/documents/Task#id): string +- [options](../../devkit/documents/Task#options): Record - [outputs](../../devkit/documents/Task#outputs): string[] - [overrides](../../devkit/documents/Task#overrides): any - [projectRoot](../../devkit/documents/Task#projectroot): string @@ -35,6 +37,14 @@ Unix timestamp of when a Batch Task ends --- +### executor + +• `Optional` **executor**: `string` + +the executor to use to run the task + +--- + ### hash • `Optional` **hash**: `string` @@ -68,6 +78,14 @@ Unique ID --- +### options + +• `Optional` **options**: `Record`\<`string`, `any`\> + +The options of the executor + +--- + ### outputs • **outputs**: `string`[] diff --git a/e2e/nx-misc/src/extras.test.ts b/e2e/nx-misc/src/extras.test.ts index 21b9db9c1634ec..ff6b5823c7e1dc 100644 --- a/e2e/nx-misc/src/extras.test.ts +++ b/e2e/nx-misc/src/extras.test.ts @@ -175,6 +175,12 @@ describe('Extra Nx Misc Tests', () => { const result = runCLI( `run ${mylib}:${echoTarget} --var1=a --var2=b --var-hyphen=c --varCamelCase=d` ); + console.log('result', result); + console.log( + runCLI( + `run ${mylib}:${echoTarget} --var1=a --var2=b --var-hyphen=c --varCamelCase=d --verbose` + ) + ); expect(result).toContain('var1: a'); expect(result).toContain('var2: b'); expect(result).toContain('hyphen: c'); diff --git a/e2e/nx-run/src/run.test.ts b/e2e/nx-run/src/run.test.ts index 02417680b415e2..f78f05f31cfe43 100644 --- a/e2e/nx-run/src/run.test.ts +++ b/e2e/nx-run/src/run.test.ts @@ -231,6 +231,7 @@ describe('Nx Running Tests', () => { .split('\n') .map((r) => r.trim()) .filter((r) => r); + console.log('withBai', withBail); withBail = withBail.slice(withBail.indexOf('Failed tasks:')); expect(withBail.length).toEqual(2); if (withBail[1] === `- ${myapp1}:error`) { diff --git a/e2e/webpack/src/webpack.test.ts b/e2e/webpack/src/webpack.test.ts index 9837e29e1efa15..240bcc65bee872 100644 --- a/e2e/webpack/src/webpack.test.ts +++ b/e2e/webpack/src/webpack.test.ts @@ -1,5 +1,4 @@ import { - checkFilesExist, cleanupProject, newProject, rmDist, diff --git a/packages/nx/src/config/task-graph.ts b/packages/nx/src/config/task-graph.ts index 573f691ccc220d..49b585eb64e360 100644 --- a/packages/nx/src/config/task-graph.ts +++ b/packages/nx/src/config/task-graph.ts @@ -27,6 +27,14 @@ export interface Task { * Overrides for the configured options of the target */ overrides: any; + /** + * the executor to use to run the task + */ + executor?: string; + /** + * The options of the executor + */ + options?: Record; /** * The outputs the task may produce diff --git a/packages/nx/src/executors/run-commands/run-commands.impl.ts b/packages/nx/src/executors/run-commands/run-commands.impl.ts index e1e7b4d5c4cac7..ed1c78691808a9 100644 --- a/packages/nx/src/executors/run-commands/run-commands.impl.ts +++ b/packages/nx/src/executors/run-commands/run-commands.impl.ts @@ -51,6 +51,8 @@ export interface RunCommandsOptions extends Json { args?: string | string[]; envFile?: string; __unparsed__: string[]; + usePty?: boolean; + streamOutput?: boolean; } const propKeys = [ @@ -62,6 +64,10 @@ const propKeys = [ 'cwd', 'args', 'envFile', + 'env', + '__unparsed__', + 'usePty', + 'streamOutput', ]; export interface NormalizedRunCommandsOptions extends RunCommandsOptions { @@ -80,6 +86,7 @@ export default async function ( context: ExecutorContext ): Promise<{ success: boolean; + terminalOutput: string; }> { await loadEnvVars(options.envFile); const normalized = normalizeOptions(options); @@ -100,10 +107,10 @@ export default async function ( } try { - const success = options.parallel + const result = options.parallel ? await runInParallel(normalized, context) : await runSerially(normalized, context); - return { success }; + return result; } catch (e) { if (process.env.NX_VERBOSE_LOGGING === 'true') { console.error(e); @@ -117,7 +124,7 @@ export default async function ( async function runInParallel( options: NormalizedRunCommandsOptions, context: ExecutorContext -) { +): Promise<{ success: boolean; terminalOutput: string }> { const procs = options.commands.map((c) => createProcess( c, @@ -125,35 +132,59 @@ async function runInParallel( options.color, calculateCwd(options.cwd, context), options.env ?? {}, - true - ).then((result) => ({ + true, + options.usePty, + options.streamOutput + ).then((result: { success: boolean; terminalOutput: string }) => ({ result, command: c.command, })) ); + let terminalOutput = ''; if (options.readyWhen) { - const r = await Promise.race(procs); - if (!r.result) { - process.stderr.write( - `Warning: command "${r.command}" exited with non-zero status code` - ); - return false; + const r: { + result: { success: boolean; terminalOutput: string }; + command: string; + } = await Promise.race(procs); + terminalOutput += r.result.terminalOutput; + if (!r.result.success) { + const output = `Warning: command "${r.command}" exited with non-zero status code`; + terminalOutput += output; + if (options.streamOutput) { + process.stderr.write(output); + } + return { success: false, terminalOutput }; } else { - return true; + return { success: true, terminalOutput }; } } else { - const r = await Promise.all(procs); - const failed = r.filter((v) => !v.result); + const r: { + result: { success: boolean; terminalOutput: string }; + command: string; + }[] = await Promise.all(procs); + terminalOutput += r.map((f) => f.result.terminalOutput).join(''); + const failed = r.filter((v) => !v.result.success); if (failed.length > 0) { - failed.forEach((f) => { - process.stderr.write( - `Warning: command "${f.command}" exited with non-zero status code` - ); - }); - return false; + const output = failed + .map( + (f) => + `Warning: command "${f.command}" exited with non-zero status code` + ) + .join('\r\n'); + terminalOutput += output; + if (options.streamOutput) { + process.stderr.write(output); + } + return { + success: false, + terminalOutput, + }; } else { - return true; + return { + success: true, + terminalOutput, + }; } } } @@ -188,25 +219,40 @@ function normalizeOptions( async function runSerially( options: NormalizedRunCommandsOptions, context: ExecutorContext -) { +): Promise<{ success: boolean; terminalOutput: string }> { + let terminalOutput = ''; for (const c of options.commands) { - const success = await createProcess( - c, - undefined, - options.color, - calculateCwd(options.cwd, context), - options.env ?? {}, - false - ); - if (!success) { - process.stderr.write( - `Warning: command "${c.command}" exited with non-zero status code` + const result: { success: boolean; terminalOutput: string } = + await createProcess( + c, + undefined, + options.color, + calculateCwd(options.cwd, context), + options.env ?? {}, + false, + options.usePty, + options.streamOutput ); - return false; + terminalOutput += result.terminalOutput; + console.log( + 'runSerially', + result, + c.command, + 'terminalOutput', + terminalOutput + ); + if (!result.success) { + const output = `Warning: command "${c.command}" exited with non-zero status code`; + result.terminalOutput += output; + if (options.streamOutput) { + process.stderr.write(output); + } + return { success: false, terminalOutput }; } } - return true; + console.log('runSerially', terminalOutput); + return { success: true, terminalOutput }; } async function createProcess( @@ -220,41 +266,57 @@ async function createProcess( color: boolean, cwd: string, env: Record, - isParallel: boolean -): Promise { + isParallel: boolean, + usePty: boolean = true, + streamOutput: boolean = true +): Promise<{ success: boolean; terminalOutput: string }> { env = processEnv(color, cwd, env); + console.log( + 'createProcess', + process.env.NX_NATIVE_COMMAND_RUNNER !== 'false' && + process.stdout.isTTY && + !commandConfig.prefix && + !isParallel && + usePty, + process.env.NX_NATIVE_COMMAND_RUNNER, + process.stdout.isTTY, + commandConfig.prefix, + isParallel, + usePty + ); // The rust runCommand is always a tty, so it will not look nice in parallel and if we need prefixes // currently does not work properly in windows if ( process.env.NX_NATIVE_COMMAND_RUNNER !== 'false' && process.stdout.isTTY && !commandConfig.prefix && - !isParallel + !isParallel && + usePty ) { const cp = new PseudoTtyProcess( - runCommand(commandConfig.command, cwd, env) + runCommand(commandConfig.command, cwd, env, !streamOutput) ); + let terminalOutput = ''; return new Promise((res) => { cp.onOutput((output) => { + terminalOutput += output; if (readyWhen && output.indexOf(readyWhen) > -1) { - res(true); + res({ success: true, terminalOutput }); } }); cp.onExit((code) => { - if (code === 0) { - res(true); - } else if (code >= 128) { + if (code >= 128) { process.exit(code); } else { - res(false); + res({ success: code === 0, terminalOutput }); } }); }); } - return nodeProcess(commandConfig, color, cwd, env, readyWhen); + return nodeProcess(commandConfig, cwd, env, readyWhen, streamOutput); } function nodeProcess( @@ -264,11 +326,12 @@ function nodeProcess( bgColor?: string; prefix?: string; }, - color: boolean, cwd: string, env: Record, - readyWhen: string -): Promise { + readyWhen: string, + streamOutput = true +): Promise<{ success: boolean; terminalOutput: string }> { + let terminalOutput = ''; return new Promise((res) => { const childProcess = exec(commandConfig.command, { maxBuffer: LARGE_BUFFER, @@ -287,24 +350,43 @@ function nodeProcess( process.on('SIGQUIT', processExitListener); childProcess.stdout.on('data', (data) => { - process.stdout.write(addColorAndPrefix(data, commandConfig)); + const output = addColorAndPrefix(data, commandConfig); + terminalOutput += output; + if (streamOutput) { + process.stdout.write(output); + } + console.log( + 'nodeProcess', + output, + readyWhen, + data.toString(), + terminalOutput + ); if (readyWhen && data.toString().indexOf(readyWhen) > -1) { - res(true); + res({ success: true, terminalOutput }); } }); childProcess.stderr.on('data', (err) => { - process.stderr.write(addColorAndPrefix(err, commandConfig)); + const output = addColorAndPrefix(err, commandConfig); + terminalOutput += output; + if (streamOutput) { + process.stderr.write(output); + } if (readyWhen && err.toString().indexOf(readyWhen) > -1) { - res(true); + res({ success: true, terminalOutput }); } }); childProcess.on('error', (err) => { - process.stderr.write(addColorAndPrefix(err.toString(), commandConfig)); - res(false); + const ouptput = addColorAndPrefix(err.toString(), commandConfig); + terminalOutput += ouptput; + if (streamOutput) { + process.stderr.write(ouptput); + } + res({ success: false, terminalOutput }); }); childProcess.on('exit', (code) => { if (!readyWhen) { - res(code === 0); + res({ success: code === 0, terminalOutput }); } }); }); @@ -345,13 +427,15 @@ function calculateCwd( } function processEnv(color: boolean, cwd: string, env: Record) { + const localEnv = appendLocalEnv({ cwd: cwd ?? process.cwd() }); const res = { ...process.env, - ...appendLocalEnv({ cwd: cwd ?? process.cwd() }), + ...localEnv, ...env, }; + res.PATH = localEnv.PATH; // need to override PATH to make sure we are using the local node_modules - if (color) { + if (!!color) { res.FORCE_COLOR = `${color}`; } return res; @@ -364,7 +448,7 @@ export function interpolateArgsIntoCommand( 'args' | 'parsedArgs' | '__unparsed__' >, forwardAllArgs: boolean -) { +): string { if (command.indexOf('{args.') > -1) { const regex = /{args\.([^}]+)}/g; return command.replace(regex, (_, group: string) => diff --git a/packages/nx/src/tasks-runner/create-task-graph.spec.ts b/packages/nx/src/tasks-runner/create-task-graph.spec.ts index dde29f32678aa6..62a4d2f92890f5 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.spec.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.spec.ts @@ -104,6 +104,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'test', }, + executor: 'nx:run-commands', outputs: [], overrides: { a: 123 }, projectRoot: 'app1-root', @@ -134,6 +135,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'test', }, + executor: 'nx:run-commands', outputs: [], overrides: { a: 123 }, projectRoot: 'app1-root', @@ -144,6 +146,7 @@ describe('createTaskGraph', () => { project: 'lib1', target: 'test', }, + executor: 'nx:run-commands', outputs: [], overrides: { a: 123 }, projectRoot: 'lib1-root', @@ -283,6 +286,7 @@ describe('createTaskGraph', () => { target: 'compile', configuration: 'libDefault', }, + executor: 'my-executor', outputs: [], overrides: {}, projectRoot: 'lib1-root', @@ -293,6 +297,7 @@ describe('createTaskGraph', () => { project: 'lib2', target: 'compile', }, + executor: 'my-executor', outputs: [], overrides: { __overrides_unparsed__: [], @@ -325,6 +330,7 @@ describe('createTaskGraph', () => { target: 'compile', configuration: 'ci', }, + executor: 'my-executor', outputs: [], overrides: {}, projectRoot: 'app1-root', @@ -336,6 +342,7 @@ describe('createTaskGraph', () => { target: 'compile', configuration: 'libDefault', }, + executor: 'my-executor', outputs: [], overrides: { __overrides_unparsed__: [], @@ -349,6 +356,7 @@ describe('createTaskGraph', () => { target: 'compile', configuration: 'ci', }, + executor: 'my-executor', outputs: [], overrides: { __overrides_unparsed__: [], @@ -454,6 +462,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'my-executor', }, 'lib3:compile': { id: 'lib3:compile', @@ -466,6 +475,7 @@ describe('createTaskGraph', () => { project: 'lib3', target: 'compile', }, + executor: 'my-executor', }, }, }); @@ -491,6 +501,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'test', }, + executor: 'nx:run-commands', outputs: [], overrides: { a: '--value=app1-root' }, projectRoot: 'app1-root', @@ -522,6 +533,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'test', }, + executor: 'nx:run-commands', outputs: [], overrides: { a: '--base-href=/app1-root${deploymentId}' }, projectRoot: 'app1-root', @@ -636,6 +648,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { myFlag: 'flag value' }, projectRoot: 'app1-root', @@ -646,6 +659,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'precompile', }, + executor: 'nx:run-commands', outputs: [], overrides: { myFlag: 'flag value' }, projectRoot: 'app1-root', @@ -656,6 +670,7 @@ describe('createTaskGraph', () => { project: 'lib1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { myFlag: 'flag value' }, projectRoot: 'lib1-root', @@ -666,6 +681,7 @@ describe('createTaskGraph', () => { project: 'lib2', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [] }, projectRoot: 'lib2-root', @@ -701,6 +717,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -713,6 +730,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'precompile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -725,6 +743,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'precompile2', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -737,6 +756,7 @@ describe('createTaskGraph', () => { project: 'lib1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -774,6 +794,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -786,6 +807,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'precompile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -798,6 +820,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'precompile2', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -810,6 +833,7 @@ describe('createTaskGraph', () => { project: 'lib1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -916,6 +940,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -928,6 +953,7 @@ describe('createTaskGraph', () => { project: 'lib1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -940,6 +966,7 @@ describe('createTaskGraph', () => { project: 'lib2', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -952,6 +979,7 @@ describe('createTaskGraph', () => { project: 'lib3', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1077,6 +1105,7 @@ describe('createTaskGraph', () => { 'infra1:apply': { id: 'infra1:apply', target: { project: 'infra1', target: 'apply' }, + executor: 'nx:run-commands', projectRoot: 'infra1-root', outputs: [], overrides: { myFlag: 'flag value' }, @@ -1084,6 +1113,7 @@ describe('createTaskGraph', () => { 'app2:compile': { id: 'app2:compile', target: { project: 'app2', target: 'compile' }, + executor: 'nx:run-commands', projectRoot: 'app2-root', outputs: [], overrides: { __overrides_unparsed__: [] }, @@ -1091,6 +1121,7 @@ describe('createTaskGraph', () => { 'coreInfra:apply': { id: 'coreInfra:apply', target: { project: 'coreInfra', target: 'apply' }, + executor: 'nx:run-commands', projectRoot: 'infra3-root', outputs: [], overrides: { myFlag: 'flag value' }, @@ -1098,6 +1129,7 @@ describe('createTaskGraph', () => { 'app1:compile': { id: 'app1:compile', target: { project: 'app1', target: 'compile' }, + executor: 'nx:run-commands', projectRoot: 'app1-root', outputs: [], overrides: { __overrides_unparsed__: [] }, @@ -1105,6 +1137,7 @@ describe('createTaskGraph', () => { 'infra2:apply': { id: 'infra2:apply', target: { project: 'infra2', target: 'apply' }, + executor: 'nx:run-commands', projectRoot: 'infra2-root', outputs: [], overrides: { myFlag: 'flag value' }, @@ -1169,6 +1202,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1181,6 +1215,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'test', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1262,6 +1297,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1274,6 +1310,7 @@ describe('createTaskGraph', () => { project: 'app3', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1352,6 +1389,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1364,6 +1402,7 @@ describe('createTaskGraph', () => { project: 'app3', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1440,6 +1479,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1473,6 +1513,7 @@ describe('createTaskGraph', () => { project: 'app1', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], @@ -1485,6 +1526,7 @@ describe('createTaskGraph', () => { project: 'app2', target: 'compile', }, + executor: 'nx:run-commands', outputs: [], overrides: { __overrides_unparsed__: [], diff --git a/packages/nx/src/tasks-runner/create-task-graph.ts b/packages/nx/src/tasks-runner/create-task-graph.ts index 41ac9c9b48fe44..13e33dea0abd6d 100644 --- a/packages/nx/src/tasks-runner/create-task-graph.ts +++ b/packages/nx/src/tasks-runner/create-task-graph.ts @@ -317,7 +317,9 @@ export class ProcessTasks { ); } - if (!project.data.targets[target].executor) { + const executor = project.data.targets[target].executor; + const options = project.data.targets[target].options; + if (!executor) { throw new Error( `Target "${project.name}:${target}" does not have an executor configured` ); @@ -347,6 +349,8 @@ export class ProcessTasks { ), // TODO(v19): Remove cast here after typing is moved back onto TargetConfiguration cache: (project.data.targets[target] as any).cache, + executor, + options, }; } diff --git a/packages/nx/src/tasks-runner/default-tasks-runner.ts b/packages/nx/src/tasks-runner/default-tasks-runner.ts index 75e80cdc9386b8..a5cb33bfd7473d 100644 --- a/packages/nx/src/tasks-runner/default-tasks-runner.ts +++ b/packages/nx/src/tasks-runner/default-tasks-runner.ts @@ -1,6 +1,5 @@ import { TasksRunner, TaskStatus } from './tasks-runner'; import { TaskOrchestrator } from './task-orchestrator'; -import { performance } from 'perf_hooks'; import { TaskHasher } from '../hasher/task-hasher'; import { LifeCycle } from './life-cycle'; import { ProjectGraph } from '../config/project-graph'; diff --git a/packages/nx/src/tasks-runner/forked-process-task-runner.ts b/packages/nx/src/tasks-runner/forked-process-task-runner.ts index fe661918e6a430..15730c733b0795 100644 --- a/packages/nx/src/tasks-runner/forked-process-task-runner.ts +++ b/packages/nx/src/tasks-runner/forked-process-task-runner.ts @@ -14,8 +14,8 @@ import { } from './batch/batch-messages'; import { stripIndents } from '../utils/strip-indents'; import { Task, TaskGraph } from '../config/task-graph'; -import { Readable, Transform } from 'stream'; -import { ChildProcess as NativeChildProcess, nxFork } from '../native'; +import { Transform } from 'stream'; +import { nxFork } from '../native'; import { PsuedoIPCServer } from './psuedo-ipc'; import { FORKED_PROCESS_OS_SOCKET_PATH } from '../daemon/socket-utils'; import { PseudoTtyProcess } from '../utils/child-process'; diff --git a/packages/nx/src/tasks-runner/task-orchestrator.ts b/packages/nx/src/tasks-runner/task-orchestrator.ts index da7daa0450ebd5..97c5bb12a8d4f6 100644 --- a/packages/nx/src/tasks-runner/task-orchestrator.ts +++ b/packages/nx/src/tasks-runner/task-orchestrator.ts @@ -1,6 +1,7 @@ import { defaultMaxListeners } from 'events'; import { performance } from 'perf_hooks'; import { TaskHasher } from '../hasher/task-hasher'; +import runCommandsImpl from '../executors/run-commands/run-commands.impl'; import { ForkedProcessTaskRunner } from './forked-process-task-runner'; import { Cache } from './cache'; import { DefaultTasksRunnerOptions } from './default-tasks-runner'; @@ -8,6 +9,7 @@ import { TaskStatus } from './tasks-runner'; import { calculateReverseDeps, getExecutorForTask, + getPrintableCommandArgsForTask, isCacheableTask, removeTasksFromTaskGraph, shouldStreamOutput, @@ -24,6 +26,8 @@ import { getTaskSpecificEnv, } from './task-env'; import * as os from 'os'; +import { workspaceRoot } from '../utils/workspace-root'; +import { output } from '../utils/output'; export class TaskOrchestrator { private cache = new Cache(this.options); @@ -376,20 +380,60 @@ export class TaskOrchestrator { // the task wasn't cached if (results.length === 0) { - // cache prep - const { code, terminalOutput } = await this.runTaskInForkedProcess( - task, - env, - pipeOutput, - temporaryOutputPath, - streamOutput - ); + const shouldPrefix = + streamOutput && process.env.NX_PREFIX_OUTPUT === 'true'; + const isRunOne = this.initiatingProject != null; + console.log({ shouldPrefix, isRunOne, streamOutput }); + if (task.executor === 'nx:run-commands' && !shouldPrefix) { + console.log(task.options, task.overrides); + if (streamOutput) { + const args = getPrintableCommandArgsForTask(task); + output.logCommand(args.join(' ')); + } + const { success, terminalOutput } = await runCommandsImpl( + { + ...task.options, + ...task.overrides, + env, + __unparsed__: task.overrides?.['__overrides_unparsed__'] ?? [], + usePty: isRunOne && !this.tasksSchedule.hasTasks(), + streamOutput, + }, + { + root: workspaceRoot, // only root is needed in runCommandsImpl + } as any + ); - results.push({ - task, - status: code === 0 ? 'success' : 'failure', - terminalOutput, - }); + console.log({ success, terminalOutput }); + const status = success ? 'success' : 'failure'; + if (!streamOutput) { + this.options.lifeCycle.printTaskTerminalOutput( + task, + status, + terminalOutput + ); + } + + results.push({ + task, + status, + terminalOutput, + }); + } else { + // cache prep + const { code, terminalOutput } = await this.runTaskInForkedProcess( + task, + env, + pipeOutput, + temporaryOutputPath, + streamOutput + ); + results.push({ + task, + status: code === 0 ? 'success' : 'failure', + terminalOutput, + }); + } } await this.postRunSteps([task], results, doNotSkipCache, { groupId }); }