nx 19.8.2 → 19.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. package/.eslintrc.json +12 -2
  2. package/package.json +12 -12
  3. package/src/command-line/add/add.js +2 -2
  4. package/src/command-line/import/utils/prepare-source-repo.js +8 -3
  5. package/src/command-line/nx-commands.js +31 -10
  6. package/src/command-line/release/utils/print-changes.js +6 -4
  7. package/src/command-line/release/utils/resolve-nx-json-error-message.js +4 -3
  8. package/src/command-line/reset/reset.js +16 -9
  9. package/src/command-line/yargs-utils/shared-options.js +2 -2
  10. package/src/core/graph/main.js +1 -1
  11. package/src/executors/run-commands/run-commands.impl.js +15 -22
  12. package/src/hasher/hash-task.d.ts +4 -2
  13. package/src/hasher/hash-task.js +6 -9
  14. package/src/native/nx.wasm32-wasi.wasm +0 -0
  15. package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +54 -6
  16. package/src/nx-cloud/utilities/axios.js +1 -2
  17. package/src/nx-cloud/utilities/onboarding.js +2 -2
  18. package/src/nx-cloud/utilities/url-shorten.js +5 -5
  19. package/src/project-graph/utils/project-configuration-utils.js +1 -1
  20. package/src/tasks-runner/cache.d.ts +2 -1
  21. package/src/tasks-runner/cache.js +10 -6
  22. package/src/tasks-runner/create-task-graph.d.ts +2 -0
  23. package/src/tasks-runner/create-task-graph.js +39 -5
  24. package/src/tasks-runner/life-cycles/dynamic-run-many-terminal-output-life-cycle.js +5 -0
  25. package/src/tasks-runner/life-cycles/static-run-many-terminal-output-life-cycle.js +7 -0
  26. package/src/tasks-runner/run-command.js +3 -1
  27. package/src/tasks-runner/task-orchestrator.d.ts +1 -0
  28. package/src/tasks-runner/task-orchestrator.js +7 -3
  29. package/src/tasks-runner/tasks-schedule.d.ts +1 -0
  30. package/src/tasks-runner/tasks-schedule.js +6 -2
  31. package/src/utils/git-utils.js +2 -2
  32. package/src/utils/plugins/output.js +1 -1
@@ -16,22 +16,11 @@ let pseudoTerminal;
16
16
  const childProcesses = new Set();
17
17
  function loadEnvVarsFile(path, env = {}) {
18
18
  (0, task_env_1.unloadDotEnvFile)(path, env);
19
- const result = (0, task_env_1.loadAndExpandDotEnvFile)(path, env, true);
19
+ const result = (0, task_env_1.loadAndExpandDotEnvFile)(path, env);
20
20
  if (result.error) {
21
21
  throw result.error;
22
22
  }
23
23
  }
