Skip to content

Commit 2031c44

Browse files
committed
[rush] Add --node-diagnostic-dir parameter
1 parent 4eee6bc commit 2031c44

File tree

5 files changed

+142
-3
lines changed

5 files changed

+142
-3
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "Add a new command line parameter `--node-diagnostic-dir=DIR` to phased commands that, when specified, tells all child build processes to write NodeJS diagnostics into `${DIR}/${packageName}/${phaseIdentifier}`. This is useful if `--cpu-prof` or `--heap-prof` are enabled, to avoid polluting workspace folders.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush"
10+
}

libraries/rush-lib/src/api/test/__snapshots__/RushCommandLine.test.ts.snap

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,14 @@ Object {
12441244
"required": false,
12451245
"shortName": undefined,
12461246
},
1247+
Object {
1248+
"description": "Specifies the directory where Node.js diagnostic reports will be written. This directory will contain a subdirectory for each project and phase.",
1249+
"environmentVariable": undefined,
1250+
"kind": "String",
1251+
"longName": "--node-diagnostic-dir",
1252+
"required": false,
1253+
"shortName": undefined,
1254+
},
12471255
Object {
12481256
"description": "Selects a single instead of the default locale (en-us) for non-ship builds or all locales for ship builds.",
12491257
"environmentVariable": undefined,
@@ -1382,6 +1390,14 @@ Object {
13821390
"required": false,
13831391
"shortName": undefined,
13841392
},
1393+
Object {
1394+
"description": "Specifies the directory where Node.js diagnostic reports will be written. This directory will contain a subdirectory for each project and phase.",
1395+
"environmentVariable": undefined,
1396+
"kind": "String",
1397+
"longName": "--node-diagnostic-dir",
1398+
"required": false,
1399+
"shortName": undefined,
1400+
},
13851401
Object {
13861402
"description": "Perform a production build, including minification and localization steps",
13871403
"environmentVariable": undefined,
@@ -1507,6 +1523,14 @@ Object {
15071523
"required": false,
15081524
"shortName": undefined,
15091525
},
1526+
Object {
1527+
"description": "Specifies the directory where Node.js diagnostic reports will be written. This directory will contain a subdirectory for each project and phase.",
1528+
"environmentVariable": undefined,
1529+
"kind": "String",
1530+
"longName": "--node-diagnostic-dir",
1531+
"required": false,
1532+
"shortName": undefined,
1533+
},
15101534
Object {
15111535
"description": "Perform a production build, including minification and localization steps",
15121536
"environmentVariable": undefined,

libraries/rush-lib/src/cli/scriptActions/PhasedScriptAction.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import { FlagFile } from '../../api/FlagFile';
5757
import { WeightedOperationPlugin } from '../../logic/operations/WeightedOperationPlugin';
5858
import { getVariantAsync, VARIANT_PARAMETER } from '../../api/Variants';
5959
import { Selection } from '../../logic/Selection';
60+
import { NodeDiagnosticDirPlugin } from '../../logic/operations/NodeDiagnosticDirPlugin';
6061

6162
/**
6263
* Constructor parameters for PhasedScriptAction.
@@ -153,6 +154,7 @@ export class PhasedScriptAction extends BaseScriptAction<IPhasedCommandConfig> {
153154
private readonly _installParameter: CommandLineFlagParameter | undefined;
154155
private readonly _variantParameter: CommandLineStringParameter | undefined;
155156
private readonly _noIPCParameter: CommandLineFlagParameter | undefined;
157+
private readonly _nodeDiagnosticDirParameter: CommandLineStringParameter;
156158

157159
public constructor(options: IPhasedScriptActionOptions) {
158160
super(options);
@@ -284,6 +286,14 @@ export class PhasedScriptAction extends BaseScriptAction<IPhasedCommandConfig> {
284286
});
285287
}
286288

289+
this._nodeDiagnosticDirParameter = this.defineStringParameter({
290+
parameterLongName: '--node-diagnostic-dir',
291+
argumentName: 'DIRECTORY',
292+
description:
293+
'Specifies the directory where Node.js diagnostic reports will be written. ' +
294+
'This directory will contain a subdirectory for each project and phase.'
295+
});
296+
287297
this.defineScriptParameters();
288298

289299
for (const [{ associatedPhases }, tsCommandLineParameter] of this.customParameters) {
@@ -366,6 +376,13 @@ export class PhasedScriptAction extends BaseScriptAction<IPhasedCommandConfig> {
366376
new ConsoleTimelinePlugin(terminal).apply(this.hooks);
367377
}
368378

379+
const diagnosticDir: string | undefined = this._nodeDiagnosticDirParameter.value;
380+
if (diagnosticDir) {
381+
new NodeDiagnosticDirPlugin({
382+
diagnosticDir
383+
}).apply(this.hooks);
384+
}
385+
369386
// Enable the standard summary
370387
new OperationResultSummarizerPlugin(terminal).apply(this.hooks);
371388

libraries/rush-lib/src/cli/test/__snapshots__/CommandLineHelp.test.ts.snap

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ exports[`CommandLineHelp prints the help for each action: build 1`] = `
155155
[-i PROJECT] [-I PROJECT]
156156
[--to-version-policy VERSION_POLICY_NAME]
157157
[--from-version-policy VERSION_POLICY_NAME] [-v] [-c]
158-
[--ignore-hooks] [-s] [-m]
158+
[--ignore-hooks] [--node-diagnostic-dir DIRECTORY] [-s] [-m]
159159
160160
161161
This command is similar to \\"rush rebuild\\", except that \\"rush build\\" performs
@@ -281,6 +281,10 @@ Optional arguments:
281281
--ignore-hooks Skips execution of the \\"eventHooks\\" scripts defined
282282
in rush.json. Make sure you know what you are
283283
skipping.
284+
--node-diagnostic-dir DIRECTORY
285+
Specifies the directory where Node.js diagnostic
286+
reports will be written. This directory will contain
287+
a subdirectory for each project and phase.
284288
-s, --ship Perform a production build, including minification
285289
and localization steps
286290
-m, --minimal Perform a fast build, which disables certain tasks
@@ -432,7 +436,7 @@ exports[`CommandLineHelp prints the help for each action: import-strings 1`] = `
432436
[-i PROJECT] [-I PROJECT]
433437
[--to-version-policy VERSION_POLICY_NAME]
434438
[--from-version-policy VERSION_POLICY_NAME] [-v]
435-
[--ignore-hooks]
439+
[--ignore-hooks] [--node-diagnostic-dir DIRECTORY]
436440
[--locale {en-us,fr-fr,es-es,zh-cn}]
437441
438442
@@ -541,6 +545,10 @@ Optional arguments:
541545
--ignore-hooks Skips execution of the \\"eventHooks\\" scripts defined
542546
in rush.json. Make sure you know what you are
543547
skipping.
548+
--node-diagnostic-dir DIRECTORY
549+
Specifies the directory where Node.js diagnostic
550+
reports will be written. This directory will contain
551+
a subdirectory for each project and phase.
544552
--locale {en-us,fr-fr,es-es,zh-cn}
545553
Selects a single instead of the default locale
546554
(en-us) for non-ship builds or all locales for ship
@@ -1030,7 +1038,8 @@ exports[`CommandLineHelp prints the help for each action: rebuild 1`] = `
10301038
[-i PROJECT] [-I PROJECT]
10311039
[--to-version-policy VERSION_POLICY_NAME]
10321040
[--from-version-policy VERSION_POLICY_NAME] [-v]
1033-
[--ignore-hooks] [-s] [-m]
1041+
[--ignore-hooks] [--node-diagnostic-dir DIRECTORY] [-s]
1042+
[-m]
10341043
10351044
10361045
This command assumes that the package.json file for each project contains a
@@ -1144,6 +1153,10 @@ Optional arguments:
11441153
--ignore-hooks Skips execution of the \\"eventHooks\\" scripts defined
11451154
in rush.json. Make sure you know what you are
11461155
skipping.
1156+
--node-diagnostic-dir DIRECTORY
1157+
Specifies the directory where Node.js diagnostic
1158+
reports will be written. This directory will contain
1159+
a subdirectory for each project and phase.
11471160
-s, --ship Perform a production build, including minification
11481161
and localization steps
11491162
-m, --minimal Perform a fast build, which disables certain tasks
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
import path from 'path';
5+
6+
import { FileSystem } from '@rushstack/node-core-library';
7+
8+
import type { IPhasedCommandPlugin, PhasedCommandHooks } from '../../pluginFramework/PhasedCommandHooks';
9+
import type { IEnvironment } from '../../utilities/Utilities';
10+
import type { Operation } from './Operation';
11+
import type { IOperationRunnerContext } from './IOperationRunner';
12+
import type { IOperationExecutionResult } from './IOperationExecutionResult';
13+
14+
const PLUGIN_NAME: 'NodeDiagnosticDirPlugin' = 'NodeDiagnosticDirPlugin';
15+
16+
export interface INodeDiagnosticDirPluginOptions {
17+
diagnosticDir: string;
18+
}
19+
20+
/**
21+
* Phased command plugin that configures the NodeJS --diagnostic-dir option to contain the project and phase name.
22+
*/
23+
export class NodeDiagnosticDirPlugin implements IPhasedCommandPlugin {
24+
private readonly _diagnosticsDir: string;
25+
26+
public constructor(options: INodeDiagnosticDirPluginOptions) {
27+
this._diagnosticsDir = options.diagnosticDir;
28+
}
29+
30+
public apply(hooks: PhasedCommandHooks): void {
31+
const getDiagnosticDir = (operation: Operation): string | undefined => {
32+
const { associatedProject } = operation;
33+
34+
if (!associatedProject) {
35+
return;
36+
}
37+
38+
const diagnosticDir: string = path.resolve(
39+
this._diagnosticsDir,
40+
associatedProject.packageName,
41+
operation.logFilenameIdentifier
42+
);
43+
44+
return diagnosticDir;
45+
};
46+
47+
hooks.beforeExecuteOperation.tap(
48+
PLUGIN_NAME,
49+
(operation: IOperationRunnerContext & IOperationExecutionResult): undefined => {
50+
const diagnosticDir: string | undefined = getDiagnosticDir(operation.operation);
51+
if (!diagnosticDir) {
52+
return;
53+
}
54+
55+
// Not all versions of NodeJS create the directory, so ensure it exists:
56+
FileSystem.ensureFolder(diagnosticDir);
57+
}
58+
);
59+
60+
hooks.createEnvironmentForOperation.tap(PLUGIN_NAME, (env: IEnvironment, operation: Operation) => {
61+
const diagnosticDir: string | undefined = getDiagnosticDir(operation);
62+
if (!diagnosticDir) {
63+
return env;
64+
}
65+
66+
const { NODE_OPTIONS } = env;
67+
68+
const diagnosticDirEnv: string = `--diagnostic-dir="${diagnosticDir}"`;
69+
70+
env.NODE_OPTIONS = NODE_OPTIONS ? `${NODE_OPTIONS} ${diagnosticDirEnv}` : diagnosticDirEnv;
71+
72+
return env;
73+
});
74+
}
75+
}

0 commit comments

Comments
 (0)