@rushstack/rush-buildxl-graph-plugin 5.153.0

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/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ @rushstack/rush-buildxl-graph-plugin
2
+
3
+ Copyright (c) Microsoft Corporation. All rights reserved.
4
+
5
+ MIT License
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,100 @@
1
+ import { IRushPlugin } from '@rushstack/rush-sdk';
2
+ import { RushConfiguration } from '@rushstack/rush-sdk';
3
+ import { RushSession } from '@rushstack/rush-sdk';
4
+
5
+ /**
6
+ * This plugin is used to drop the build graph to a file for BuildXL to consume.
7
+ * @public
8
+ */
9
+ declare class DropBuildGraphPlugin implements IRushPlugin {
10
+ readonly pluginName: string;
11
+ private readonly _buildXLCommandNames;
12
+ constructor(options: IDropGraphPluginOptions);
13
+ apply(session: RushSession, rushConfiguration: RushConfiguration): void;
14
+ }
15
+ export default DropBuildGraphPlugin;
16
+
17
+ /**
18
+ * This is the type that represents the schema of the drop file
19
+ * @public
20
+ */
21
+ export declare interface IBuildXLRushGraph {
22
+ nodes: IGraphNode[];
23
+ repoSettings: {
24
+ commonTempFolder: string;
25
+ };
26
+ }
27
+
28
+ /**
29
+ * @public
30
+ */
31
+ export declare interface IDropGraphPluginOptions {
32
+ /**
33
+ * The names of the commands that will be used to run BuildXL
34
+ */
35
+ buildXLCommandNames: string[];
36
+ }
37
+
38
+ /**
39
+ * @example
40
+ * ```
41
+ * {
42
+ * "id": "@rushstack/node-core-library#_phase:build",
43
+ * "task": "_phase:build",
44
+ * "package": "@rushstack/node-core-library",
45
+ * "dependencies": [
46
+ * "@rushstack/eslint-patch#_phase:build",
47
+ * "@rushstack/eslint-plugin#_phase:build",
48
+ * "@rushstack/eslint-plugin-packlets#_phase:build",
49
+ * "@rushstack/eslint-plugin-security#_phase:build"
50
+ * ],
51
+ * "workingDirectory": "/repo/libraries/node-core-library",
52
+ * "command": "heft run --only build -- --clean --production --drop-graph ./src/examples/graph.json"
53
+ * }
54
+ * ```
55
+ *
56
+ * See https://github.com/microsoft/BuildXL/blob/adf025c1b96b8106984928df3e9c30c8331bc8d6/Public/Src/Tools/JavaScript/Tool.RushGraphBuilder/src/RushBuildPluginGraph.ts
57
+ *
58
+ * @public
59
+ */
60
+ export declare interface IGraphNode {
61
+ /**
62
+ * The unique id of the Pip
63
+ *
64
+ * @example
65
+ * `@rushstack/node-core-library#_phase:build`
66
+ */
67
+ id: string;
68
+ /**
69
+ * The command to run during the Pip
70
+ */
71
+ command: string;
72
+ /**
73
+ * The working directory of the Pip
74
+ */
75
+ workingDirectory: string;
76
+ /**
77
+ * The project name associated with the Pip
78
+ *
79
+ * @example
80
+ * `@rushstack/node-core-library`
81
+ */
82
+ package: string;
83
+ /**
84
+ * The task name of the Pip
85
+ *
86
+ * @example
87
+ * `_phase:build`
88
+ */
89
+ task: string;
90
+ /**
91
+ * The IDs of the dependencies of the Pip. These are the {@link IGraphNode.id} properties of other Pips.
92
+ */
93
+ dependencies: string[];
94
+ /**
95
+ * If false, the Pip is uncacheable
96
+ */
97
+ cacheable?: false;
98
+ }
99
+
100
+ export { }
@@ -0,0 +1,32 @@
1
+ import { type IRushPlugin, type RushConfiguration, type RushSession } from '@rushstack/rush-sdk';
2
+ import type { IGraphNode } from './GraphProcessor';
3
+ /**
4
+ * This is the type that represents the schema of the drop file
5
+ * @public
6
+ */
7
+ export interface IBuildXLRushGraph {
8
+ nodes: IGraphNode[];
9
+ repoSettings: {
10
+ commonTempFolder: string;
11
+ };
12
+ }
13
+ /**
14
+ * @public
15
+ */
16
+ export interface IDropGraphPluginOptions {
17
+ /**
18
+ * The names of the commands that will be used to run BuildXL
19
+ */
20
+ buildXLCommandNames: string[];
21
+ }
22
+ /**
23
+ * This plugin is used to drop the build graph to a file for BuildXL to consume.
24
+ * @public
25
+ */
26
+ export declare class DropBuildGraphPlugin implements IRushPlugin {
27
+ readonly pluginName: string;
28
+ private readonly _buildXLCommandNames;
29
+ constructor(options: IDropGraphPluginOptions);
30
+ apply(session: RushSession, rushConfiguration: RushConfiguration): void;
31
+ }
32
+ //# sourceMappingURL=DropBuildGraphPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropBuildGraphPlugin.d.ts","sourceRoot":"","sources":["../src/DropBuildGraphPlugin.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,WAAW,EAEhB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,YAAY,EAAE;QACZ,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAID;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,WAAW;IACtD,SAAgB,UAAU,EAAE,MAAM,CAAe;IACjD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAW;gBAE7B,OAAO,EAAE,uBAAuB;IAI5C,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,GAAG,IAAI;CAyD/E"}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.DropBuildGraphPlugin = void 0;
39
+ const rush_sdk_1 = require("@rushstack/rush-sdk");
40
+ const ts_command_line_1 = require("@rushstack/ts-command-line");
41
+ const PLUGIN_NAME = 'DropBuildGraphPlugin';
42
+ const DROP_GRAPH_PARAMETER_LONG_NAME = '--drop-graph';
43
+ /**
44
+ * This plugin is used to drop the build graph to a file for BuildXL to consume.
45
+ * @public
46
+ */
47
+ class DropBuildGraphPlugin {
48
+ constructor(options) {
49
+ this.pluginName = PLUGIN_NAME;
50
+ this._buildXLCommandNames = options.buildXLCommandNames;
51
+ }
52
+ apply(session, rushConfiguration) {
53
+ async function handleCreateOperationsForCommandAsync(commandName, operations, context) {
54
+ // TODO: Introduce an API to allow plugins to register command line options for arbitrary, existing commands
55
+ // in a repo
56
+ const dropGraphParameter = context.customParameters.get(DROP_GRAPH_PARAMETER_LONG_NAME);
57
+ if (!dropGraphParameter) {
58
+ // TODO: Introduce an API to allow plugins to register command line options for arbitrary, existing commands
59
+ // in a repo
60
+ throw new Error(`The ${DROP_GRAPH_PARAMETER_LONG_NAME} parameter needs to be defined in "${rush_sdk_1.RushConstants.commandLineFilename}" ` +
61
+ `and associated with the action "${commandName}"`);
62
+ }
63
+ else if (dropGraphParameter.kind !== ts_command_line_1.CommandLineParameterKind.String) {
64
+ throw new Error(`The ${DROP_GRAPH_PARAMETER_LONG_NAME} parameter must be a string parameter`);
65
+ }
66
+ const dropGraphPath = dropGraphParameter === null || dropGraphParameter === void 0 ? void 0 : dropGraphParameter.value;
67
+ if (dropGraphPath) {
68
+ const { dropGraphAsync } = await Promise.resolve().then(() => __importStar(require('./dropGraph')));
69
+ const isValid = await dropGraphAsync({
70
+ operations,
71
+ context,
72
+ dropGraphPath,
73
+ rushConfiguration,
74
+ logger: session.getLogger(PLUGIN_NAME)
75
+ });
76
+ if (!isValid) {
77
+ throw new Error('Failed to validate the graph');
78
+ }
79
+ else {
80
+ // If the --drop-graph flag is present, we want to exit the process after dropping the graph
81
+ return new Set();
82
+ }
83
+ }
84
+ else {
85
+ return operations;
86
+ }
87
+ }
88
+ for (const buildXLCommandName of this._buildXLCommandNames) {
89
+ session.hooks.runPhasedCommand.for(buildXLCommandName).tap(PLUGIN_NAME, (command) => {
90
+ command.hooks.createOperations.tapPromise({
91
+ name: PLUGIN_NAME,
92
+ stage: Number.MAX_SAFE_INTEGER // Run this after other plugins have created all operations
93
+ }, async (operations, context) => await handleCreateOperationsForCommandAsync(command.actionName, operations, context));
94
+ });
95
+ }
96
+ }
97
+ }
98
+ exports.DropBuildGraphPlugin = DropBuildGraphPlugin;
99
+ //# sourceMappingURL=DropBuildGraphPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropBuildGraphPlugin.js","sourceRoot":"","sources":["../src/DropBuildGraphPlugin.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE3D,kDAQ6B;AAC7B,gEAAuG;AAIvG,MAAM,WAAW,GAA2B,sBAAsB,CAAC;AAuBnE,MAAM,8BAA8B,GAAmB,cAAc,CAAC;AAEtE;;;GAGG;AACH,MAAa,oBAAoB;IAI/B,YAAmB,OAAgC;QAHnC,eAAU,GAAW,WAAW,CAAC;QAI/C,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAC1D,CAAC;IAEM,KAAK,CAAC,OAAoB,EAAE,iBAAoC;QACrE,KAAK,UAAU,qCAAqC,CAClD,WAAmB,EACnB,UAA0B,EAC1B,OAAiC;YAEjC,4GAA4G;YAC5G,YAAY;YACZ,MAAM,kBAAkB,GAA2C,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAC7F,8BAA8B,CACD,CAAC;YAChC,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACxB,4GAA4G;gBAC5G,YAAY;gBACZ,MAAM,IAAI,KAAK,CACb,OAAO,8BAA8B,sCAAsC,wBAAa,CAAC,mBAAmB,IAAI;oBAC9G,mCAAmC,WAAW,GAAG,CACpD,CAAC;YACJ,CAAC;iBAAM,IAAI,kBAAkB,CAAC,IAAI,KAAK,0CAAwB,CAAC,MAAM,EAAE,CAAC;gBACvE,MAAM,IAAI,KAAK,CAAC,OAAO,8BAA8B,uCAAuC,CAAC,CAAC;YAChG,CAAC;YAED,MAAM,aAAa,GAAuB,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAE,KAAK,CAAC;YACpE,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,EAAE,cAAc,EAAE,GAAG,wDAAa,aAAa,GAAC,CAAC;gBACvD,MAAM,OAAO,GAAY,MAAM,cAAc,CAAC;oBAC5C,UAAU;oBACV,OAAO;oBACP,aAAa;oBACb,iBAAiB;oBACjB,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC;iBACvC,CAAC,CAAC;gBAEH,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;gBAClD,CAAC;qBAAM,CAAC;oBACN,4FAA4F;oBAC5F,OAAO,IAAI,GAAG,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,UAAU,CAAC;YACpB,CAAC;QACH,CAAC;QAED,KAAK,MAAM,kBAAkB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,OAAuB,EAAE,EAAE;gBAClG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CACvC;oBACE,IAAI,EAAE,WAAW;oBACjB,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,2DAA2D;iBAC3F,EACD,KAAK,EAAE,UAA0B,EAAE,OAAiC,EAAE,EAAE,CACtE,MAAM,qCAAqC,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CACvF,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF;AAjED,oDAiEC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport {\n RushConstants,\n type ICreateOperationsContext,\n type IPhasedCommand,\n type IRushPlugin,\n type Operation,\n type RushConfiguration,\n type RushSession\n} from '@rushstack/rush-sdk';\nimport { CommandLineParameterKind, type CommandLineStringParameter } from '@rushstack/ts-command-line';\n\nimport type { IGraphNode } from './GraphProcessor';\n\nconst PLUGIN_NAME: 'DropBuildGraphPlugin' = 'DropBuildGraphPlugin';\n\n/**\n * This is the type that represents the schema of the drop file\n * @public\n */\nexport interface IBuildXLRushGraph {\n nodes: IGraphNode[];\n repoSettings: {\n commonTempFolder: string;\n };\n}\n\n/**\n * @public\n */\nexport interface IDropGraphPluginOptions {\n /**\n * The names of the commands that will be used to run BuildXL\n */\n buildXLCommandNames: string[];\n}\n\nconst DROP_GRAPH_PARAMETER_LONG_NAME: '--drop-graph' = '--drop-graph';\n\n/**\n * This plugin is used to drop the build graph to a file for BuildXL to consume.\n * @public\n */\nexport class DropBuildGraphPlugin implements IRushPlugin {\n public readonly pluginName: string = PLUGIN_NAME;\n private readonly _buildXLCommandNames: string[];\n\n public constructor(options: IDropGraphPluginOptions) {\n this._buildXLCommandNames = options.buildXLCommandNames;\n }\n\n public apply(session: RushSession, rushConfiguration: RushConfiguration): void {\n async function handleCreateOperationsForCommandAsync(\n commandName: string,\n operations: Set<Operation>,\n context: ICreateOperationsContext\n ): Promise<Set<Operation>> {\n // TODO: Introduce an API to allow plugins to register command line options for arbitrary, existing commands\n // in a repo\n const dropGraphParameter: CommandLineStringParameter | undefined = context.customParameters.get(\n DROP_GRAPH_PARAMETER_LONG_NAME\n ) as CommandLineStringParameter;\n if (!dropGraphParameter) {\n // TODO: Introduce an API to allow plugins to register command line options for arbitrary, existing commands\n // in a repo\n throw new Error(\n `The ${DROP_GRAPH_PARAMETER_LONG_NAME} parameter needs to be defined in \"${RushConstants.commandLineFilename}\" ` +\n `and associated with the action \"${commandName}\"`\n );\n } else if (dropGraphParameter.kind !== CommandLineParameterKind.String) {\n throw new Error(`The ${DROP_GRAPH_PARAMETER_LONG_NAME} parameter must be a string parameter`);\n }\n\n const dropGraphPath: string | undefined = dropGraphParameter?.value;\n if (dropGraphPath) {\n const { dropGraphAsync } = await import('./dropGraph');\n const isValid: boolean = await dropGraphAsync({\n operations,\n context,\n dropGraphPath,\n rushConfiguration,\n logger: session.getLogger(PLUGIN_NAME)\n });\n\n if (!isValid) {\n throw new Error('Failed to validate the graph');\n } else {\n // If the --drop-graph flag is present, we want to exit the process after dropping the graph\n return new Set();\n }\n } else {\n return operations;\n }\n }\n\n for (const buildXLCommandName of this._buildXLCommandNames) {\n session.hooks.runPhasedCommand.for(buildXLCommandName).tap(PLUGIN_NAME, (command: IPhasedCommand) => {\n command.hooks.createOperations.tapPromise(\n {\n name: PLUGIN_NAME,\n stage: Number.MAX_SAFE_INTEGER // Run this after other plugins have created all operations\n },\n async (operations: Set<Operation>, context: ICreateOperationsContext) =>\n await handleCreateOperationsForCommandAsync(command.actionName, operations, context)\n );\n });\n }\n }\n}\n"]}
@@ -0,0 +1,72 @@
1
+ import type { Operation, ILogger } from '@rushstack/rush-sdk';
2
+ /**
3
+ * @example
4
+ * ```
5
+ * {
6
+ * "id": "@rushstack/node-core-library#_phase:build",
7
+ * "task": "_phase:build",
8
+ * "package": "@rushstack/node-core-library",
9
+ * "dependencies": [
10
+ * "@rushstack/eslint-patch#_phase:build",
11
+ * "@rushstack/eslint-plugin#_phase:build",
12
+ * "@rushstack/eslint-plugin-packlets#_phase:build",
13
+ * "@rushstack/eslint-plugin-security#_phase:build"
14
+ * ],
15
+ * "workingDirectory": "/repo/libraries/node-core-library",
16
+ * "command": "heft run --only build -- --clean --production --drop-graph ./src/examples/graph.json"
17
+ * }
18
+ * ```
19
+ *
20
+ * See https://github.com/microsoft/BuildXL/blob/adf025c1b96b8106984928df3e9c30c8331bc8d6/Public/Src/Tools/JavaScript/Tool.RushGraphBuilder/src/RushBuildPluginGraph.ts
21
+ *
22
+ * @public
23
+ */
24
+ export interface IGraphNode {
25
+ /**
26
+ * The unique id of the Pip
27
+ *
28
+ * @example
29
+ * `@rushstack/node-core-library#_phase:build`
30
+ */
31
+ id: string;
32
+ /**
33
+ * The command to run during the Pip
34
+ */
35
+ command: string;
36
+ /**
37
+ * The working directory of the Pip
38
+ */
39
+ workingDirectory: string;
40
+ /**
41
+ * The project name associated with the Pip
42
+ *
43
+ * @example
44
+ * `@rushstack/node-core-library`
45
+ */
46
+ package: string;
47
+ /**
48
+ * The task name of the Pip
49
+ *
50
+ * @example
51
+ * `_phase:build`
52
+ */
53
+ task: string;
54
+ /**
55
+ * The IDs of the dependencies of the Pip. These are the {@link IGraphNode.id} properties of other Pips.
56
+ */
57
+ dependencies: string[];
58
+ /**
59
+ * If false, the Pip is uncacheable
60
+ */
61
+ cacheable?: false;
62
+ }
63
+ export declare function getOperationId(operation: Operation): string;
64
+ export declare class GraphProcessor {
65
+ private readonly _logger;
66
+ constructor(logger: ILogger);
67
+ processOperations(operations: Set<Operation>): IGraphNode[];
68
+ validateGraph(entries: readonly Readonly<IGraphNode>[]): boolean;
69
+ private _pruneNoOps;
70
+ private _operationAsHashedEntry;
71
+ }
72
+ //# sourceMappingURL=GraphProcessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphProcessor.d.ts","sourceRoot":"","sources":["../src/GraphProcessor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAI9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,gBAAgB,EAAE,MAAM,CAAC;IAEzB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC;CACnB;AAqBD,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAM3D;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEf,MAAM,EAAE,OAAO;IAO3B,iBAAiB,CAAC,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,UAAU,EAAE;IAe3D,aAAa,CAAC,OAAO,EAAE,SAAS,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,OAAO;IAgCvE,OAAO,CAAC,WAAW;IA6CnB,OAAO,CAAC,uBAAuB;CAsDhC"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.GraphProcessor = void 0;
6
+ exports.getOperationId = getOperationId;
7
+ const terminal_1 = require("@rushstack/terminal");
8
+ const REQUIRED_FIELDS = [
9
+ // command is absent because it is not required
10
+ 'id',
11
+ 'task',
12
+ 'package',
13
+ 'dependencies',
14
+ 'workingDirectory'
15
+ ];
16
+ /*
17
+ * Get the operation id
18
+ */
19
+ function getOperationId(operation) {
20
+ const { associatedPhase: { name: task }, associatedProject: { packageName } } = operation;
21
+ return `${packageName}#${task}`;
22
+ }
23
+ class GraphProcessor {
24
+ constructor(logger) {
25
+ this._logger = logger;
26
+ }
27
+ /*
28
+ * Convert the operationMap into an array of graph nodes with empty commands pruned
29
+ */
30
+ processOperations(operations) {
31
+ const nodeMap = new Map();
32
+ for (const operation of operations) {
33
+ const entry = this._operationAsHashedEntry(operation);
34
+ nodeMap.set(entry.id, entry);
35
+ }
36
+ return this._pruneNoOps(nodeMap);
37
+ }
38
+ /*
39
+ * Validate that all dependencies exist
40
+ * Validate that all nodes have a non-empty command
41
+ * Print a message to the logger, and return true if the graph is valid
42
+ */
43
+ validateGraph(entries) {
44
+ const entryIDs = new Set(entries.map((entry) => entry.id));
45
+ let isValid = true;
46
+ for (const entry of entries) {
47
+ for (const depId of entry.dependencies) {
48
+ if (!entryIDs.has(depId)) {
49
+ this._logger.emitError(new Error(`${entry.id} has a dependency on ${depId} which does not exist`));
50
+ isValid = false;
51
+ }
52
+ }
53
+ if (!entry.command) {
54
+ this._logger.emitError(new Error(`There is an empty command in ${entry.id}`));
55
+ isValid = false;
56
+ }
57
+ }
58
+ if (isValid) {
59
+ this._logger.terminal.writeLine(terminal_1.Colorize.green('All nodes have non-empty commands and dependencies which exist'));
60
+ }
61
+ const totalEdges = entries.reduce((acc, entry) => acc + entry.dependencies.length, 0);
62
+ this._logger.terminal.writeLine(`Graph has ${entries.length} nodes, ${totalEdges} edges`);
63
+ return isValid;
64
+ }
65
+ /*
66
+ * remove all entries with empty commands
67
+ * if an entry has a dependency with an empty command, it should inherit the dependencies of the empty command
68
+ */
69
+ _pruneNoOps(inputNodeMap) {
70
+ // Cache for the non-empty upstream dependencies of each operation
71
+ const nonEmptyDependenciesByOperation = new Map();
72
+ function getNonEmptyDependencies(node) {
73
+ // If we've already computed this, return the cached result
74
+ let nonEmptyDependencies = nonEmptyDependenciesByOperation.get(node);
75
+ if (!nonEmptyDependencies) {
76
+ nonEmptyDependencies = new Set();
77
+ nonEmptyDependenciesByOperation.set(node, nonEmptyDependencies);
78
+ for (const dependencyID of node.dependencies) {
79
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
80
+ if (!inputNodeMap.get(dependencyID).command) {
81
+ // If the dependency is empty, recursively inherit its non-empty dependencies
82
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
83
+ for (const deepDependency of getNonEmptyDependencies(inputNodeMap.get(dependencyID))) {
84
+ nonEmptyDependencies.add(deepDependency);
85
+ }
86
+ }
87
+ else {
88
+ nonEmptyDependencies.add(dependencyID);
89
+ }
90
+ }
91
+ }
92
+ return nonEmptyDependencies;
93
+ }
94
+ const result = [];
95
+ for (const node of inputNodeMap.values()) {
96
+ const command = node.command;
97
+ if (command) {
98
+ const nonEmptyDependencySet = getNonEmptyDependencies(node);
99
+ result.push({
100
+ ...node,
101
+ dependencies: Array.from(nonEmptyDependencySet),
102
+ command: command
103
+ });
104
+ }
105
+ }
106
+ return result;
107
+ }
108
+ /*
109
+ * Convert an operation into a graph node
110
+ */
111
+ _operationAsHashedEntry(operation) {
112
+ const { runner, associatedPhase: { name: task }, associatedProject: {
113
+ // "package" is a reserved word
114
+ packageName, projectFolder: workingDirectory }, settings, dependencies: operationDependencies } = operation;
115
+ const dependencies = new Set();
116
+ for (const dependency of operationDependencies.values()) {
117
+ const id = getOperationId(dependency);
118
+ dependencies.add(id);
119
+ }
120
+ const node = {
121
+ id: getOperationId(operation),
122
+ task,
123
+ package: packageName,
124
+ dependencies,
125
+ workingDirectory,
126
+ command: runner === null || runner === void 0 ? void 0 : runner.commandToRun
127
+ };
128
+ if (settings === null || settings === void 0 ? void 0 : settings.disableBuildCacheForOperation) {
129
+ node.cacheable = false;
130
+ }
131
+ const missingFields = [];
132
+ for (const requiredField of REQUIRED_FIELDS) {
133
+ if (!node[requiredField]) {
134
+ missingFields.push(requiredField);
135
+ }
136
+ }
137
+ if (missingFields.length > 0) {
138
+ this._logger.emitError(new Error(`Operation is missing required fields ${missingFields.join(', ')}: ${JSON.stringify(node)}`));
139
+ }
140
+ // the runner is a no-op if and only if the command is empty
141
+ if (!!(runner === null || runner === void 0 ? void 0 : runner.isNoOp) !== !node.command) {
142
+ this._logger.emitError(new Error(`${node.id}: Operation runner isNoOp does not match commandToRun existence`));
143
+ }
144
+ return node;
145
+ }
146
+ }
147
+ exports.GraphProcessor = GraphProcessor;
148
+ //# sourceMappingURL=GraphProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphProcessor.js","sourceRoot":"","sources":["../src/GraphProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { Operation, ILogger } from '@rushstack/rush-sdk';\nimport type { ShellOperationRunner } from '@rushstack/rush-sdk/lib/logic/operations/ShellOperationRunner';\nimport { Colorize } from '@rushstack/terminal';\n\n/**\n * @example\n * ```\n * {\n * \"id\": \"@rushstack/node-core-library#_phase:build\",\n * \"task\": \"_phase:build\",\n * \"package\": \"@rushstack/node-core-library\",\n * \"dependencies\": [\n * \"@rushstack/eslint-patch#_phase:build\",\n * \"@rushstack/eslint-plugin#_phase:build\",\n * \"@rushstack/eslint-plugin-packlets#_phase:build\",\n * \"@rushstack/eslint-plugin-security#_phase:build\"\n * ],\n * \"workingDirectory\": \"/repo/libraries/node-core-library\",\n * \"command\": \"heft run --only build -- --clean --production --drop-graph ./src/examples/graph.json\"\n * }\n * ```\n *\n * See https://github.com/microsoft/BuildXL/blob/adf025c1b96b8106984928df3e9c30c8331bc8d6/Public/Src/Tools/JavaScript/Tool.RushGraphBuilder/src/RushBuildPluginGraph.ts\n *\n * @public\n */\nexport interface IGraphNode {\n /**\n * The unique id of the Pip\n *\n * @example\n * `@rushstack/node-core-library#_phase:build`\n */\n id: string;\n\n /**\n * The command to run during the Pip\n */\n command: string;\n\n /**\n * The working directory of the Pip\n */\n workingDirectory: string;\n\n /**\n * The project name associated with the Pip\n *\n * @example\n * `@rushstack/node-core-library`\n */\n package: string;\n\n /**\n * The task name of the Pip\n *\n * @example\n * `_phase:build`\n */\n task: string;\n\n /**\n * The IDs of the dependencies of the Pip. These are the {@link IGraphNode.id} properties of other Pips.\n */\n dependencies: string[];\n\n /**\n * If false, the Pip is uncacheable\n */\n cacheable?: false;\n}\n\ninterface IGraphNodeInternal extends Omit<IGraphNode, 'dependencies' | 'command'> {\n dependencies: ReadonlySet<string>;\n command: string | undefined;\n}\n\ntype NodeMap = ReadonlyMap<string, IGraphNodeInternal>;\n\nconst REQUIRED_FIELDS: Array<keyof IGraphNodeInternal> = [\n // command is absent because it is not required\n 'id',\n 'task',\n 'package',\n 'dependencies',\n 'workingDirectory'\n];\n\n/*\n * Get the operation id\n */\nexport function getOperationId(operation: Operation): string {\n const {\n associatedPhase: { name: task },\n associatedProject: { packageName }\n } = operation;\n return `${packageName}#${task}`;\n}\n\nexport class GraphProcessor {\n private readonly _logger: ILogger;\n\n public constructor(logger: ILogger) {\n this._logger = logger;\n }\n\n /*\n * Convert the operationMap into an array of graph nodes with empty commands pruned\n */\n public processOperations(operations: Set<Operation>): IGraphNode[] {\n const nodeMap: Map<string, IGraphNodeInternal> = new Map();\n for (const operation of operations) {\n const entry: IGraphNodeInternal = this._operationAsHashedEntry(operation);\n nodeMap.set(entry.id, entry);\n }\n\n return this._pruneNoOps(nodeMap);\n }\n\n /*\n * Validate that all dependencies exist\n * Validate that all nodes have a non-empty command\n * Print a message to the logger, and return true if the graph is valid\n */\n public validateGraph(entries: readonly Readonly<IGraphNode>[]): boolean {\n const entryIDs: Set<string> = new Set(entries.map((entry) => entry.id));\n let isValid: boolean = true;\n for (const entry of entries) {\n for (const depId of entry.dependencies) {\n if (!entryIDs.has(depId)) {\n this._logger.emitError(new Error(`${entry.id} has a dependency on ${depId} which does not exist`));\n isValid = false;\n }\n }\n\n if (!entry.command) {\n this._logger.emitError(new Error(`There is an empty command in ${entry.id}`));\n isValid = false;\n }\n }\n\n if (isValid) {\n this._logger.terminal.writeLine(\n Colorize.green('All nodes have non-empty commands and dependencies which exist')\n );\n }\n\n const totalEdges: number = entries.reduce((acc, entry) => acc + entry.dependencies.length, 0);\n this._logger.terminal.writeLine(`Graph has ${entries.length} nodes, ${totalEdges} edges`);\n return isValid;\n }\n\n /*\n * remove all entries with empty commands\n * if an entry has a dependency with an empty command, it should inherit the dependencies of the empty command\n */\n private _pruneNoOps(inputNodeMap: NodeMap): IGraphNode[] {\n // Cache for the non-empty upstream dependencies of each operation\n const nonEmptyDependenciesByOperation: Map<IGraphNodeInternal, Set<string>> = new Map();\n function getNonEmptyDependencies(node: IGraphNodeInternal): ReadonlySet<string> {\n // If we've already computed this, return the cached result\n let nonEmptyDependencies: Set<string> | undefined = nonEmptyDependenciesByOperation.get(node);\n if (!nonEmptyDependencies) {\n nonEmptyDependencies = new Set();\n nonEmptyDependenciesByOperation.set(node, nonEmptyDependencies);\n for (const dependencyID of node.dependencies) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (!inputNodeMap.get(dependencyID)!.command) {\n // If the dependency is empty, recursively inherit its non-empty dependencies\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n for (const deepDependency of getNonEmptyDependencies(inputNodeMap.get(dependencyID)!)) {\n nonEmptyDependencies.add(deepDependency);\n }\n } else {\n nonEmptyDependencies.add(dependencyID);\n }\n }\n }\n\n return nonEmptyDependencies;\n }\n\n const result: IGraphNode[] = [];\n for (const node of inputNodeMap.values()) {\n const command: string | undefined = node.command;\n if (command) {\n const nonEmptyDependencySet: ReadonlySet<string> = getNonEmptyDependencies(node);\n result.push({\n ...node,\n dependencies: Array.from(nonEmptyDependencySet),\n command: command\n });\n }\n }\n\n return result;\n }\n\n /*\n * Convert an operation into a graph node\n */\n private _operationAsHashedEntry(operation: Operation): IGraphNodeInternal {\n const {\n runner,\n associatedPhase: { name: task },\n associatedProject: {\n // \"package\" is a reserved word\n packageName,\n projectFolder: workingDirectory\n },\n settings,\n dependencies: operationDependencies\n } = operation;\n\n const dependencies: Set<string> = new Set();\n for (const dependency of operationDependencies.values()) {\n const id: string = getOperationId(dependency);\n dependencies.add(id);\n }\n\n const node: Partial<IGraphNodeInternal> = {\n id: getOperationId(operation),\n task,\n package: packageName,\n dependencies,\n workingDirectory,\n command: (runner as Partial<Pick<ShellOperationRunner, 'commandToRun'>>)?.commandToRun\n };\n\n if (settings?.disableBuildCacheForOperation) {\n node.cacheable = false;\n }\n\n const missingFields: (keyof IGraphNodeInternal)[] = [];\n for (const requiredField of REQUIRED_FIELDS) {\n if (!node[requiredField]) {\n missingFields.push(requiredField);\n }\n }\n\n if (missingFields.length > 0) {\n this._logger.emitError(\n new Error(`Operation is missing required fields ${missingFields.join(', ')}: ${JSON.stringify(node)}`)\n );\n }\n\n // the runner is a no-op if and only if the command is empty\n if (!!runner?.isNoOp !== !node.command) {\n this._logger.emitError(\n new Error(`${node.id}: Operation runner isNoOp does not match commandToRun existence`)\n );\n }\n\n return node as IGraphNodeInternal;\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export declare function filterObjectForDebug(obj: object, depth?: number, simplify?: boolean): object;
2
+ export declare function filterObjectForTesting(obj: object, depth?: number, ignoreSets?: boolean): object;
3
+ //# sourceMappingURL=debugGraphFiltering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugGraphFiltering.d.ts","sourceRoot":"","sources":["../src/debugGraphFiltering.ts"],"names":[],"mappings":"AAoCA,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,QAAQ,GAAE,OAAe,GAAG,MAAM,CAkCvG;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,UAAU,GAAE,OAAe,GAAG,MAAM,CA4B3G"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.filterObjectForDebug = filterObjectForDebug;
6
+ exports.filterObjectForTesting = filterObjectForTesting;
7
+ const GraphProcessor_1 = require("./GraphProcessor");
8
+ const BANNED_KEYS = new Set([
9
+ 'packageJsonEditor',
10
+ '_packageJson',
11
+ '_subspaces',
12
+ 'subspace',
13
+ 'rushConfiguration',
14
+ '_rushConfiguration',
15
+ 'associatedParameters',
16
+ '_dependencyProjects'
17
+ ]);
18
+ const ALLOWED_KEYS = new Set([
19
+ 'associatedPhase',
20
+ 'name',
21
+ 'associatedProject',
22
+ 'packageName',
23
+ 'projectFolder',
24
+ 'dependencies',
25
+ 'runner',
26
+ 'commandToRun',
27
+ 'isNoOp'
28
+ ]);
29
+ /*
30
+ * Filter Rush's build graph to remove repetitive and unimportant information. Useful if the schema ever changes, or needs to.
31
+ * Due to the fact that it includes all properties that are not banned, it is not guaranteed to be stable across versions.
32
+ * Should not be part of the critical path.
33
+ * @param obj - the object to filter
34
+ * @param depth - the maximum depth to recurse
35
+ * @param simplify - if true, will replace embedded operations with their operation id
36
+ */
37
+ function filterObjectForDebug(obj, depth = 10, simplify = false) {
38
+ const output = {};
39
+ for (const [key, value] of Object.entries(obj)) {
40
+ if (BANNED_KEYS.has(key)) {
41
+ output[key] = `${key} truncated`;
42
+ continue;
43
+ }
44
+ else if (typeof value === 'function') {
45
+ output[key] = `${key}()`;
46
+ continue;
47
+ }
48
+ else if (value instanceof Set) {
49
+ output[key] = filterObjectForDebug(Array.from(value), Math.min(depth - 1, 5), true);
50
+ continue;
51
+ }
52
+ else if (value instanceof Object) {
53
+ if (depth <= 0) {
54
+ output[key] = `${key} too deep`;
55
+ continue;
56
+ }
57
+ if (simplify) {
58
+ const operationId = (0, GraphProcessor_1.getOperationId)(value);
59
+ if (operationId) {
60
+ output[key] = operationId;
61
+ continue;
62
+ }
63
+ }
64
+ output[key] = filterObjectForDebug(value, depth - 1);
65
+ continue;
66
+ }
67
+ output[key] = value;
68
+ }
69
+ return output;
70
+ }
71
+ function filterObjectForTesting(obj, depth = 10, ignoreSets = false) {
72
+ const output = {};
73
+ for (const [key, value] of Object.entries(obj)) {
74
+ if (!ALLOWED_KEYS.has(key) && !key.match(/^\d+$/)) {
75
+ continue;
76
+ }
77
+ else if (value instanceof Set) {
78
+ if (!ignoreSets) {
79
+ // Don't need sets inside sets
80
+ output[key] = Array.from(value).map((subValue) => filterObjectForTesting(subValue, Math.min(depth - 1, 5), true));
81
+ }
82
+ continue;
83
+ }
84
+ else if (value instanceof Object) {
85
+ if (depth <= 0) {
86
+ output[key] = `${key} too deep`;
87
+ continue;
88
+ }
89
+ output[key] = filterObjectForTesting(value, depth - 1, ignoreSets);
90
+ continue;
91
+ }
92
+ output[key] = value;
93
+ }
94
+ return output;
95
+ }
96
+ //# sourceMappingURL=debugGraphFiltering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugGraphFiltering.js","sourceRoot":"","sources":["../src/debugGraphFiltering.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { getOperationId } from './GraphProcessor';\n\nconst BANNED_KEYS: ReadonlySet<string> = new Set([\n 'packageJsonEditor',\n '_packageJson',\n '_subspaces',\n 'subspace',\n 'rushConfiguration',\n '_rushConfiguration',\n 'associatedParameters',\n '_dependencyProjects'\n]);\n\nconst ALLOWED_KEYS: ReadonlySet<string> = new Set([\n 'associatedPhase',\n 'name',\n 'associatedProject',\n 'packageName',\n 'projectFolder',\n 'dependencies',\n 'runner',\n 'commandToRun',\n 'isNoOp'\n]);\n\n/*\n * Filter Rush's build graph to remove repetitive and unimportant information. Useful if the schema ever changes, or needs to.\n * Due to the fact that it includes all properties that are not banned, it is not guaranteed to be stable across versions.\n * Should not be part of the critical path.\n * @param obj - the object to filter\n * @param depth - the maximum depth to recurse\n * @param simplify - if true, will replace embedded operations with their operation id\n */\nexport function filterObjectForDebug(obj: object, depth: number = 10, simplify: boolean = false): object {\n const output: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (BANNED_KEYS.has(key)) {\n output[key] = `${key} truncated`;\n continue;\n } else if (typeof value === 'function') {\n output[key] = `${key}()`;\n continue;\n } else if (value instanceof Set) {\n output[key] = filterObjectForDebug(Array.from(value), Math.min(depth - 1, 5), true);\n continue;\n } else if (value instanceof Object) {\n if (depth <= 0) {\n output[key] = `${key} too deep`;\n continue;\n }\n\n if (simplify) {\n const operationId: string | undefined = getOperationId(value);\n if (operationId) {\n output[key] = operationId;\n continue;\n }\n }\n\n output[key] = filterObjectForDebug(value, depth - 1);\n continue;\n }\n\n output[key] = value;\n }\n\n return output;\n}\n\nexport function filterObjectForTesting(obj: object, depth: number = 10, ignoreSets: boolean = false): object {\n const output: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (!ALLOWED_KEYS.has(key) && !key.match(/^\\d+$/)) {\n continue;\n } else if (value instanceof Set) {\n if (!ignoreSets) {\n // Don't need sets inside sets\n output[key] = Array.from(value).map((subValue) =>\n filterObjectForTesting(subValue, Math.min(depth - 1, 5), true)\n );\n }\n\n continue;\n } else if (value instanceof Object) {\n if (depth <= 0) {\n output[key] = `${key} too deep`;\n continue;\n }\n\n output[key] = filterObjectForTesting(value, depth - 1, ignoreSets);\n continue;\n }\n\n output[key] = value;\n }\n\n return output;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { ICreateOperationsContext, ILogger, Operation, RushConfiguration } from '@rushstack/rush-sdk';
2
+ export interface IDropGraphOptions {
3
+ operations: Set<Operation>;
4
+ context: ICreateOperationsContext;
5
+ dropGraphPath: string;
6
+ rushConfiguration: RushConfiguration;
7
+ logger: ILogger;
8
+ }
9
+ export declare function dropGraphAsync(options: IDropGraphOptions): Promise<boolean>;
10
+ //# sourceMappingURL=dropGraph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropGraph.d.ts","sourceRoot":"","sources":["../src/dropGraph.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,wBAAwB,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAO3G,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3B,OAAO,EAAE,wBAAwB,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,MAAM,EAAE,OAAO,CAAC;CACjB;AAID,wBAAsB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAqDjF"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.dropGraphAsync = dropGraphAsync;
9
+ const path_1 = __importDefault(require("path"));
10
+ const node_core_library_1 = require("@rushstack/node-core-library");
11
+ const GraphProcessor_1 = require("./GraphProcessor");
12
+ const debugGraphFiltering_1 = require("./debugGraphFiltering");
13
+ const DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME = 'DEBUG_RUSH_BUILD_GRAPH';
14
+ async function dropGraphAsync(options) {
15
+ const { operations, context, dropGraphPath, rushConfiguration: { commonTempFolder }, logger } = options;
16
+ if (process.env[DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME]) {
17
+ let filterFn;
18
+ const debugValue = process.env[DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME];
19
+ switch (process.env.DEBUG_RUSH_BUILD_GRAPH) {
20
+ case 'test': {
21
+ filterFn = debugGraphFiltering_1.filterObjectForTesting;
22
+ break;
23
+ }
24
+ case 'full': {
25
+ filterFn = debugGraphFiltering_1.filterObjectForDebug;
26
+ break;
27
+ }
28
+ default: {
29
+ throw new Error(`Invalid value for ${DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME}: ${debugValue}`);
30
+ }
31
+ }
32
+ if (filterFn) {
33
+ const graphOut = [];
34
+ for (const operation of operations.keys()) {
35
+ graphOut.push(filterFn(operation));
36
+ }
37
+ const debugOutput = {
38
+ OperationMap: graphOut,
39
+ ICreateOperationsContext: filterFn(context)
40
+ };
41
+ const debugPathOut = `${path_1.default.dirname(dropGraphPath)}/debug-${path_1.default.basename(dropGraphPath)}`;
42
+ await node_core_library_1.JsonFile.saveAsync(debugOutput, debugPathOut, { ensureFolderExists: true });
43
+ }
44
+ }
45
+ const graphProcessor = new GraphProcessor_1.GraphProcessor(logger);
46
+ const nodes = graphProcessor.processOperations(operations);
47
+ const buildXLGraph = {
48
+ nodes,
49
+ repoSettings: {
50
+ commonTempFolder
51
+ }
52
+ };
53
+ await node_core_library_1.JsonFile.saveAsync(buildXLGraph, dropGraphPath, { ensureFolderExists: true });
54
+ return graphProcessor.validateGraph(buildXLGraph.nodes);
55
+ }
56
+ //# sourceMappingURL=dropGraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropGraph.js","sourceRoot":"","sources":["../src/dropGraph.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;AAoB3D,wCAqDC;AAvED,gDAAwB;AAExB,oEAAwD;AAGxD,qDAAmE;AACnE,+DAAqF;AAUrF,MAAM,mCAAmC,GAA6B,wBAAwB,CAAC;AAExF,KAAK,UAAU,cAAc,CAAC,OAA0B;IAC7D,MAAM,EACJ,UAAU,EACV,OAAO,EACP,aAAa,EACb,iBAAiB,EAAE,EAAE,gBAAgB,EAAE,EACvC,MAAM,EACP,GAAG,OAAO,CAAC;IACZ,IAAI,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,EAAE,CAAC;QACrD,IAAI,QAA+D,CAAC;QACpE,MAAM,UAAU,GAAuB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACxF,QAAQ,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;YAC3C,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,QAAQ,GAAG,4CAAsB,CAAC;gBAClC,MAAM;YACR,CAAC;YAED,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,QAAQ,GAAG,0CAAoB,CAAC;gBAChC,MAAM;YACR,CAAC;YAED,OAAO,CAAC,CAAC,CAAC;gBACR,MAAM,IAAI,KAAK,CAAC,qBAAqB,mCAAmC,KAAK,UAAU,EAAE,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,QAAQ,GAAc,EAAE,CAAC;YAC/B,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC1C,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACrC,CAAC;YAED,MAAM,WAAW,GAAY;gBAC3B,YAAY,EAAE,QAAQ;gBACtB,wBAAwB,EAAE,QAAQ,CAAC,OAAO,CAAC;aAC5C,CAAC;YACF,MAAM,YAAY,GAAW,GAAG,cAAI,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,cAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACpG,MAAM,4BAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,YAAY,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAmB,IAAI,+BAAc,CAAC,MAAM,CAAC,CAAC;IAClE,MAAM,KAAK,GAAiB,cAAc,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACzE,MAAM,YAAY,GAAsB;QACtC,KAAK;QACL,YAAY,EAAE;YACZ,gBAAgB;SACjB;KACF,CAAC;IAEF,MAAM,4BAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,aAAa,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;IACpF,OAAO,cAAc,CAAC,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport path from 'path';\nimport type { ICreateOperationsContext, ILogger, Operation, RushConfiguration } from '@rushstack/rush-sdk';\nimport { JsonFile } from '@rushstack/node-core-library';\n\nimport type { IBuildXLRushGraph } from './DropBuildGraphPlugin';\nimport { type IGraphNode, GraphProcessor } from './GraphProcessor';\nimport { filterObjectForDebug, filterObjectForTesting } from './debugGraphFiltering';\n\nexport interface IDropGraphOptions {\n operations: Set<Operation>;\n context: ICreateOperationsContext;\n dropGraphPath: string;\n rushConfiguration: RushConfiguration;\n logger: ILogger;\n}\n\nconst DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME: 'DEBUG_RUSH_BUILD_GRAPH' = 'DEBUG_RUSH_BUILD_GRAPH';\n\nexport async function dropGraphAsync(options: IDropGraphOptions): Promise<boolean> {\n const {\n operations,\n context,\n dropGraphPath,\n rushConfiguration: { commonTempFolder },\n logger\n } = options;\n if (process.env[DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME]) {\n let filterFn: ((obj: object, depth?: number) => object) | undefined;\n const debugValue: string | undefined = process.env[DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME];\n switch (process.env.DEBUG_RUSH_BUILD_GRAPH) {\n case 'test': {\n filterFn = filterObjectForTesting;\n break;\n }\n\n case 'full': {\n filterFn = filterObjectForDebug;\n break;\n }\n\n default: {\n throw new Error(`Invalid value for ${DEBUG_RUSH_BUILD_GRAPH_ENV_VAR_NAME}: ${debugValue}`);\n }\n }\n\n if (filterFn) {\n const graphOut: unknown[] = [];\n for (const operation of operations.keys()) {\n graphOut.push(filterFn(operation));\n }\n\n const debugOutput: unknown = {\n OperationMap: graphOut,\n ICreateOperationsContext: filterFn(context)\n };\n const debugPathOut: string = `${path.dirname(dropGraphPath)}/debug-${path.basename(dropGraphPath)}`;\n await JsonFile.saveAsync(debugOutput, debugPathOut, { ensureFolderExists: true });\n }\n }\n\n const graphProcessor: GraphProcessor = new GraphProcessor(logger);\n const nodes: IGraphNode[] = graphProcessor.processOperations(operations);\n const buildXLGraph: IBuildXLRushGraph = {\n nodes,\n repoSettings: {\n commonTempFolder\n }\n };\n\n await JsonFile.saveAsync(buildXLGraph, dropGraphPath, { ensureFolderExists: true });\n return graphProcessor.validateGraph(buildXLGraph.nodes);\n}\n"]}
package/lib/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type { IBuildXLRushGraph } from './DropBuildGraphPlugin';
2
+ export type { IGraphNode } from './GraphProcessor';
3
+ export type { IDropGraphPluginOptions } from './DropBuildGraphPlugin';
4
+ import { DropBuildGraphPlugin } from './DropBuildGraphPlugin';
5
+ export default DropBuildGraphPlugin;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,eAAe,oBAAoB,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ const DropBuildGraphPlugin_1 = require("./DropBuildGraphPlugin");
6
+ exports.default = DropBuildGraphPlugin_1.DropBuildGraphPlugin;
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;AAK3D,iEAA8D;AAC9D,kBAAe,2CAAoB,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport type { IBuildXLRushGraph } from './DropBuildGraphPlugin';\nexport type { IGraphNode } from './GraphProcessor';\nexport type { IDropGraphPluginOptions } from './DropBuildGraphPlugin';\nimport { DropBuildGraphPlugin } from './DropBuildGraphPlugin';\nexport default DropBuildGraphPlugin;\n"]}
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "Configuration for the BuildXL graph drop plugin.",
4
+ "type": "object",
5
+ "required": ["buildXLCommandNames"],
6
+ "properties": {
7
+ "buildXLCommandNames": {
8
+ "type": "array",
9
+ "description": "The names of the commands that will be used to run BuildXL",
10
+ "items": {
11
+ "type": "string"
12
+ }
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.52.5"
9
+ }
10
+ ]
11
+ }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@rushstack/rush-buildxl-graph-plugin",
3
+ "version": "5.153.0",
4
+ "description": "Rush plugin for generating a BuildXL graph.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/microsoft/rushstack",
8
+ "directory": "rush-plugins/rush-buildxl-graph-plugin"
9
+ },
10
+ "homepage": "https://rushjs.io",
11
+ "main": "lib/index.js",
12
+ "types": "lib/index.d.ts",
13
+ "license": "MIT",
14
+ "dependencies": {
15
+ "@rushstack/node-core-library": "5.13.0",
16
+ "@rushstack/ts-command-line": "5.0.0",
17
+ "@rushstack/terminal": "0.15.2",
18
+ "@rushstack/rush-sdk": "5.153.0"
19
+ },
20
+ "devDependencies": {
21
+ "@microsoft/rush-lib": "5.153.0",
22
+ "@rushstack/heft": "0.73.2",
23
+ "local-node-rig": "1.0.0"
24
+ },
25
+ "scripts": {
26
+ "build": "heft build --clean",
27
+ "start": "heft test --clean --watch",
28
+ "_phase:build": "heft run --only build -- --clean",
29
+ "_phase:test": "heft run --only test -- --clean"
30
+ }
31
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush-plugin-manifest.schema.json",
3
+ "plugins": [
4
+ {
5
+ "pluginName": "rush-buildxl-graph-plugin",
6
+ "description": "Plugin for providing access to Rush build graph.",
7
+ "entryPoint": "lib/index.js",
8
+ "optionsSchema": "lib/schemas/rush-buildxl-graph-plugin.schema.json"
9
+ }
10
+ ]
11
+ }