nx 19.4.0-beta.0 → 19.4.0-beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. package/package.json +14 -14
  2. package/release/changelog-renderer/index.d.ts +6 -0
  3. package/release/changelog-renderer/index.js +1 -1
  4. package/src/command-line/connect/connect-to-nx-cloud.d.ts +1 -1
  5. package/src/command-line/connect/connect-to-nx-cloud.js +16 -25
  6. package/src/command-line/graph/graph.d.ts +1 -0
  7. package/src/command-line/graph/graph.js +12 -1
  8. package/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +5 -6
  9. package/src/command-line/release/changelog.js +6 -1
  10. package/src/command-line/release/config/config.js +3 -0
  11. package/src/command-line/run/command-object.js +2 -1
  12. package/src/config/workspace-json-project-json.d.ts +2 -0
  13. package/src/core/graph/main.js +1 -1
  14. package/src/core/graph/styles.css +1 -1
  15. package/src/daemon/client/client.d.ts +5 -0
  16. package/src/daemon/client/client.js +14 -0
  17. package/src/daemon/message-types/task-history.d.ts +13 -0
  18. package/src/daemon/message-types/task-history.js +19 -0
  19. package/src/daemon/server/handle-get-task-history.d.ts +4 -0
  20. package/src/daemon/server/handle-get-task-history.js +12 -0
  21. package/src/daemon/server/handle-write-task-runs-to-history.d.ts +5 -0
  22. package/src/daemon/server/handle-write-task-runs-to-history.js +12 -0
  23. package/src/daemon/server/plugins.js +12 -2
  24. package/src/daemon/server/server.js +9 -0
  25. package/src/daemon/socket-utils.d.ts +1 -0
  26. package/src/daemon/socket-utils.js +6 -1
  27. package/src/executors/run-commands/run-commands.impl.js +29 -20
  28. package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.d.ts +1 -0
  29. package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +68 -33
  30. package/src/nx-cloud/generators/connect-to-nx-cloud/schema.json +5 -0
  31. package/src/nx-cloud/utilities/url-shorten.d.ts +2 -1
  32. package/src/nx-cloud/utilities/url-shorten.js +47 -11
  33. package/src/plugins/package-json-workspaces/create-nodes.js +12 -7
  34. package/src/plugins/project-json/build-nodes/package-json-next-to-project-json.js +10 -2
  35. package/src/plugins/target-defaults/target-defaults-plugin.d.ts +5 -0
  36. package/src/project-graph/plugins/internal-api.js +1 -1
  37. package/src/project-graph/plugins/isolation/index.d.ts +1 -1
  38. package/src/project-graph/plugins/isolation/index.js +8 -13
  39. package/src/project-graph/plugins/isolation/messaging.d.ts +6 -3
  40. package/src/project-graph/plugins/isolation/messaging.js +9 -3
  41. package/src/project-graph/plugins/isolation/plugin-pool.d.ts +1 -1
  42. package/src/project-graph/plugins/isolation/plugin-pool.js +123 -43
  43. package/src/project-graph/plugins/isolation/plugin-worker.js +128 -107
  44. package/src/project-graph/project-graph.js +7 -1
  45. package/src/project-graph/utils/normalize-project-nodes.d.ts +1 -5
  46. package/src/project-graph/utils/normalize-project-nodes.js +2 -17
  47. package/src/project-graph/utils/project-configuration-utils.js +14 -3
  48. package/src/project-graph/utils/retrieve-workspace-files.d.ts +3 -3
  49. package/src/tasks-runner/default-tasks-runner.js +2 -2
  50. package/src/tasks-runner/life-cycle.d.ts +10 -10
  51. package/src/tasks-runner/life-cycle.js +10 -10
  52. package/src/tasks-runner/life-cycles/task-history-life-cycle.d.ts +9 -0
  53. package/src/tasks-runner/life-cycles/task-history-life-cycle.js +54 -0
  54. package/src/tasks-runner/run-command.js +6 -0
  55. package/src/tasks-runner/task-env.d.ts +13 -0
  56. package/src/tasks-runner/task-env.js +41 -26
  57. package/src/tasks-runner/task-orchestrator.js +4 -4
  58. package/src/utils/git-utils.d.ts +1 -1
  59. package/src/utils/git-utils.js +13 -2
  60. package/src/utils/nx-cloud-utils.d.ts +1 -1
  61. package/src/utils/nx-cloud-utils.js +1 -1
  62. package/src/utils/package-json.d.ts +3 -0
  63. package/src/utils/package-json.js +15 -3
  64. package/src/utils/serialize-target.d.ts +1 -0
  65. package/src/utils/serialize-target.js +7 -0
  66. package/src/utils/task-history.d.ts +8 -0
  67. 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