24
- function loadEnvVars(path, env = {}) {
25
- if (path) {
26
- loadEnvVarsFile(path, env);
27
- }
28
- else {
29
- try {
30
- loadEnvVarsFile('.env', env);
31
- }
32
- catch { }
33
- }
34
- }
35
24
  const propKeys = [
36
25
  'command',
37
26
  'commands',
@@ -292,20 +281,24 @@ function calculateCwd(cwd, context) {
292
281
  return cwd;
293
282
  return path.join(context.root, cwd);
294
283
  }
295
- function processEnv(color, cwd, env, envFile) {
296
- const localEnv = (0, npm_run_path_1.env)({ cwd: cwd ?? process.cwd() });
297
- let res = {
284
+ /**
285
+ * Env variables are processed in the following order:
286
+ * - env option from executor options
287
+ * - env file from envFile option if provided
288
+ * - local env variables
289
+ */
290
+ function processEnv(color, cwd, envOptionFromExecutor, envFile) {
291
+ let localEnv = (0, npm_run_path_1.env)({ cwd: cwd ?? process.cwd() });
292
+ localEnv = {
298
293
  ...process.env,
299
294
  ...localEnv,
300
295
  };
301
- // env file from envFile option takes priority over process env
302
- if (process.env.NX_LOAD_DOT_ENV_FILES !== 'false') {
303
- loadEnvVars(envFile, res);
296
+ if (process.env.NX_LOAD_DOT_ENV_FILES !== 'false' && envFile) {
297
+ loadEnvVarsFile(envFile, localEnv);
304
298
  }
305
- // env variables from env option takes priority over everything else
306
- res = {
307
- ...res,
308
- ...env,
299
+ let res = {
300
+ ...localEnv,
301
+ ...envOptionFromExecutor,
309
302
  };
310
303
  // need to override PATH to make sure we are using the local node_modules
311
304
  if (localEnv.PATH)
@@ -2,5 +2,7 @@ import { Task, TaskGraph } from '../config/task-graph';
2
2
  import { TaskHasher } from './task-hasher';
3
3
  import { ProjectGraph } from '../config/project-graph';
4
4
  import { NxJsonConfiguration } from '../config/nx-json';
5
- export declare function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration): Promise<void>;
6
- export declare function hashTask(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, task: Task, env: NodeJS.ProcessEnv): Promise<void>;
5
+ import { TaskDetails } from '../native';
6
+ export declare function getTaskDetails(): TaskDetails | null;
7
+ export declare function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, tasksDetails: TaskDetails | null): Promise<void>;
8
+ export declare function hashTask(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, task: Task, env: NodeJS.ProcessEnv, taskDetails: TaskDetails | null): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTaskDetails = getTaskDetails;
3
4
  exports.hashTasksThatDoNotDependOnOutputsOfOtherTasks = hashTasksThatDoNotDependOnOutputsOfOtherTasks;
4
5
  exports.hashTask = hashTask;
5
6
  const utils_1 = require("../tasks-runner/utils");
@@ -19,9 +20,8 @@ function getTaskDetails() {
19
20
  }
20
21
  return taskDetails;
21
22
  }
22
- async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGraph, taskGraph, nxJson) {
23
+ async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGraph, taskGraph, nxJson, tasksDetails) {
23
24
  performance.mark('hashMultipleTasks:start');
24
- const taskDetails = getTaskDetails();
25
25
  const tasks = Object.values(taskGraph.tasks);
26
26
  const tasksWithHashers = await Promise.all(tasks.map(async (task) => {
27
27
  const customHasher = (0, utils_1.getCustomHasher)(task, projectGraph);
@@ -42,9 +42,8 @@ async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGrap
42
42
  tasksToHash[i].hash = hashes[i].value;
43
43
  tasksToHash[i].hashDetails = hashes[i].details;
44
44
  }
45
- // TODO: Remove if when sqlite is always on
46
- if (taskDetails) {
47
- taskDetails.recordTaskDetails(tasksToHash.map((task) => ({
45
+ if (tasksDetails?.recordTaskDetails) {
46
+ tasksDetails.recordTaskDetails(tasksToHash.map((task) => ({
48
47
  hash: task.hash,
49
48
  project: task.target.project,
50
49
  target: task.target.target,
@@ -54,9 +53,8 @@ async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGrap
54
53
  performance.mark('hashMultipleTasks:end');
55
54
  performance.measure('hashMultipleTasks', 'hashMultipleTasks:start', 'hashMultipleTasks:end');
56
55
  }
57
- async function hashTask(hasher, projectGraph, taskGraph, task, env) {
56
+ async function hashTask(hasher, projectGraph, taskGraph, task, env, taskDetails) {
58
57
  performance.mark('hashSingleTask:start');
59
- const taskDetails = getTaskDetails();
60
58
  const customHasher = (0, utils_1.getCustomHasher)(task, projectGraph);
61
59
  const projectsConfigurations = (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
62
60
  const { value, details } = await (customHasher
@@ -72,8 +70,7 @@ async function hashTask(hasher, projectGraph, taskGraph, task, env) {
72
70
  : hasher.hashTask(task, taskGraph, env));
73
71
  task.hash = value;
74
72
  task.hashDetails = details;
75
- // TODO: Remove if when wasm supports sqlite
76
- if (taskDetails) {
73
+ if (taskDetails?.recordTaskDetails) {
77
74
  taskDetails.recordTaskDetails([
78
75
  {
79
76
  hash: task.hash,
Binary file
@@ -42,6 +42,18 @@ function getNxInitDate() {
42
42
  return null;
43
43
  }
44
44
  }
45
+ async function createNxCloudWorkspaceV1(workspaceName, installationSource, nxInitDate) {
46
+ const apiUrl = (0, get_cloud_options_1.getCloudUrl)();
47
+ const response = await require('axios').post(`${apiUrl}/nx-cloud/create-org-and-workspace`, {
48
+ workspaceName,
49
+ installationSource,
50
+ nxInitDate,
51
+ });
52
+ if (response.data.message) {
53
+ throw new Error(response.data.message);
54
+ }
55
+ return response.data;
56
+ }
45
57
  async function createNxCloudWorkspaceV2(workspaceName, installationSource, nxInitDate) {
46
58
  const apiUrl = (0, get_cloud_options_1.getCloudUrl)();
47
59
  const response = await require('axios').post(`${apiUrl}/nx-cloud/v2/create-org-and-workspace`, {
@@ -69,6 +81,19 @@ async function printSuccessMessage(token, installationSource, usesGithub) {
69
81
  });
70
82
  return connectCloudUrl;
71
83
  }
84
+ function addNxCloudAccessTokenToNxJson(tree, token, directory = '') {
85
+ const nxJsonPath = (0, path_1.join)(directory, 'nx.json');
86
+ if (tree.exists(nxJsonPath)) {
87
+ (0, json_1.updateJson)(tree, (0, path_1.join)(directory, 'nx.json'), (nxJson) => {
88
+ const overrideUrl = process.env.NX_CLOUD_API || process.env.NRWL_API;
89
+ if (overrideUrl) {
90
+ nxJson.nxCloudUrl = overrideUrl;
91
+ }
92
+ nxJson.nxCloudAccessToken = token;
93
+ return nxJson;
94
+ });
95
+ }
96
+ }
72
97
  function addNxCloudIdToNxJson(tree, nxCloudId, directory = '') {
73
98
  const nxJsonPath = (0, path_1.join)(directory, 'nx.json');
74
99
  if (tree.exists(nxJsonPath)) {
@@ -89,6 +114,7 @@ async function connectToNxCloud(tree, schema, nxJson = (0, nx_json_1.readNxJson)
89
114
  return null;
90
115
  }
91
116
  const isGitHubDetected = schema.github ?? (await (0, url_shorten_1.repoUsesGithub)(schema.github));
117
+ let responseFromCreateNxCloudWorkspaceV1;
92
118
  let responseFromCreateNxCloudWorkspaceV2;
93
119
  /**
94
120
  * Do not create an Nx Cloud token if the user is using GitHub and
@@ -98,12 +124,34 @@ async function connectToNxCloud(tree, schema, nxJson = (0, nx_json_1.readNxJson)
98
124
  isGitHubDetected &&
99
125
  schema.installationSource === 'nx-connect')
100
126
  return null;
101
- responseFromCreateNxCloudWorkspaceV2 = await createNxCloudWorkspaceV2(getRootPackageName(tree), schema.installationSource, getNxInitDate());
102
- addNxCloudIdToNxJson(tree, responseFromCreateNxCloudWorkspaceV2?.nxCloudId, schema.directory);
103
- await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree, {
104
- silent: schema.hideFormatLogs,
105
- });
106
- return responseFromCreateNxCloudWorkspaceV2.nxCloudId;
127
+ try {
128
+ responseFromCreateNxCloudWorkspaceV2 = await createNxCloudWorkspaceV2(getRootPackageName(tree), schema.installationSource, getNxInitDate());
129
+ }
130
+ catch (e) {
131
+ if (e.response?.status === 404) {
132
+ responseFromCreateNxCloudWorkspaceV1 = await createNxCloudWorkspaceV1(getRootPackageName(tree), schema.installationSource, getNxInitDate());
133
+ }
134
+ else {
135
+ throw e;
136
+ }
137
+ }
138
+ if (responseFromCreateNxCloudWorkspaceV2) {
139
+ addNxCloudIdToNxJson(tree, responseFromCreateNxCloudWorkspaceV2?.nxCloudId, schema.directory);
140
+ await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree, {
141
+ silent: schema.hideFormatLogs,
142
+ });
143
+ return responseFromCreateNxCloudWorkspaceV2.nxCloudId;
144
+ }
145
+ else if (responseFromCreateNxCloudWorkspaceV1) {
146
+ addNxCloudAccessTokenToNxJson(tree, responseFromCreateNxCloudWorkspaceV1?.token, schema.directory);
147
+ await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree, {
148
+ silent: schema.hideFormatLogs,
149
+ });
150
+ return responseFromCreateNxCloudWorkspaceV1.token;
151
+ }
152
+ else {
153
+ throw new Error('Could not create an Nx Cloud Workspace. Please try again.');
154
+ }
107
155
  }
108
156
  async function connectToNxCloudGenerator(tree, options) {
109
157
  await connectToNxCloud(tree, options);
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createApiAxiosInstance = createApiAxiosInstance;
4
4
  const path_1 = require("path");
5
5
  const environment_1 = require("./environment");
6
- const axios = require('axios');
7
6
  function createApiAxiosInstance(options) {
8
7
  let axiosConfigBuilder = (axiosConfig) => axiosConfig;
9
8
  const baseUrl = process.env.NX_CLOUD_API || options.url || 'https://cloud.nx.app';
@@ -17,7 +16,7 @@ function createApiAxiosInstance(options) {
17
16
  const { nxCloudProxyConfig } = require((0, path_1.join)(process.cwd(), options.customProxyConfigPath));
18
17
  axiosConfigBuilder = nxCloudProxyConfig ?? axiosConfigBuilder;
19
18
  }
20
- return axios.create(axiosConfigBuilder({
19
+ return require('axios').create(axiosConfigBuilder({
21
20
  baseURL: baseUrl,
22
21
  timeout: environment_1.NX_CLOUD_NO_TIMEOUTS ? environment_1.UNLIMITED_TIMEOUT : 10000,
23
22
  headers: { authorization: accessToken },
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createNxCloudOnboardingURLForWelcomeApp = createNxCloudOnboardingURLForWelcomeApp;
4
4
  exports.getNxCloudAppOnBoardingUrl = getNxCloudAppOnBoardingUrl;
5
5
  exports.readNxCloudToken = readNxCloudToken;
6
- const devkit_exports_1 = require("../../devkit-exports");
7
6
  const is_workspace_claimed_1 = require("./is-workspace-claimed");
8
7
  const url_shorten_1 = require("./url-shorten");
9
8
  const run_command_1 = require("../../tasks-runner/run-command");
9
+ const nx_json_1 = require("../../generators/utils/nx-json");
10
10
  async function createNxCloudOnboardingURLForWelcomeApp(tree, token) {
11
11
  token = token || readNxCloudToken(tree);
12
12
  if (!token) {
@@ -22,7 +22,7 @@ async function getNxCloudAppOnBoardingUrl(token) {
22
22
  return onboardingUrl;
23
23
  }
24
24
  function readNxCloudToken(tree) {
25
- const nxJson = (0, devkit_exports_1.readNxJson)(tree);
25
+ const nxJson = (0, nx_json_1.readNxJson)(tree);
26
26
  const { accessToken, nxCloudId } = (0, run_command_1.getRunnerOptions)('default', nxJson, {}, true);
27
27
  return accessToken || nxCloudId;
28
28
  }
@@ -7,7 +7,7 @@ exports.getNxCloudVersion = getNxCloudVersion;
7
7
  exports.removeVersionModifier = removeVersionModifier;
8
8
  exports.versionIsValid = versionIsValid;
9
9
  exports.compareCleanCloudVersions = compareCleanCloudVersions;
10
- const devkit_exports_1 = require("../../devkit-exports");
10
+ const logger_1 = require("../../utils/logger");
11
11
  const git_utils_1 = require("../../utils/git-utils");
12
12
  const get_cloud_options_1 = require("./get-cloud-options");
13
13
  /**
@@ -27,7 +27,7 @@ async function createNxCloudOnboardingURL(onboardingSource, accessToken, usesGit
27
27
  }
28
28
  }
29
29
  catch (e) {
30
- devkit_exports_1.logger.verbose(`Failed to get Nx Cloud version.
30
+ logger_1.logger.verbose(`Failed to get Nx Cloud version.
31
31
  ${e}`);
32
32
  return apiUrl;
33
33
  }
@@ -46,7 +46,7 @@ async function createNxCloudOnboardingURL(onboardingSource, accessToken, usesGit
46
46
  return `${apiUrl}/connect/${response.data}`;
47
47
  }
48
48
  catch (e) {
49
- devkit_exports_1.logger.verbose(`Failed to shorten Nx Cloud URL.
49
+ logger_1.logger.verbose(`Failed to shorten Nx Cloud URL.
50
50
  ${e}`);
51
51
  return getURLifShortenFailed(usesGithub, githubSlug === 'github' ? null : githubSlug, apiUrl, source, accessToken);
52
52
  }
@@ -96,7 +96,7 @@ async function getInstallationSupportsGitHub(apiUrl) {
96
96
  }
97
97
  catch (e) {
98
98
  if (process.env.NX_VERBOSE_LOGGING === 'true') {
99
- devkit_exports_1.logger.warn(`Failed to access system features. GitHub integration assumed to be disabled.
99
+ logger_1.logger.warn(`Failed to access system features. GitHub integration assumed to be disabled.
100
100
  ${e}`);
101
101
  }
102
102
  return false;
@@ -116,7 +116,7 @@ async function getNxCloudVersion(apiUrl) {
116
116
  return version;
117
117
  }
118
118
  catch (e) {
119
- devkit_exports_1.logger.verbose(`Failed to get version of Nx Cloud.
119
+ logger_1.logger.verbose(`Failed to get version of Nx Cloud.
120
120
  ${e}`);
121
121
  return null;
122
122
  }
@@ -184,7 +184,7 @@ function mergeMetadata(sourceMap, sourceInformation, baseSourceMapPath, metadata
184
184
  }
185
185
  }
186
186
  else {
187
- result[metadataKey] = value;
187
+ result[metadataKey][key] = value[key];
188
188
  if (sourceMap) {
189
189
  sourceMap[`${baseSourceMapPath}.${metadataKey}`] =
190
190
  sourceInformation;
@@ -11,7 +11,8 @@ export type TaskWithCachedResult = {
11
11
  task: Task;
12
12
  cachedResult: CachedResult;
13
13
  };
14
- export declare function getCache(nxJson: NxJsonConfiguration, options: DefaultTasksRunnerOptions): DbCache | Cache;
14
+ export declare function dbCacheEnabled(nxJson?: NxJsonConfiguration): boolean;
15
+ export declare function getCache(options: DefaultTasksRunnerOptions): DbCache | Cache;
15
16
  export declare class DbCache {
16
17
  private readonly options;
17
18
  private cache;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Cache = exports.DbCache = void 0;
4
+ exports.dbCacheEnabled = dbCacheEnabled;
4
5
  exports.getCache = getCache;
5
6
  const workspace_root_1 = require("../utils/workspace-root");
6
7
  const path_1 = require("path");
@@ -19,14 +20,17 @@ const update_manager_1 = require("../nx-cloud/update-manager");
19
20
  const get_cloud_options_1 = require("../nx-cloud/utilities/get-cloud-options");
20
21
  const is_ci_1 = require("../utils/is-ci");
21
22
  const output_1 = require("../utils/output");
22
- function getCache(nxJson, options) {
23
- return process.env.NX_DISABLE_DB !== 'true' &&
24
- (nxJson.enableDbCache === true || process.env.NX_DB_CACHE === 'true')
23
+ function dbCacheEnabled(nxJson = (0, nx_json_1.readNxJson)()) {
24
+ return (process.env.NX_DISABLE_DB !== 'true' &&
25
+ (nxJson.enableDbCache === true || process.env.NX_DB_CACHE === 'true'));
26
+ }
27
+ // Do not change the order of these arguments as this function is used by nx cloud
28
+ function getCache(options) {
29
+ const nxJson = (0, nx_json_1.readNxJson)();
30
+ return dbCacheEnabled(nxJson)
25
31
  ? new DbCache({
26
32
  // Remove this in Nx 21
27
- nxCloudRemoteCache: (0, nx_cloud_utils_1.isNxCloudUsed)((0, nx_json_1.readNxJson)())
28
- ? options.remoteCache
29
- : null,
33
+ nxCloudRemoteCache: (0, nx_cloud_utils_1.isNxCloudUsed)(nxJson) ? options.remoteCache : null,
30
34
  })
31
35
  : new Cache(options);
32
36
  }
@@ -18,9 +18,11 @@ export declare class ProcessTasks {
18
18
  private processTasksForMultipleProjects;
19
19
  private processTasksForSingleProject;
20
20
  private processTasksForDependencies;
21
+ private createDummyTask;
21
22
  createTask(id: string, project: ProjectGraphProjectNode, target: string, resolvedConfiguration: string | undefined, overrides: Object): Task;
22
23
  resolveConfiguration(project: ProjectGraphProjectNode, target: string, configuration: string | undefined): string;
23
24
  getId(project: string, target: string, configuration: string | undefined): string;
25
+ private filterDummyTasks;
24
26
  }
25
27
  export declare function createTaskGraph(projectGraph: ProjectGraph, extraTargetDependencies: TargetDependencies, projectNames: string[], targets: string[], configuration: string | undefined, overrides: Object, excludeTaskDependencies?: boolean): TaskGraph;
26
28
  export declare function mapTargetDefaultsToDependencies(defaults: TargetDefaults | undefined): TargetDependencies;
@@ -6,6 +6,7 @@ exports.mapTargetDefaultsToDependencies = mapTargetDefaultsToDependencies;
6
6
  const utils_1 = require("./utils");
7
7
  const project_graph_utils_1 = require("../utils/project-graph-utils");
8
8
  const output_1 = require("../utils/output");
9
+ const DUMMY_TASK_TARGET = '__nx_dummy_task__';
9
10
  class ProcessTasks {
10
11
  constructor(extraTargetDependencies, projectGraph) {
11
12
  this.extraTargetDependencies = extraTargetDependencies;
@@ -52,10 +53,11 @@ class ProcessTasks {
52
53
  this.dependencies[d] = this.dependencies[d].filter((dd) => !!initialTasks[dd]);
53
54
  }
54
55
  }
55
- for (const projectName of Object.keys(this.dependencies)) {
56
- if (this.dependencies[projectName].length > 1) {
57
- this.dependencies[projectName] = [
58
- ...new Set(this.dependencies[projectName]).values(),
56
+ this.filterDummyTasks();
57
+ for (const taskId of Object.keys(this.dependencies)) {
58
+ if (this.dependencies[taskId].length > 0) {
59
+ this.dependencies[taskId] = [
60
+ ...new Set(this.dependencies[taskId].filter((d) => d !== taskId)).values(),
59
61
  ];
60
62
  }
61
63
  }
@@ -113,6 +115,9 @@ class ProcessTasks {
113
115
  }
114
116
  }
115
117
  processTasksForDependencies(projectUsedToDeriveDependencies, dependencyConfig, configuration, task, taskOverrides, overrides) {
118
+ if (!this.projectGraph.dependencies.hasOwnProperty(projectUsedToDeriveDependencies)) {
119
+ return;
120
+ }
116
121
  for (const dep of this.projectGraph.dependencies[projectUsedToDeriveDependencies]) {
117
122
  const depProject = this.projectGraph.nodes[dep.target];
118
123
  // this is to handle external dependencies
@@ -132,10 +137,20 @@ class ProcessTasks {
132
137
  }
133
138
  }
134
139
  else {
135
- this.processTask(task, depProject.name, configuration, overrides);
140
+ const dummyId = this.getId(depProject.name, DUMMY_TASK_TARGET, undefined);
141
+ this.dependencies[task.id].push(dummyId);
142
+ this.dependencies[dummyId] = [];
143
+ const noopTask = this.createDummyTask(dummyId, task);
144
+ this.processTask(noopTask, depProject.name, configuration, overrides);
136
145
  }
137
146
  }
138
147
  }
148
+ createDummyTask(id, task) {
149
+ return {
150
+ ...task,
151
+ id,
152
+ };
153
+ }
139
154
  createTask(id, project, target, resolvedConfiguration, overrides) {
140
155
  if (!project.data.targets[target]) {
141
156
  throw new Error(`Cannot find configuration for task ${project.name}:${target}`);
@@ -173,6 +188,25 @@ class ProcessTasks {
173
188
  }
174
189
  return id;
175
190
  }
191
+ filterDummyTasks() {
192
+ for (const [key, deps] of Object.entries(this.dependencies)) {
193
+ const normalizedDeps = [];
194
+ for (const dep of deps) {
195
+ if (dep.endsWith(DUMMY_TASK_TARGET)) {
196
+ normalizedDeps.push(...this.dependencies[dep].filter((d) => !d.endsWith(DUMMY_TASK_TARGET)));
197
+ }
198
+ else {
199
+ normalizedDeps.push(dep);
200
+ }
201
+ }
202
+ this.dependencies[key] = normalizedDeps;
203
+ }
204
+ for (const key of Object.keys(this.dependencies)) {
205
+ if (key.endsWith(DUMMY_TASK_TARGET)) {
206
+ delete this.dependencies[key];
207
+ }
208
+ }
209
+ }
176
210
  }
177
211
  exports.ProcessTasks = ProcessTasks;
178
212
  function createTaskGraph(projectGraph, extraTargetDependencies, projectNames, targets, configuration, overrides, excludeTaskDependencies = false) {
@@ -224,6 +224,11 @@ async function createRunManyDynamicOutputRenderer({ projectNames, tasks, args, o
224
224
  clearRenderInterval();
225
225
  const timeTakenText = (0, pretty_time_1.prettyTime)(process.hrtime(start));
226
226
  moveCursorToStartOfPinnedFooter();
227
+ if (totalTasks === 0) {
228
+ renderPinnedFooter([output_1.output.applyNxPrefix('gray', 'No tasks were run')]);
229
+ resolveRenderIsDonePromise();
230
+ return;
231
+ }
227
232
  if (totalSuccessfulTasks === totalTasks) {
228
233
  const text = `Successfully ran ${(0, formatting_utils_1.formatTargetsAndProjects)(projectNames, targets, tasks)}`;
229
234
  const taskOverridesRows = [];
@@ -23,6 +23,9 @@ class StaticRunManyTerminalOutputLifeCycle {
23
23
  this.allCompletedTasks = new Map();
24
24
  }
25
25
  startCommand() {
26
+ if (this.tasks.length === 0) {
27
+ return;
28
+ }
26
29
  if (this.projectNames.length <= 0) {
27
30
  output_1.output.logSingleLine(`No projects with ${(0, formatting_utils_1.formatTargetsAndProjects)(this.projectNames, this.args.targets, this.tasks)} were run`);
28
31
  return;
@@ -45,6 +48,10 @@ class StaticRunManyTerminalOutputLifeCycle {
45
48
  }
46
49
  endCommand() {
47
50
  output_1.output.addNewline();
51
+ if (this.tasks.length === 0) {
52
+ output_1.output.logSingleLine(`No tasks were run`);
53
+ return;
54
+ }
48
55
  if (this.failedTasks.length === 0) {
49
56
  output_1.output.addVerticalSeparatorWithoutNewLines('green');
50
57
  const bodyLines = this.cachedTasks.length > 0
@@ -363,12 +363,14 @@ function setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles) {
363
363
  }
364
364
  async function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, }) {
365
365
  setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles);
366
+ // this needs to be done before we start to run the tasks
367
+ const taskDetails = (0, hash_task_1.getTaskDetails)();
366
368
  const { tasksRunner, runnerOptions } = getRunner(nxArgs, nxJson);
367
369
  let hasher = (0, create_task_hasher_1.createTaskHasher)(projectGraph, nxJson, runnerOptions);
368
370
  // this is used for two reasons: to fetch all remote cache hits AND
369
371
  // to submit everything that is known in advance to Nx Cloud to run in
370
372
  // a distributed fashion
371
- await (0, hash_task_1.hashTasksThatDoNotDependOnOutputsOfOtherTasks)(hasher, projectGraph, taskGraph, nxJson);
373
+ await (0, hash_task_1.hashTasksThatDoNotDependOnOutputsOfOtherTasks)(hasher, projectGraph, taskGraph, nxJson, taskDetails);
372
374
  const taskResultsLifecycle = new task_results_life_cycle_1.TaskResultsLifeCycle();
373
375
  const compositedLifeCycle = new life_cycle_1.CompositeLifeCycle([
374
376
  ...constructLifeCycles(lifeCycle),
@@ -15,6 +15,7 @@ export declare class TaskOrchestrator {
15
15
  private readonly bail;
16
16
  private readonly daemon;
17
17
  private readonly outputStyle;
18
+ private taskDetails;
18
19
  private cache;
19
20
  private forkedProcessTaskRunner;
20
21
  private tasksSchedule;
@@ -27,7 +27,8 @@ class TaskOrchestrator {
27
27
  this.bail = bail;
28
28
  this.daemon = daemon;
29
29
  this.outputStyle = outputStyle;
30
- this.cache = (0, cache_1.getCache)(this.nxJson, this.options);
30
+ this.taskDetails = (0, hash_task_1.getTaskDetails)();
31
+ this.cache = (0, cache_1.getCache)(this.options);
31
32
  this.forkedProcessTaskRunner = new forked_process_task_runner_1.ForkedProcessTaskRunner(this.options);
32
33
  this.tasksSchedule = new tasks_schedule_1.TasksSchedule(this.projectGraph, this.taskGraph, this.options);
33
34
  // region internal state
@@ -93,7 +94,7 @@ class TaskOrchestrator {
93
94
  const task = this.taskGraph.tasks[taskId];
94
95
  const taskSpecificEnv = (0, task_env_1.getTaskSpecificEnv)(task);
95
96
  if (!task.hash) {
96
- await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, taskSpecificEnv);
97
+ await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, taskSpecificEnv, this.taskDetails);
97
98
  }
98
99
  await this.options.lifeCycle.scheduleTask(task);
99
100
  return taskSpecificEnv;
@@ -101,7 +102,7 @@ class TaskOrchestrator {
101
102
  async processScheduledBatch(batch) {
102
103
  await Promise.all(Object.values(batch.taskGraph.tasks).map(async (task) => {
103
104
  if (!task.hash) {
104
- await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, this.batchEnv);
105
+ await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, this.batchEnv, this.taskDetails);
105
106
  }
106
107
  await this.options.lifeCycle.scheduleTask(task);
107
108
  }));
@@ -321,6 +322,9 @@ class TaskOrchestrator {
321
322
  };
322
323
  }
323
324
  catch (e) {
325
+ if (process.env.NX_VERBOSE_LOGGING === 'true') {
326
+ console.error(e);
327
+ }
324
328
  return {
325
329
  code: 1,
326
330
  };
@@ -19,6 +19,7 @@ export declare class TasksSchedule {
19
19
  private completedTasks;
20
20
  private scheduleRequestsExecutionChain;
21
21
  private estimatedTaskTimings;
22
+ private projectDependencies;
22
23
  constructor(projectGraph: ProjectGraph, taskGraph: TaskGraph, options: DefaultTasksRunnerOptions);
23
24
  init(): Promise<void>;
24
25
  scheduleNextTasks(): Promise<void>;
@@ -20,12 +20,16 @@ class TasksSchedule {
20
20
  this.completedTasks = new Set();
21
21
  this.scheduleRequestsExecutionChain = Promise.resolve();
22
22
  this.estimatedTaskTimings = {};
23
+ this.projectDependencies = {};
23
24
  }
24
25
  async init() {
25
26
  if (this.taskHistory) {
26
27
  this.estimatedTaskTimings =
27
28
  await this.taskHistory.getEstimatedTaskTimings(Object.values(this.taskGraph.tasks).map((t) => t.target));
28
29
  }
30
+ for (const project of Object.values(this.taskGraph.tasks).map((t) => t.target.project)) {
31
+ this.projectDependencies[project] ??= (0, project_graph_utils_1.findAllProjectNodeDependencies)(project, this.reverseProjectGraph).length;
32
+ }
29
33
  }
30
34
  async scheduleNextTasks() {
31
35
  this.scheduleRequestsExecutionChain =
@@ -90,8 +94,8 @@ class TasksSchedule {
90
94
  // Most likely tasks with no dependencies such as test
91
95
  const project1 = this.taskGraph.tasks[taskId1].target.project;
92
96
  const project2 = this.taskGraph.tasks[taskId2].target.project;
93
- const project1NodeDependencies = (0, project_graph_utils_1.findAllProjectNodeDependencies)(project1, this.reverseProjectGraph).length;
94
- const project2NodeDependencies = (0, project_graph_utils_1.findAllProjectNodeDependencies)(project2, this.reverseProjectGraph).length;
97
+ const project1NodeDependencies = this.projectDependencies[project1];
98
+ const project2NodeDependencies = this.projectDependencies[project2];
95
99
  const dependenciesDiff = project2NodeDependencies - project1NodeDependencies;
96
100
  if (dependenciesDiff !== 0) {
97
101
  return dependenciesDiff;
@@ -8,7 +8,7 @@ exports.commitChanges = commitChanges;
8
8
  exports.getLatestCommitSha = getLatestCommitSha;
9
9
  const child_process_1 = require("child_process");
10
10
  const path_1 = require("path");
11
- const devkit_exports_1 = require("../devkit-exports");
11
+ const logger_1 = require("./logger");
12
12
  function execAsync(command, execOptions) {
13
13
  return new Promise((res, rej) => {
14
14
  (0, child_process_1.exec)(command, execOptions, (err, stdout, stderr) => {
@@ -236,7 +236,7 @@ function commitChanges(commitMessage, directory) {
236
236
  // We don't want to throw during create-nx-workspace
237
237
  // because maybe there was an error when setting up git
238
238
  // initially.
239
- devkit_exports_1.logger.verbose(`Git may not be set up correctly for this new workspace.
239
+ logger_1.logger.verbose(`Git may not be set up correctly for this new workspace.
240
240
  ${err}`);
241
241
  }
242
242
  else {
@@ -47,7 +47,7 @@ function listAlsoAvailableCorePlugins(installedPlugins) {
47
47
  }
48
48
  }
49
49
  function listPowerpackPlugins() {
50
- const powerpackLink = 'https://nx.dev/plugin-registry';
50
+ const powerpackLink = 'https://nx.dev/plugin-registry#powerpack';
51
51
  output_1.output.log({
52
52
  title: `Available Powerpack Plugins: ${powerpackLink}`,
53
53
  });