nx 19.4.0-beta.0 → 19.4.0-beta.2
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/package.json +14 -14
- package/release/changelog-renderer/index.d.ts +6 -0
- package/release/changelog-renderer/index.js +1 -1
- package/src/command-line/connect/connect-to-nx-cloud.d.ts +1 -1
- package/src/command-line/connect/connect-to-nx-cloud.js +16 -25
- package/src/command-line/graph/graph.d.ts +1 -0
- package/src/command-line/graph/graph.js +12 -1
- package/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +5 -6
- package/src/command-line/release/changelog.js +6 -1
- package/src/command-line/release/config/config.js +3 -0
- package/src/command-line/run/command-object.js +2 -1
- package/src/config/workspace-json-project-json.d.ts +2 -0
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/styles.css +1 -1
- package/src/daemon/client/client.d.ts +5 -0
- package/src/daemon/client/client.js +14 -0
- package/src/daemon/message-types/task-history.d.ts +13 -0
- package/src/daemon/message-types/task-history.js +19 -0
- package/src/daemon/server/handle-get-task-history.d.ts +4 -0
- package/src/daemon/server/handle-get-task-history.js +12 -0
- package/src/daemon/server/handle-write-task-runs-to-history.d.ts +5 -0
- package/src/daemon/server/handle-write-task-runs-to-history.js +12 -0
- package/src/daemon/server/plugins.js +12 -2
- package/src/daemon/server/server.js +9 -0
- package/src/daemon/socket-utils.d.ts +1 -0
- package/src/daemon/socket-utils.js +6 -1
- package/src/executors/run-commands/run-commands.impl.js +29 -20
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.d.ts +1 -0
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +68 -33
- package/src/nx-cloud/generators/connect-to-nx-cloud/schema.json +5 -0
- package/src/nx-cloud/utilities/url-shorten.d.ts +2 -1
- package/src/nx-cloud/utilities/url-shorten.js +47 -11
- package/src/plugins/package-json-workspaces/create-nodes.js +12 -7
- package/src/plugins/project-json/build-nodes/package-json-next-to-project-json.js +10 -2
- package/src/plugins/target-defaults/target-defaults-plugin.d.ts +5 -0
- package/src/project-graph/plugins/internal-api.js +1 -1
- package/src/project-graph/plugins/isolation/index.d.ts +1 -1
- package/src/project-graph/plugins/isolation/index.js +8 -13
- package/src/project-graph/plugins/isolation/messaging.d.ts +6 -3
- package/src/project-graph/plugins/isolation/messaging.js +9 -3
- package/src/project-graph/plugins/isolation/plugin-pool.d.ts +1 -1
- package/src/project-graph/plugins/isolation/plugin-pool.js +123 -43
- package/src/project-graph/plugins/isolation/plugin-worker.js +128 -107
- package/src/project-graph/project-graph.js +7 -1
- package/src/project-graph/utils/normalize-project-nodes.d.ts +1 -5
- package/src/project-graph/utils/normalize-project-nodes.js +2 -17
- package/src/project-graph/utils/project-configuration-utils.js +14 -3
- package/src/project-graph/utils/retrieve-workspace-files.d.ts +3 -3
- package/src/tasks-runner/default-tasks-runner.js +2 -2
- package/src/tasks-runner/life-cycle.d.ts +10 -10
- package/src/tasks-runner/life-cycle.js +10 -10
- package/src/tasks-runner/life-cycles/task-history-life-cycle.d.ts +9 -0
- package/src/tasks-runner/life-cycles/task-history-life-cycle.js +54 -0
- package/src/tasks-runner/run-command.js +6 -0
- package/src/tasks-runner/task-env.d.ts +13 -0
- package/src/tasks-runner/task-env.js +41 -26
- package/src/tasks-runner/task-orchestrator.js +4 -4
- package/src/utils/git-utils.d.ts +1 -1
- package/src/utils/git-utils.js +13 -2
- package/src/utils/nx-cloud-utils.d.ts +1 -1
- package/src/utils/nx-cloud-utils.js +1 -1
- package/src/utils/package-json.d.ts +3 -0
- package/src/utils/package-json.js +15 -3
- package/src/utils/serialize-target.d.ts +1 -0
- package/src/utils/serialize-target.js +7 -0
- package/src/utils/task-history.d.ts +8 -0
- package/src/utils/task-history.js +97 -0
@@ -3,116 +3,137 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const messaging_1 = require("./messaging");
|
4
4
|
const loader_1 = require("../loader");
|
5
5
|
const serializable_error_1 = require("../../../utils/serializable-error");
|
6
|
+
const net_1 = require("net");
|
7
|
+
const consume_messages_from_socket_1 = require("../../../utils/consume-messages-from-socket");
|
8
|
+
const fs_1 = require("fs");
|
6
9
|
if (process.env.NX_PERF_LOGGING === 'true') {
|
7
10
|
require('../../../utils/perf-logging');
|
8
11
|
}
|
9
12
|
global.NX_GRAPH_CREATION = true;
|
10
13
|
let plugin;
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
14
|
+
const socketPath = process.argv[2];
|
15
|
+
const server = (0, net_1.createServer)((socket) => {
|
16
|
+
socket.on('data', (0, consume_messages_from_socket_1.consumeMessagesFromSocket)((raw) => {
|
17
|
+
const message = JSON.parse(raw.toString());
|
18
|
+
if (!(0, messaging_1.isPluginWorkerMessage)(message)) {
|
19
|
+
return;
|
20
|
+
}
|
21
|
+
return (0, messaging_1.consumeMessage)(socket, message, {
|
22
|
+
load: async ({ plugin: pluginConfiguration, root }) => {
|
23
|
+
process.chdir(root);
|
24
|
+
try {
|
25
|
+
const [promise] = (0, loader_1.loadNxPlugin)(pluginConfiguration, root);
|
26
|
+
plugin = await promise;
|
27
|
+
return {
|
28
|
+
type: 'load-result',
|
29
|
+
payload: {
|
30
|
+
name: plugin.name,
|
31
|
+
include: plugin.include,
|
32
|
+
exclude: plugin.exclude,
|
33
|
+
createNodesPattern: plugin.createNodes?.[0],
|
34
|
+
hasCreateDependencies: 'createDependencies' in plugin && !!plugin.createDependencies,
|
35
|
+
hasProcessProjectGraph: 'processProjectGraph' in plugin &&
|
36
|
+
!!plugin.processProjectGraph,
|
37
|
+
hasCreateMetadata: 'createMetadata' in plugin && !!plugin.createMetadata,
|
38
|
+
success: true,
|
39
|
+
},
|
40
|
+
};
|
41
|
+
}
|
42
|
+
catch (e) {
|
43
|
+
return {
|
44
|
+
type: 'load-result',
|
45
|
+
payload: {
|
46
|
+
success: false,
|
47
|
+
error: (0, serializable_error_1.createSerializableError)(e),
|
48
|
+
},
|
49
|
+
};
|
50
|
+
}
|
51
|
+
},
|
52
|
+
createNodes: async ({ configFiles, context, tx }) => {
|
53
|
+
try {
|
54
|
+
const result = await plugin.createNodes[1](configFiles, context);
|
55
|
+
return {
|
56
|
+
type: 'createNodesResult',
|
57
|
+
payload: { result, success: true, tx },
|
58
|
+
};
|
59
|
+
}
|
60
|
+
catch (e) {
|
61
|
+
return {
|
62
|
+
type: 'createNodesResult',
|
63
|
+
payload: {
|
64
|
+
success: false,
|
65
|
+
error: (0, serializable_error_1.createSerializableError)(e),
|
66
|
+
tx,
|
67
|
+
},
|
68
|
+
};
|
69
|
+
}
|
70
|
+
},
|
71
|
+
createDependencies: async ({ context, tx }) => {
|
72
|
+
try {
|
73
|
+
const result = await plugin.createDependencies(context);
|
74
|
+
return {
|
75
|
+
type: 'createDependenciesResult',
|
76
|
+
payload: { dependencies: result, success: true, tx },
|
77
|
+
};
|
78
|
+
}
|
79
|
+
catch (e) {
|
80
|
+
return {
|
81
|
+
type: 'createDependenciesResult',
|
82
|
+
payload: {
|
83
|
+
success: false,
|
84
|
+
error: (0, serializable_error_1.createSerializableError)(e),
|
85
|
+
tx,
|
86
|
+
},
|
87
|
+
};
|
88
|
+
}
|
89
|
+
},
|
90
|
+
processProjectGraph: async ({ graph, ctx, tx }) => {
|
91
|
+
try {
|
92
|
+
const result = await plugin.processProjectGraph(graph, ctx);
|
93
|
+
return {
|
94
|
+
type: 'processProjectGraphResult',
|
95
|
+
payload: { graph: result, success: true, tx },
|
96
|
+
};
|
97
|
+
}
|
98
|
+
catch (e) {
|
99
|
+
return {
|
100
|
+
type: 'processProjectGraphResult',
|
101
|
+
payload: {
|
102
|
+
success: false,
|
103
|
+
error: (0, serializable_error_1.createSerializableError)(e),
|
104
|
+
tx,
|
105
|
+
},
|
106
|
+
};
|
107
|
+
}
|
108
|
+
},
|
109
|
+
createMetadata: async ({ graph, context, tx }) => {
|
110
|
+
try {
|
111
|
+
const result = await plugin.createMetadata(graph, context);
|
112
|
+
return {
|
113
|
+
type: 'createMetadataResult',
|
114
|
+
payload: { metadata: result, success: true, tx },
|
115
|
+
};
|
116
|
+
}
|
117
|
+
catch (e) {
|
118
|
+
return {
|
119
|
+
type: 'createMetadataResult',
|
120
|
+
payload: { success: false, error: e.stack, tx },
|
121
|
+
};
|
122
|
+
}
|
123
|
+
},
|
124
|
+
});
|
125
|
+
}));
|
118
126
|
});
|
127
|
+
server.listen(socketPath);
|
128
|
+
const exitHandler = (exitCode) => () => {
|
129
|
+
server.close();
|
130
|
+
try {
|
131
|
+
(0, fs_1.unlinkSync)(socketPath);
|
132
|
+
}
|
133
|
+
catch (e) { }
|
134
|
+
process.exit(exitCode);
|
135
|
+
};
|
136
|
+
const events = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'exit'];
|
137
|
+
events.forEach((event) => process.once(event, exitHandler(0)));
|
138
|
+
process.once('uncaughtException', exitHandler(1));
|
139
|
+
process.once('unhandledRejection', exitHandler(1));
|
@@ -110,7 +110,13 @@ async function buildProjectGraphAndSourceMapsWithoutDaemon() {
|
|
110
110
|
}
|
111
111
|
}
|
112
112
|
finally {
|
113
|
-
|
113
|
+
// When plugins are isolated we don't clean them up during
|
114
|
+
// a single run of the CLI. They are cleaned up when the CLI
|
115
|
+
// process exits. Cleaning them here could cause issues if pending
|
116
|
+
// promises are not resolved.
|
117
|
+
if (process.env.NX_ISOLATE_PLUGINS !== 'true') {
|
118
|
+
cleanup();
|
119
|
+
}
|
114
120
|
}
|
115
121
|
const { projectGraph, projectFileMapCache } = projectGraphResult;
|
116
122
|
perf_hooks_1.performance.mark('build-project-graph-using-project-file-map:end');
|
@@ -1,10 +1,6 @@
|
|
1
1
|
import { ProjectGraphProjectNode } from '../../config/project-graph';
|
2
2
|
import { ProjectGraphBuilder } from '../project-graph-builder';
|
3
|
-
import { ProjectConfiguration
|
3
|
+
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
4
4
|
import { CreateDependenciesContext } from '../plugins';
|
5
5
|
export declare function normalizeProjectNodes({ projects }: CreateDependenciesContext, builder: ProjectGraphBuilder): Promise<void>;
|
6
|
-
/**
|
7
|
-
* Apply target defaults and normalization
|
8
|
-
*/
|
9
|
-
export declare function normalizeProjectTargets(project: ProjectConfiguration, projectName: string): Record<string, TargetConfiguration>;
|
10
6
|
export declare function normalizeImplicitDependencies(source: string, implicitDependencies: ProjectConfiguration['implicitDependencies'], projects: Record<string, ProjectGraphProjectNode>): string[];
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.normalizeImplicitDependencies = exports.
|
3
|
+
exports.normalizeImplicitDependencies = exports.normalizeProjectNodes = void 0;
|
4
4
|
const find_matching_projects_1 = require("../../utils/find-matching-projects");
|
5
5
|
async function normalizeProjectNodes({ projects }, builder) {
|
6
6
|
// Sorting projects by name to make sure that the order of projects in the graph is deterministic.
|
@@ -23,7 +23,7 @@ async function normalizeProjectNodes({ projects }, builder) {
|
|
23
23
|
for (const key of sortedProjectNames) {
|
24
24
|
const p = projects[key];
|
25
25
|
p.implicitDependencies = normalizeImplicitDependencies(key, p.implicitDependencies, partialProjectGraphNodes);
|
26
|
-
p.targets
|
26
|
+
p.targets ??= {};
|
27
27
|
// TODO: remove in v16
|
28
28
|
const projectType = p.projectType === 'application'
|
29
29
|
? key.endsWith('-e2e') || key === 'e2e'
|
@@ -57,21 +57,6 @@ async function normalizeProjectNodes({ projects }, builder) {
|
|
57
57
|
});
|
58
58
|
}
|
59
59
|
exports.normalizeProjectNodes = normalizeProjectNodes;
|
60
|
-
/**
|
61
|
-
* Apply target defaults and normalization
|
62
|
-
*/
|
63
|
-
function normalizeProjectTargets(project, projectName) {
|
64
|
-
// Any node on the graph will have a targets object, it just may be empty
|
65
|
-
const targets = project.targets ?? {};
|
66
|
-
for (const target in targets) {
|
67
|
-
if (!targets[target].command && !targets[target].executor) {
|
68
|
-
delete targets[target];
|
69
|
-
continue;
|
70
|
-
}
|
71
|
-
}
|
72
|
-
return targets;
|
73
|
-
}
|
74
|
-
exports.normalizeProjectTargets = normalizeProjectTargets;
|
75
60
|
function normalizeImplicitDependencies(source, implicitDependencies, projects) {
|
76
61
|
if (!implicitDependencies?.length) {
|
77
62
|
return implicitDependencies ?? [];
|
@@ -293,7 +293,7 @@ function mergeCreateNodesResults(results, errors) {
|
|
293
293
|
const externalNodes = {};
|
294
294
|
const configurationSourceMaps = {};
|
295
295
|
for (const result of results.flat()) {
|
296
|
-
const [
|
296
|
+
const [pluginName, file, nodes] = result;
|
297
297
|
const { projects: projectNodes, externalNodes: pluginExternalNodes } = nodes;
|
298
298
|
const sourceInfo = [file, pluginName];
|
299
299
|
if (result[symbols_1.OVERRIDE_SOURCE_FILE]) {
|
@@ -436,9 +436,20 @@ function validateAndNormalizeProjectRootMap(projectRootMap) {
|
|
436
436
|
}
|
437
437
|
for (const targetName in project.targets) {
|
438
438
|
project.targets[targetName] = normalizeTarget(project.targets[targetName], project);
|
439
|
-
if (
|
439
|
+
if (
|
440
|
+
// If the target has no executor or command, it doesn't do anything
|
441
|
+
!project.targets[targetName].executor &&
|
440
442
|
!project.targets[targetName].command) {
|
441
|
-
|
443
|
+
// But it may have dependencies that do something
|
444
|
+
if (project.targets[targetName].dependsOn &&
|
445
|
+
project.targets[targetName].dependsOn.length > 0) {
|
446
|
+
project.targets[targetName].executor = 'nx:noop';
|
447
|
+
}
|
448
|
+
else {
|
449
|
+
// If it does nothing, and has no depenencies,
|
450
|
+
// we can remove it.
|
451
|
+
delete project.targets[targetName];
|
452
|
+
}
|
442
453
|
}
|
443
454
|
}
|
444
455
|
}
|
@@ -9,12 +9,12 @@ import { LoadedNxPlugin } from '../plugins/internal-api';
|
|
9
9
|
* @param nxJson
|
10
10
|
*/
|
11
11
|
export declare function retrieveWorkspaceFiles(workspaceRoot: string, projectRootMap: Record<string, string>): Promise<{
|
12
|
-
allWorkspaceFiles: import("
|
12
|
+
allWorkspaceFiles: import("../file-utils").FileData[];
|
13
13
|
fileMap: {
|
14
14
|
projectFileMap: ProjectFiles;
|
15
|
-
nonProjectFiles: import("
|
15
|
+
nonProjectFiles: import("../../native").FileData[];
|
16
16
|
};
|
17
|
-
rustReferences: import("
|
17
|
+
rustReferences: import("../../native").NxWorkspaceFilesExternals;
|
18
18
|
}>;
|
19
19
|
/**
|
20
20
|
* Walk through the workspace and return `ProjectConfigurations`. Only use this if the projectFileMap is not needed.
|
@@ -13,12 +13,12 @@ const defaultTasksRunner = async (tasks, options, context) => {
|
|
13
13
|
options['parallel'] === '') {
|
14
14
|
options['parallel'] = Number(options['maxParallel'] || 3);
|
15
15
|
}
|
16
|
-
options.lifeCycle.startCommand();
|
16
|
+
await options.lifeCycle.startCommand();
|
17
17
|
try {
|
18
18
|
return await runAllTasks(tasks, options, context);
|
19
19
|
}
|
20
20
|
finally {
|
21
|
-
options.lifeCycle.endCommand();
|
21
|
+
await options.lifeCycle.endCommand();
|
22
22
|
}
|
23
23
|
};
|
24
24
|
exports.defaultTasksRunner = defaultTasksRunner;
|
@@ -10,9 +10,9 @@ export interface TaskMetadata {
|
|
10
10
|
groupId: number;
|
11
11
|
}
|
12
12
|
export interface LifeCycle {
|
13
|
-
startCommand?(): void
|
14
|
-
endCommand?(): void
|
15
|
-
scheduleTask?(task: Task): void
|
13
|
+
startCommand?(): void | Promise<void>;
|
14
|
+
endCommand?(): void | Promise<void>;
|
15
|
+
scheduleTask?(task: Task): void | Promise<void>;
|
16
16
|
/**
|
17
17
|
* @deprecated use startTasks
|
18
18
|
*
|
@@ -25,19 +25,19 @@ export interface LifeCycle {
|
|
25
25
|
* endTask won't be supported after Nx 14 is released.
|
26
26
|
*/
|
27
27
|
endTask?(task: Task, code: number): void;
|
28
|
-
startTasks?(task: Task[], metadata: TaskMetadata): void
|
29
|
-
endTasks?(taskResults: TaskResult[], metadata: TaskMetadata): void
|
28
|
+
startTasks?(task: Task[], metadata: TaskMetadata): void | Promise<void>;
|
29
|
+
endTasks?(taskResults: TaskResult[], metadata: TaskMetadata): void | Promise<void>;
|
30
30
|
printTaskTerminalOutput?(task: Task, status: TaskStatus, output: string): void;
|
31
31
|
}
|
32
32
|
export declare class CompositeLifeCycle implements LifeCycle {
|
33
33
|
private readonly lifeCycles;
|
34
34
|
constructor(lifeCycles: LifeCycle[]);
|
35
|
-
startCommand(): void
|
36
|
-
endCommand(): void
|
37
|
-
scheduleTask(task: Task): void
|
35
|
+
startCommand(): Promise<void>;
|
36
|
+
endCommand(): Promise<void>;
|
37
|
+
scheduleTask(task: Task): Promise<void>;
|
38
38
|
startTask(task: Task): void;
|
39
39
|
endTask(task: Task, code: number): void;
|
40
|
-
startTasks(tasks: Task[], metadata: TaskMetadata): void
|
41
|
-
endTasks(taskResults: TaskResult[], metadata: TaskMetadata): void
|
40
|
+
startTasks(tasks: Task[], metadata: TaskMetadata): Promise<void>;
|
41
|
+
endTasks(taskResults: TaskResult[], metadata: TaskMetadata): Promise<void>;
|
42
42
|
printTaskTerminalOutput(task: Task, status: TaskStatus, output: string): void;
|
43
43
|
}
|
@@ -5,24 +5,24 @@ class CompositeLifeCycle {
|
|
5
5
|
constructor(lifeCycles) {
|
6
6
|
this.lifeCycles = lifeCycles;
|
7
7
|
}
|
8
|
-
startCommand() {
|
8
|
+
async startCommand() {
|
9
9
|
for (let l of this.lifeCycles) {
|
10
10
|
if (l.startCommand) {
|
11
|
-
l.startCommand();
|
11
|
+
await l.startCommand();
|
12
12
|
}
|
13
13
|
}
|
14
14
|
}
|
15
|
-
endCommand() {
|
15
|
+
async endCommand() {
|
16
16
|
for (let l of this.lifeCycles) {
|
17
17
|
if (l.endCommand) {
|
18
|
-
l.endCommand();
|
18
|
+
await l.endCommand();
|
19
19
|
}
|
20
20
|
}
|
21
21
|
}
|
22
|
-
scheduleTask(task) {
|
22
|
+
async scheduleTask(task) {
|
23
23
|
for (let l of this.lifeCycles) {
|
24
24
|
if (l.scheduleTask) {
|
25
|
-
l.scheduleTask(task);
|
25
|
+
await l.scheduleTask(task);
|
26
26
|
}
|
27
27
|
}
|
28
28
|
}
|
@@ -40,20 +40,20 @@ class CompositeLifeCycle {
|
|
40
40
|
}
|
41
41
|
}
|
42
42
|
}
|
43
|
-
startTasks(tasks, metadata) {
|
43
|
+
async startTasks(tasks, metadata) {
|
44
44
|
for (let l of this.lifeCycles) {
|
45
45
|
if (l.startTasks) {
|
46
|
-
l.startTasks(tasks, metadata);
|
46
|
+
await l.startTasks(tasks, metadata);
|
47
47
|
}
|
48
48
|
else if (l.startTask) {
|
49
49
|
tasks.forEach((t) => l.startTask(t));
|
50
50
|
}
|
51
51
|
}
|
52
52
|
}
|
53
|
-
endTasks(taskResults, metadata) {
|
53
|
+
async endTasks(taskResults, metadata) {
|
54
54
|
for (let l of this.lifeCycles) {
|
55
55
|
if (l.endTasks) {
|
56
|
-
l.endTasks(taskResults, metadata);
|
56
|
+
await l.endTasks(taskResults, metadata);
|
57
57
|
}
|
58
58
|
else if (l.endTask) {
|
59
59
|
taskResults.forEach((t) => l.endTask(t.task, t.code));
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Task } from '../../config/task-graph';
|
2
|
+
import { LifeCycle, TaskResult } from '../life-cycle';
|
3
|
+
export declare class TaskHistoryLifeCycle implements LifeCycle {
|
4
|
+
private startTimings;
|
5
|
+
private taskRuns;
|
6
|
+
startTasks(tasks: Task[]): void;
|
7
|
+
endTasks(taskResults: TaskResult[]): Promise<void>;
|
8
|
+
endCommand(): Promise<void>;
|
9
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.TaskHistoryLifeCycle = void 0;
|
4
|
+
const serialize_target_1 = require("../../utils/serialize-target");
|
5
|
+
const output_1 = require("../../utils/output");
|
6
|
+
const task_history_1 = require("../../utils/task-history");
|
7
|
+
class TaskHistoryLifeCycle {
|
8
|
+
constructor() {
|
9
|
+
this.startTimings = {};
|
10
|
+
this.taskRuns = [];
|
11
|
+
}
|
12
|
+
startTasks(tasks) {
|
13
|
+
for (let task of tasks) {
|
14
|
+
this.startTimings[task.id] = new Date().getTime();
|
15
|
+
}
|
16
|
+
}
|
17
|
+
async endTasks(taskResults) {
|
18
|
+
const taskRuns = taskResults.map((taskResult) => ({
|
19
|
+
project: taskResult.task.target.project,
|
20
|
+
target: taskResult.task.target.target,
|
21
|
+
configuration: taskResult.task.target.configuration,
|
22
|
+
hash: taskResult.task.hash,
|
23
|
+
code: taskResult.code.toString(),
|
24
|
+
status: taskResult.status,
|
25
|
+
start: (taskResult.task.startTime ?? this.startTimings[taskResult.task.id]).toString(),
|
26
|
+
end: (taskResult.task.endTime ?? new Date().getTime()).toString(),
|
27
|
+
}));
|
28
|
+
this.taskRuns.push(...taskRuns);
|
29
|
+
}
|
30
|
+
async endCommand() {
|
31
|
+
await (0, task_history_1.writeTaskRunsToHistory)(this.taskRuns);
|
32
|
+
const history = await (0, task_history_1.getHistoryForHashes)(this.taskRuns.map((t) => t.hash));
|
33
|
+
const flakyTasks = [];
|
34
|
+
// check if any hash has different exit codes => flaky
|
35
|
+
for (let hash in history) {
|
36
|
+
if (history[hash].length > 1 &&
|
37
|
+
history[hash].some((run) => run.code !== history[hash][0].code)) {
|
38
|
+
flakyTasks.push((0, serialize_target_1.serializeTarget)(history[hash][0].project, history[hash][0].target, history[hash][0].configuration));
|
39
|
+
}
|
40
|
+
}
|
41
|
+
if (flakyTasks.length > 0) {
|
42
|
+
output_1.output.warn({
|
43
|
+
title: `Nx detected ${flakyTasks.length === 1 ? 'a flaky task' : ' flaky tasks'}`,
|
44
|
+
bodyLines: [
|
45
|
+
,
|
46
|
+
...flakyTasks.map((t) => ` ${t}`),
|
47
|
+
'',
|
48
|
+
`Flaky tasks can disrupt your CI pipeline. Automatically retry them with Nx Cloud. Learn more at https://nx.dev/ci/features/flaky-tasks`,
|
49
|
+
],
|
50
|
+
});
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
exports.TaskHistoryLifeCycle = TaskHistoryLifeCycle;
|
@@ -14,6 +14,7 @@ const dynamic_run_many_terminal_output_life_cycle_1 = require("./life-cycles/dyn
|
|
14
14
|
const task_profiling_life_cycle_1 = require("./life-cycles/task-profiling-life-cycle");
|
15
15
|
const is_ci_1 = require("../utils/is-ci");
|
16
16
|
const dynamic_run_one_terminal_output_life_cycle_1 = require("./life-cycles/dynamic-run-one-terminal-output-life-cycle");
|
17
|
+
const nx_json_1 = require("../config/nx-json");
|
17
18
|
const create_task_graph_1 = require("./create-task-graph");
|
18
19
|
const task_graph_utils_1 = require("./task-graph-utils");
|
19
20
|
const params_1 = require("../utils/params");
|
@@ -21,6 +22,8 @@ const hash_task_1 = require("../hasher/hash-task");
|
|
21
22
|
const client_1 = require("../daemon/client/client");
|
22
23
|
const store_run_information_life_cycle_1 = require("./life-cycles/store-run-information-life-cycle");
|
23
24
|
const create_task_hasher_1 = require("../hasher/create-task-hasher");
|
25
|
+
const task_history_life_cycle_1 = require("./life-cycles/task-history-life-cycle");
|
26
|
+
const nx_cloud_utils_1 = require("../utils/nx-cloud-utils");
|
24
27
|
async function getTerminalOutputLifeCycle(initiatingProject, projectNames, tasks, nxArgs, nxJson, overrides) {
|
25
28
|
const { runnerOptions } = getRunner(nxArgs, nxJson);
|
26
29
|
const isRunOne = initiatingProject != null;
|
@@ -203,6 +206,9 @@ function constructLifeCycles(lifeCycle) {
|
|
203
206
|
if (process.env.NX_PROFILE) {
|
204
207
|
lifeCycles.push(new task_profiling_life_cycle_1.TaskProfilingLifeCycle(process.env.NX_PROFILE));
|
205
208
|
}
|
209
|
+
if (!(0, nx_cloud_utils_1.isNxCloudUsed)((0, nx_json_1.readNxJson)())) {
|
210
|
+
lifeCycles.push(new task_history_life_cycle_1.TaskHistoryLifeCycle());
|
211
|
+
}
|
206
212
|
return lifeCycles;
|
207
213
|
}
|
208
214
|
function mergeTargetDependencies(defaults, deps) {
|
@@ -6,3 +6,16 @@ export declare function getEnvVariablesForTask(task: Task, taskSpecificEnv: Node
|
|
6
6
|
[x: string]: string;
|
7
7
|
TZ?: string;
|
8
8
|
};
|
9
|
+
/**
|
10
|
+
* This function loads a .env file and expands the variables in it.
|
11
|
+
* It is going to override existing environmentVariables.
|
12
|
+
* @param filename
|
13
|
+
* @param environmentVariables
|
14
|
+
*/
|
15
|
+
export declare function loadAndExpandDotEnvFile(filename: string, environmentVariables: NodeJS.ProcessEnv, override?: boolean): import("dotenv-expand").DotenvExpandOutput;
|
16
|
+
/**
|
17
|
+
* This function unloads a .env file and removes the variables in it from the environmentVariables.
|
18
|
+
* @param filename
|
19
|
+
* @param environmentVariables
|
20
|
+
*/
|
21
|
+
export declare function unloadDotEnvFile(filename: string, environmentVariables: NodeJS.ProcessEnv, override?: boolean): void;
|