- process.on('message', async (message) => {
12
- if (!(0, messaging_1.isPluginWorkerMessage)(message)) {
13
- return;
14
- }
15
- return (0, messaging_1.consumeMessage)(message, {
16
- load: async ({ plugin: pluginConfiguration, root }) => {
17
- process.chdir(root);
18
- try {
19
- const [promise] = (0, loader_1.loadNxPlugin)(pluginConfiguration, root);
20
- plugin = await promise;
21
- return {
22
- type: 'load-result',
23
- payload: {
24
- name: plugin.name,
25
- include: plugin.include,
26
- exclude: plugin.exclude,
27
- createNodesPattern: plugin.createNodes?.[0],
28
- hasCreateDependencies: 'createDependencies' in plugin && !!plugin.createDependencies,
29
- hasProcessProjectGraph: 'processProjectGraph' in plugin && !!plugin.processProjectGraph,
30
- hasCreateMetadata: 'createMetadata' in plugin && !!plugin.createMetadata,
31
- success: true,
32
- },
33
- };
34
- }
35
- catch (e) {
36
- return {
37
- type: 'load-result',
38
- payload: {
39
- success: false,
40
- error: (0, serializable_error_1.createSerializableError)(e),
41
- },
42
- };
43
- }
44
- },
45
- createNodes: async ({ configFiles, context, tx }) => {
46
- try {
47
- const result = await plugin.createNodes[1](configFiles, context);
48
- return {
49
- type: 'createNodesResult',
50
- payload: { result, success: true, tx },
51
- };
52
- }
53
- catch (e) {
54
- return {
55
- type: 'createNodesResult',
56
- payload: {
57
- success: false,
58
- error: (0, serializable_error_1.createSerializableError)(e),
59
- tx,
60
- },
61
- };
62
- }
63
- },
64
- createDependencies: async ({ context, tx }) => {
65
- try {
66
- const result = await plugin.createDependencies(context);
67
- return {
68
- type: 'createDependenciesResult',
69
- payload: { dependencies: result, success: true, tx },
70
- };
71
- }
72
- catch (e) {
73
- return {
74
- type: 'createDependenciesResult',
75
- payload: {
76
- success: false,
77
- error: (0, serializable_error_1.createSerializableError)(e),
78
- tx,
79
- },
80
- };
81
- }
82
- },
83
- processProjectGraph: async ({ graph, ctx, tx }) => {
84
- try {
85
- const result = await plugin.processProjectGraph(graph, ctx);
86
- return {
87
- type: 'processProjectGraphResult',
88
- payload: { graph: result, success: true, tx },
89
- };
90
- }
91
- catch (e) {
92
- return {
93
- type: 'processProjectGraphResult',
94
- payload: {
95
- success: false,
96
- error: (0, serializable_error_1.createSerializableError)(e),
97
- tx,
98
- },
99
- };
100
- }
101
- },
102
- createMetadata: async ({ graph, context, tx }) => {
103
- try {
104
- const result = await plugin.createMetadata(graph, context);
105
- return {
106
- type: 'createMetadataResult',
107
- payload: { metadata: result, success: true, tx },
108
- };
109
- }
110
- catch (e) {
111
- return {
112
- type: 'createMetadataResult',
113
- payload: { success: false, error: e.stack, tx },
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
- cleanup();
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, TargetConfiguration } from '../../config/workspace-json-project-json';
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.normalizeProjectTargets = exports.normalizeProjectNodes = void 0;
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 = normalizeProjectTargets(p, key);
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 [file, pluginName, nodes] = result;
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 (!project.targets[targetName].executor &&
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
- delete project.targets[targetName];
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("nx/src/devkit-exports").FileData[];
12
+ allWorkspaceFiles: import("../file-utils").FileData[];
13
13
  fileMap: {
14
14
  projectFileMap: ProjectFiles;
15
- nonProjectFiles: import("nx/src/native").FileData[];
15
+ nonProjectFiles: import("../../native").FileData[];
16
16
  };
17
- rustReferences: import("nx/src/native").NxWorkspaceFilesExternals;
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;