nx 19.0.0-canary.20240419-e617e54 → 19.0.0-canary.20240423-b37bfdb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/migrations.json +2 -1
- package/package.json +12 -12
- package/src/core/graph/main.js +1 -1
- package/src/executors/run-commands/run-commands.impl.d.ts +1 -0
- package/src/executors/run-commands/run-commands.impl.js +64 -20
- package/src/executors/run-commands/schema.json +5 -0
- package/src/project-graph/utils/project-configuration-utils.js +1 -1
- package/src/tasks-runner/life-cycles/dynamic-run-many-terminal-output-life-cycle.js +4 -0
- package/src/tasks-runner/life-cycles/dynamic-run-one-terminal-output-life-cycle.js +4 -0
- package/src/tasks-runner/pseudo-terminal.js +6 -0
@@ -7,17 +7,10 @@ const yargsParser = require("yargs-parser");
|
|
7
7
|
const npm_run_path_1 = require("npm-run-path");
|
8
8
|
const chalk = require("chalk");
|
9
9
|
const pseudo_terminal_1 = require("../../tasks-runner/pseudo-terminal");
|
10
|
+
const exit_codes_1 = require("../../utils/exit-codes");
|
10
11
|
exports.LARGE_BUFFER = 1024 * 1000000;
|
11
|
-
|
12
|
-
|
13
|
-
for (const listener of exitListeners) {
|
14
|
-
listener();
|
15
|
-
}
|
16
|
-
}
|
17
|
-
process.on('exit', processExitListener);
|
18
|
-
process.on('SIGTERM', processExitListener);
|
19
|
-
process.on('SIGINT', processExitListener);
|
20
|
-
process.on('SIGQUIT', processExitListener);
|
12
|
+
let pseudoTerminal;
|
13
|
+
const childProcesses = new Set();
|
21
14
|
async function loadEnvVars(path) {
|
22
15
|
if (path) {
|
23
16
|
const result = (await Promise.resolve().then(() => require('dotenv'))).config({ path });
|
@@ -46,8 +39,10 @@ const propKeys = [
|
|
46
39
|
'usePty',
|
47
40
|
'streamOutput',
|
48
41
|
'verbose',
|
42
|
+
'forwardAllArgs',
|
49
43
|
];
|
50
44
|
async function default_1(options, context) {
|
45
|
+
registerProcessListener();
|
51
46
|
await loadEnvVars(options.envFile);
|
52
47
|
const normalized = normalizeOptions(options);
|
53
48
|
if (options.readyWhen && !options.parallel) {
|
@@ -141,14 +136,12 @@ function normalizeOptions(options) {
|
|
141
136
|
options.parsedArgs = parseArgs(unparsedCommandArgs, options.unknownOptions, options.args);
|
142
137
|
options.unparsedCommandArgs = unparsedCommandArgs;
|
143
138
|
options.commands.forEach((c) => {
|
144
|
-
c.command = interpolateArgsIntoCommand(c.command, options, c.forwardAllArgs ?? true);
|
139
|
+
c.command = interpolateArgsIntoCommand(c.command, options, c.forwardAllArgs ?? options.forwardAllArgs ?? true);
|
145
140
|
});
|
146
141
|
return options;
|
147
142
|
}
|
148
143
|
async function runSerially(options, context) {
|
149
|
-
|
150
|
-
? (0, pseudo_terminal_1.getPseudoTerminal)()
|
151
|
-
: null;
|
144
|
+
pseudoTerminal ??= pseudo_terminal_1.PseudoTerminal.isSupported() ? (0, pseudo_terminal_1.getPseudoTerminal)() : null;
|
152
145
|
let terminalOutput = '';
|
153
146
|
for (const c of options.commands) {
|
154
147
|
const result = await createProcess(pseudoTerminal, c, undefined, options.color, calculateCwd(options.cwd, context), options.env ?? {}, false, options.usePty, options.streamOutput);
|
@@ -182,6 +175,7 @@ async function createProcess(pseudoTerminal, commandConfig, readyWhen, color, cw
|
|
182
175
|
jsEnv: env,
|
183
176
|
quiet: !streamOutput,
|
184
177
|
});
|
178
|
+
childProcesses.add(cp);
|
185
179
|
return new Promise((res) => {
|
186
180
|
cp.onOutput((output) => {
|
187
181
|
terminalOutput += output;
|
@@ -212,11 +206,7 @@ function nodeProcess(commandConfig, cwd, env, readyWhen, streamOutput = true) {
|
|
212
206
|
env,
|
213
207
|
cwd,
|
214
208
|
});
|
215
|
-
|
216
|
-
* Ensure the child process is killed when the parent exits
|
217
|
-
*/
|
218
|
-
const childProcessKiller = (signal) => childProcess.kill(signal);
|
219
|
-
exitListeners.add(childProcessKiller);
|
209
|
+
childProcesses.add(childProcess);
|
220
210
|
childProcess.stdout.on('data', (data) => {
|
221
211
|
const output = addColorAndPrefix(data, commandConfig);
|
222
212
|
terminalOutput += output;
|
@@ -246,7 +236,7 @@ function nodeProcess(commandConfig, cwd, env, readyWhen, streamOutput = true) {
|
|
246
236
|
res({ success: false, terminalOutput });
|
247
237
|
});
|
248
238
|
childProcess.on('exit', (code) => {
|
249
|
-
|
239
|
+
childProcesses.delete(childProcess);
|
250
240
|
if (!readyWhen) {
|
251
241
|
res({ success: code === 0, terminalOutput });
|
252
242
|
}
|
@@ -369,3 +359,57 @@ function filterPropKeysFromUnParsedOptions(__unparsed__, unparsedCommandArgs = {
|
|
369
359
|
}
|
370
360
|
return parsedOptions;
|
371
361
|
}
|
362
|
+
let registered = false;
|
363
|
+
function registerProcessListener() {
|
364
|
+
if (registered) {
|
365
|
+
return;
|
366
|
+
}
|
367
|
+
registered = true;
|
368
|
+
// When the nx process gets a message, it will be sent into the task's process
|
369
|
+
process.on('message', (message) => {
|
370
|
+
// this.publisher.publish(message.toString());
|
371
|
+
if (pseudoTerminal) {
|
372
|
+
pseudoTerminal.sendMessageToChildren(message);
|
373
|
+
}
|
374
|
+
childProcesses.forEach((p) => {
|
375
|
+
if ('connected' in p && p.connected) {
|
376
|
+
p.send(message);
|
377
|
+
}
|
378
|
+
});
|
379
|
+
});
|
380
|
+
// Terminate any task processes on exit
|
381
|
+
process.on('exit', () => {
|
382
|
+
childProcesses.forEach((p) => {
|
383
|
+
if ('connected' in p ? p.connected : p.isAlive) {
|
384
|
+
p.kill();
|
385
|
+
}
|
386
|
+
});
|
387
|
+
});
|
388
|
+
process.on('SIGINT', () => {
|
389
|
+
childProcesses.forEach((p) => {
|
390
|
+
if ('connected' in p ? p.connected : p.isAlive) {
|
391
|
+
p.kill('SIGTERM');
|
392
|
+
}
|
393
|
+
});
|
394
|
+
// we exit here because we don't need to write anything to cache.
|
395
|
+
process.exit((0, exit_codes_1.signalToCode)('SIGINT'));
|
396
|
+
});
|
397
|
+
process.on('SIGTERM', () => {
|
398
|
+
childProcesses.forEach((p) => {
|
399
|
+
if ('connected' in p ? p.connected : p.isAlive) {
|
400
|
+
p.kill('SIGTERM');
|
401
|
+
}
|
402
|
+
});
|
403
|
+
// no exit here because we expect child processes to terminate which
|
404
|
+
// will store results to the cache and will terminate this process
|
405
|
+
});
|
406
|
+
process.on('SIGHUP', () => {
|
407
|
+
childProcesses.forEach((p) => {
|
408
|
+
if ('connected' in p ? p.connected : p.isAlive) {
|
409
|
+
p.kill('SIGTERM');
|
410
|
+
}
|
411
|
+
});
|
412
|
+
// no exit here because we expect child processes to terminate which
|
413
|
+
// will store results to the cache and will terminate this process
|
414
|
+
});
|
415
|
+
}
|
@@ -135,6 +135,11 @@
|
|
135
135
|
"$source": "unparsed"
|
136
136
|
},
|
137
137
|
"x-priority": "internal"
|
138
|
+
},
|
139
|
+
"forwardAllArgs": {
|
140
|
+
"type": "boolean",
|
141
|
+
"description": "Whether arguments should be forwarded when interpolation is not present.",
|
142
|
+
"default": true
|
138
143
|
}
|
139
144
|
},
|
140
145
|
"additionalProperties": true,
|
@@ -388,7 +388,7 @@ function mergeTargetConfigurations(target, baseTarget, projectConfigSourceMap, s
|
|
388
388
|
const { configurations: defaultConfigurations, options: defaultOptions, ...baseTargetProperties } = baseTarget ?? {};
|
389
389
|
// Target is "compatible", e.g. executor is defined only once or is the same
|
390
390
|
// in both places. This means that it is likely safe to merge
|
391
|
-
const isCompatible = isCompatibleTarget(
|
391
|
+
const isCompatible = isCompatibleTarget(baseTarget ?? {}, target);
|
392
392
|
// If the targets are not compatible, we would normally overwrite the old target
|
393
393
|
// with the new one. However, we have a special case for targets that have the
|
394
394
|
// ONLY_MODIFIES_EXISTING_TARGET symbol set. This prevents the merged target
|
@@ -24,6 +24,10 @@ const EXTENDED_LEFT_PAD = ` `;
|
|
24
24
|
*/
|
25
25
|
async function createRunManyDynamicOutputRenderer({ projectNames, tasks, args, overrides, }) {
|
26
26
|
cliCursor.hide();
|
27
|
+
// Show the cursor again after the process exits
|
28
|
+
process.on('exit', () => {
|
29
|
+
cliCursor.show();
|
30
|
+
});
|
27
31
|
let resolveRenderIsDonePromise;
|
28
32
|
const renderIsDone = new Promise((resolve) => (resolveRenderIsDonePromise = resolve)).then(() => {
|
29
33
|
clearRenderInterval();
|
@@ -24,6 +24,10 @@ const EXTENDED_LEFT_PAD = ` `;
|
|
24
24
|
*/
|
25
25
|
async function createRunOneDynamicOutputRenderer({ initiatingProject, tasks, args, overrides, }) {
|
26
26
|
cliCursor.hide();
|
27
|
+
// Show the cursor again after the process exits
|
28
|
+
process.on('exit', () => {
|
29
|
+
cliCursor.show();
|
30
|
+
});
|
27
31
|
let resolveRenderIsDonePromise;
|
28
32
|
const renderIsDone = new Promise((resolve) => (resolveRenderIsDonePromise = resolve)).then(() => {
|
29
33
|
clearRenderInterval();
|
@@ -142,6 +142,12 @@ function supportedPtyPlatform() {
|
|
142
142
|
if (process.platform !== 'win32') {
|
143
143
|
return true;
|
144
144
|
}
|
145
|
+
// TODO: Re-enable Windows support when it's stable
|
146
|
+
// Currently, there's an issue with control chars.
|
147
|
+
// See: https://github.com/nrwl/nx/issues/22358
|
148
|
+
if (process.env.NX_WINDOWS_PTY_SUPPORT !== 'true') {
|
149
|
+
return false;
|
150
|
+
}
|
145
151
|
let windowsVersion = os.release().split('.');
|
146
152
|
let windowsBuild = windowsVersion[2];
|
147
153
|
if (!windowsBuild) {
|