nx 19.6.0-beta.0 → 19.6.0-beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/package.json +12 -12
  2. package/release/changelog-renderer/index.js +16 -1
  3. package/src/command-line/init/init-v2.js +1 -1
  4. package/src/command-line/release/changelog.js +80 -42
  5. package/src/command-line/release/config/version-plans.d.ts +5 -0
  6. package/src/command-line/release/config/version-plans.js +9 -5
  7. package/src/command-line/release/plan.js +25 -45
  8. package/src/command-line/release/utils/generate-version-plan-content.js +2 -3
  9. package/src/command-line/release/version.d.ts +5 -0
  10. package/src/core/graph/main.js +1 -1
  11. package/src/core/graph/styles.css +1 -1
  12. package/src/daemon/cache.d.ts +1 -0
  13. package/src/daemon/cache.js +25 -18
  14. package/src/daemon/client/client.js +9 -1
  15. package/src/daemon/message-types/force-shutdown.d.ts +5 -0
  16. package/src/daemon/message-types/force-shutdown.js +11 -0
  17. package/src/daemon/server/handle-force-shutdown.d.ts +5 -0
  18. package/src/daemon/server/handle-force-shutdown.js +18 -0
  19. package/src/daemon/server/handle-request-shutdown.js +2 -0
  20. package/src/daemon/server/server.d.ts +1 -0
  21. package/src/daemon/server/server.js +14 -0
  22. package/src/daemon/server/shutdown-utils.d.ts +2 -1
  23. package/src/daemon/server/shutdown-utils.js +11 -4
  24. package/src/daemon/server/watcher.js +3 -0
  25. package/src/native/nx.wasm32-wasi.wasm +0 -0
  26. package/src/nx-cloud/models/onboarding-status.d.ts +1 -0
  27. package/src/nx-cloud/models/onboarding-status.js +2 -0
  28. package/src/nx-cloud/utilities/is-workspace-claimed.d.ts +1 -0
  29. package/src/nx-cloud/utilities/is-workspace-claimed.js +24 -0
  30. package/src/nx-cloud/utilities/onboarding.d.ts +5 -0
  31. package/src/nx-cloud/utilities/onboarding.js +28 -0
  32. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +7 -2
  33. package/src/project-graph/plugins/internal-api.js +16 -5
  34. package/src/project-graph/plugins/isolation/messaging.d.ts +5 -1
  35. package/src/project-graph/plugins/isolation/messaging.js +1 -0
  36. package/src/project-graph/plugins/isolation/plugin-pool.js +4 -6
  37. package/src/project-graph/plugins/isolation/plugin-worker.js +15 -0
  38. package/src/project-graph/utils/project-configuration-utils.js +5 -2
  39. package/src/utils/package-manager.js +12 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "19.6.0-beta.0",
3
+ "version": "19.6.0-beta.1",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -71,7 +71,7 @@
71
71
  "yargs-parser": "21.1.1",
72
72
  "node-machine-id": "1.1.12",
73
73
  "ora": "5.3.0",
74
- "@nrwl/tao": "19.6.0-beta.0"
74
+ "@nrwl/tao": "19.6.0-beta.1"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "@swc-node/register": "^1.8.0",
@@ -86,16 +86,16 @@
86
86
  }
87
87
  },
88
88
  "optionalDependencies": {
89
- "@nx/nx-darwin-x64": "19.6.0-beta.0",
90
- "@nx/nx-darwin-arm64": "19.6.0-beta.0",
91
- "@nx/nx-linux-x64-gnu": "19.6.0-beta.0",
92
- "@nx/nx-linux-x64-musl": "19.6.0-beta.0",
93
- "@nx/nx-win32-x64-msvc": "19.6.0-beta.0",
94
- "@nx/nx-linux-arm64-gnu": "19.6.0-beta.0",
95
- "@nx/nx-linux-arm64-musl": "19.6.0-beta.0",
96
- "@nx/nx-linux-arm-gnueabihf": "19.6.0-beta.0",
97
- "@nx/nx-win32-arm64-msvc": "19.6.0-beta.0",
98
- "@nx/nx-freebsd-x64": "19.6.0-beta.0"
89
+ "@nx/nx-darwin-x64": "19.6.0-beta.1",
90
+ "@nx/nx-darwin-arm64": "19.6.0-beta.1",
91
+ "@nx/nx-linux-x64-gnu": "19.6.0-beta.1",
92
+ "@nx/nx-linux-x64-musl": "19.6.0-beta.1",
93
+ "@nx/nx-win32-x64-msvc": "19.6.0-beta.1",
94
+ "@nx/nx-linux-arm64-gnu": "19.6.0-beta.1",
95
+ "@nx/nx-linux-arm64-musl": "19.6.0-beta.1",
96
+ "@nx/nx-linux-arm-gnueabihf": "19.6.0-beta.1",
97
+ "@nx/nx-win32-arm64-msvc": "19.6.0-beta.1",
98
+ "@nx/nx-freebsd-x64": "19.6.0-beta.1"
99
99
  },
100
100
  "nx-migrations": {
101
101
  "migrations": "./migrations.json",
@@ -216,13 +216,28 @@ function groupBy(items, key) {
216
216
  return groups;
217
217
  }
218
218
  function formatChange(change, changelogRenderOptions, repoSlug) {
219
+ let description = change.description;
220
+ let extraLines = [];
221
+ let extraLinesStr = '';
222
+ if (description.includes('\n')) {
223
+ [description, ...extraLines] = description.split('\n');
224
+ // Align the extra lines with the start of the description for better readability
225
+ const indentation = ' ';
226
+ extraLinesStr = extraLines
227
+ .filter((l) => l.trim().length > 0)
228
+ .map((l) => `${indentation}${l}`)
229
+ .join('\n');
230
+ }
219
231
  let changeLine = '- ' +
220
232
  (change.isBreaking ? '⚠️ ' : '') +
221
233
  (change.scope ? `**${change.scope.trim()}:** ` : '') +
222
- change.description;
234
+ description;
223
235
  if (repoSlug && changelogRenderOptions.commitReferences) {
224
236
  changeLine += (0, github_1.formatReferences)(change.githubReferences, repoSlug);
225
237
  }
238
+ if (extraLinesStr) {
239
+ changeLine += '\n\n' + extraLinesStr;
240
+ }
226
241
  return changeLine;
227
242
  }
228
243
  /**
@@ -33,7 +33,7 @@ async function initHandler(options) {
33
33
  (0, add_nx_scripts_1.generateDotNxSetup)(version);
34
34
  const { plugins } = await detectPlugins();
35
35
  plugins.forEach((plugin) => {
36
- (0, child_process_2.execSync)(`./nx add ${plugin}`, {
36
+ (0, child_process_1.runNxSync)(`add ${plugin}`, {
37
37
  stdio: 'inherit',
38
38
  });
39
39
  });
@@ -146,23 +146,34 @@ function createAPI(overrideReleaseConfig) {
146
146
  const releaseGroup = releaseGroups[0];
147
147
  if (releaseGroup.projectsRelationship === 'fixed') {
148
148
  const versionPlans = releaseGroup.versionPlans;
149
- workspaceChangelogChanges = filterHiddenChanges(versionPlans
150
- .map((vp) => {
151
- const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
152
- // only properly formatted conventional commits messages will be included in the changelog
153
- if (!parsedMessage) {
154
- return null;
155
- }
156
- return {
157
- type: parsedMessage.type,
158
- scope: parsedMessage.scope,
159
- description: parsedMessage.description,
160
- body: '',
161
- isBreaking: parsedMessage.breaking,
162
- githubReferences: [],
163
- };
149
+ workspaceChangelogChanges = versionPlans
150
+ .flatMap((vp) => {
151
+ const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
152
+ const changes = !vp.triggeredByProjects
153
+ ? {
154
+ type: releaseType.type,
155
+ scope: '',
156
+ description: vp.message,
157
+ body: '',
158
+ isBreaking: releaseType.isBreaking,
159
+ githubReferences: [],
160
+ affectedProjects: '*',
161
+ }
162
+ : vp.triggeredByProjects.map((project) => {
163
+ return {
164
+ type: releaseType.type,
165
+ scope: project,
166
+ description: vp.message,
167
+ body: '',
168
+ // TODO: what about github references?
169
+ isBreaking: releaseType.isBreaking,
170
+ githubReferences: [],
171
+ affectedProjects: [project],
172
+ };
173
+ });
174
+ return changes;
164
175
  })
165
- .filter(Boolean), nxReleaseConfig.conventionalCommits);
176
+ .filter(Boolean);
166
177
  }
167
178
  }
168
179
  }
@@ -286,24 +297,25 @@ function createAPI(overrideReleaseConfig) {
286
297
  // TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
287
298
  let commits;
288
299
  if (releaseGroup.versionPlans) {
289
- changes = filterHiddenChanges(releaseGroup.versionPlans
300
+ changes = releaseGroup.versionPlans
290
301
  .map((vp) => {
291
- const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
292
- // only properly formatted conventional commits messages will be included in the changelog
293
- if (!parsedMessage) {
302
+ const bumpForProject = vp.projectVersionBumps[project.name];
303
+ if (!bumpForProject) {
294
304
  return null;
295
305
  }
306
+ const releaseType = versionPlanSemverReleaseTypeToChangelogType(bumpForProject);
296
307
  return {
297
- type: parsedMessage.type,
298
- scope: parsedMessage.scope,
299
- description: parsedMessage.description,
308
+ type: releaseType.type,
309
+ scope: project.name,
310
+ description: vp.message,
300
311
  body: '',
301
- isBreaking: parsedMessage.breaking,
312
+ isBreaking: releaseType.isBreaking,
302
313
  affectedProjects: Object.keys(vp.projectVersionBumps),
314
+ // TODO: can we include github references when using version plans?
303
315
  githubReferences: [],
304
316
  };
305
317
  })
306
- .filter(Boolean), nxReleaseConfig.conventionalCommits);
318
+ .filter(Boolean);
307
319
  }
308
320
  else {
309
321
  let fromRef = args.from ||
@@ -385,24 +397,34 @@ function createAPI(overrideReleaseConfig) {
385
397
  // TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
386
398
  let commits = [];
387
399
  if (releaseGroup.versionPlans) {
388
- changes = filterHiddenChanges(releaseGroup.versionPlans
389
- .map((vp) => {
390
- const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
391
- // only properly formatted conventional commits messages will be included in the changelog
392
- if (!parsedMessage) {
393
- return null;
394
- }
395
- return {
396
- type: parsedMessage.type,
397
- scope: parsedMessage.scope,
398
- description: parsedMessage.description,
399
- body: '',
400
- isBreaking: parsedMessage.breaking,
401
- githubReferences: [],
402
- affectedProjects: '*',
403
- };
400
+ changes = releaseGroup.versionPlans
401
+ .flatMap((vp) => {
402
+ const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
403
+ const changes = !vp.triggeredByProjects
404
+ ? {
405
+ type: releaseType.type,
406
+ scope: '',
407
+ description: vp.message,
408
+ body: '',
409
+ isBreaking: releaseType.isBreaking,
410
+ githubReferences: [],
411
+ affectedProjects: '*',
412
+ }
413
+ : vp.triggeredByProjects.map((project) => {
414
+ return {
415
+ type: releaseType.type,
416
+ scope: project,
417
+ description: vp.message,
418
+ body: '',
419
+ // TODO: what about github references?
420
+ isBreaking: releaseType.isBreaking,
421
+ githubReferences: [],
422
+ affectedProjects: [project],
423
+ };
424
+ });
425
+ return changes;
404
426
  })
405
- .filter(Boolean), nxReleaseConfig.conventionalCommits);
427
+ .filter(Boolean);
406
428
  }
407
429
  else {
408
430
  let fromRef = args.from ||
@@ -914,3 +936,19 @@ function createFileToProjectMap(projectFileMap) {
914
936
  }
915
937
  return fileToProjectMap;
916
938
  }
939
+ function versionPlanSemverReleaseTypeToChangelogType(bump) {
940
+ switch (bump) {
941
+ case 'premajor':
942
+ case 'major':
943
+ return { type: 'feat', isBreaking: true };
944
+ case 'preminor':
945
+ case 'minor':
946
+ return { type: 'feat', isBreaking: false };
947
+ case 'prerelease':
948
+ case 'prepatch':
949
+ case 'patch':
950
+ return { type: 'fix', isBreaking: false };
951
+ default:
952
+ throw new Error(`Invalid semver bump type: ${bump}`);
953
+ }
954
+ }
@@ -15,6 +15,11 @@ export interface VersionPlan extends VersionPlanFile {
15
15
  }
16
16
  export interface GroupVersionPlan extends VersionPlan {
17
17
  groupVersionBump: ReleaseType;
18
+ /**
19
+ * Will not be set if the group name was the trigger, otherwise will be a list of
20
+ * all the individual project names explicitly found in the version plan file.
21
+ */
22
+ triggeredByProjects?: string[];
18
23
  }
19
24
  export interface ProjectsVersionPlan extends VersionPlan {
20
25
  projectVersionBumps: Record<string, ReleaseType>;
@@ -29,7 +29,7 @@ async function readRawVersionPlans() {
29
29
  relativePath: (0, path_1.join)(versionPlansDirectory, versionPlanFile),
30
30
  fileName: versionPlanFile,
31
31
  content: parsedContent.attributes,
32
- message: getSingleLineMessage(parsedContent.body),
32
+ message: parsedContent.body,
33
33
  createdOnMs: versionPlanStats.birthtimeMs,
34
34
  });
35
35
  }
@@ -39,6 +39,9 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
39
39
  const groupsByName = releaseGroups.reduce((acc, group) => acc.set(group.name, group), new Map());
40
40
  const isDefaultGroup = isDefault(releaseGroups);
41
41
  for (const rawVersionPlan of rawVersionPlans) {
42
+ if (!rawVersionPlan.message) {
43
+ throw new Error(`Please add a changelog message to version plan: '${rawVersionPlan.fileName}'`);
44
+ }
42
45
  for (const [key, value] of Object.entries(rawVersionPlan.content)) {
43
46
  if (groupsByName.has(key)) {
44
47
  const group = groupsByName.get(key);
@@ -143,6 +146,9 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
143
146
  throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' that conflicts with another project's version bump in the same release group '${groupForProject.name}'. When the group is in fixed versioning mode, all projects' version bumps within the same group must match.`);
144
147
  }
145
148
  }
149
+ else {
150
+ existingPlan.triggeredByProjects.push(key);
151
+ }
146
152
  }
147
153
  else {
148
154
  groupForProject.versionPlans.push({
@@ -152,7 +158,9 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
152
158
  createdOnMs: rawVersionPlan.createdOnMs,
153
159
  message: rawVersionPlan.message,
154
160
  // This is a fixed group, so the version bump is for the group, even if a project within it was specified
161
+ // but we track the projects that triggered the version bump so that we can accurately produce changelog entries.
155
162
  groupVersionBump: value,
163
+ triggeredByProjects: [key],
156
164
  });
157
165
  }
158
166
  }
@@ -177,7 +185,3 @@ function getVersionPlansAbsolutePath() {
177
185
  function isReleaseType(value) {
178
186
  return semver_1.RELEASE_TYPES.includes(value);
179
187
  }
180
- // changelog messages may only be a single line long, so ignore anything else
181
- function getSingleLineMessage(message) {
182
- return message.trim().split('\n')[0];
183
- }
@@ -4,21 +4,22 @@ exports.releasePlanCLIHandler = void 0;
4
4
  exports.createAPI = createAPI;
5
5
  const enquirer_1 = require("enquirer");
6
6
  const fs_extra_1 = require("fs-extra");
7
- const path_1 = require("path");
7
+ const node_path_1 = require("node:path");
8
8
  const semver_1 = require("semver");
9
+ const tmp_1 = require("tmp");
9
10
  const nx_json_1 = require("../../config/nx-json");
10
11
  const file_map_utils_1 = require("../../project-graph/file-map-utils");
11
12
  const project_graph_1 = require("../../project-graph/project-graph");
12
13
  const output_1 = require("../../utils/output");
13
14
  const params_1 = require("../../utils/params");
14
15
  const config_1 = require("./config/config");
16
+ const deep_merge_json_1 = require("./config/deep-merge-json");
15
17
  const filter_release_groups_1 = require("./config/filter-release-groups");
16
18
  const version_plans_1 = require("./config/version-plans");
17
19
  const generate_version_plan_content_1 = require("./utils/generate-version-plan-content");
18
- const git_1 = require("./utils/git");
20
+ const launch_editor_1 = require("./utils/launch-editor");
19
21
  const print_changes_1 = require("./utils/print-changes");
20
22
  const print_config_1 = require("./utils/print-config");
21
- const deep_merge_json_1 = require("./config/deep-merge-json");
22
23
  const releasePlanCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => createAPI({})(args));
23
24
  exports.releasePlanCLIHandler = releasePlanCLIHandler;
24
25
  function createAPI(overrideReleaseConfig) {
@@ -53,25 +54,6 @@ function createAPI(overrideReleaseConfig) {
53
54
  versionPlanBumps[projectOrGroup] = version;
54
55
  }
55
56
  };
56
- if (args.message) {
57
- const message = (0, git_1.parseConventionalCommitsMessage)(args.message);
58
- if (!message) {
59
- output_1.output.error({
60
- title: 'Changelog message is not in conventional commits format.',
61
- bodyLines: [
62
- 'Please ensure your message is in the form of:',
63
- ' type(optional scope): description',
64
- '',
65
- 'For example:',
66
- ' feat(pkg-b): add new feature',
67
- ' fix(pkg-a): correct a bug',
68
- ' chore: update build process',
69
- ' fix(core)!: breaking change in core package',
70
- ],
71
- });
72
- process.exit(1);
73
- }
74
- }
75
57
  if (releaseGroups[0].name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP) {
76
58
  const group = releaseGroups[0];
77
59
  if (group.projectsRelationship === 'independent') {
@@ -106,9 +88,10 @@ function createAPI(overrideReleaseConfig) {
106
88
  });
107
89
  return 0;
108
90
  }
109
- const versionPlanMessage = args.message || (await promptForMessage());
91
+ const versionPlanName = `version-plan-${new Date().getTime()}`;
92
+ const versionPlanMessage = args.message || (await promptForMessage(versionPlanName));
110
93
  const versionPlanFileContent = (0, generate_version_plan_content_1.generateVersionPlanContent)(versionPlanBumps, versionPlanMessage);
111
- const versionPlanFileName = `version-plan-${new Date().getTime()}.md`;
94
+ const versionPlanFileName = `${versionPlanName}.md`;
112
95
  if (args.dryRun) {
113
96
  output_1.output.logSingleLine(`Would create version plan file "${versionPlanFileName}", but --dry-run was set.`);
114
97
  (0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
@@ -118,7 +101,7 @@ function createAPI(overrideReleaseConfig) {
118
101
  (0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
119
102
  const versionPlansAbsolutePath = (0, version_plans_1.getVersionPlansAbsolutePath)();
120
103
  await (0, fs_extra_1.ensureDir)(versionPlansAbsolutePath);
121
- await (0, fs_extra_1.writeFile)((0, path_1.join)(versionPlansAbsolutePath, versionPlanFileName), versionPlanFileContent);
104
+ await (0, fs_extra_1.writeFile)((0, node_path_1.join)(versionPlansAbsolutePath, versionPlanFileName), versionPlanFileContent);
122
105
  }
123
106
  return 0;
124
107
  };
@@ -142,41 +125,38 @@ async function promptForVersion(message) {
142
125
  process.exit(0);
143
126
  }
144
127
  }
145
- async function promptForMessage() {
128
+ async function promptForMessage(versionPlanName) {
146
129
  let message;
147
130
  do {
148
- message = await _promptForMessage();
131
+ message = await _promptForMessage(versionPlanName);
149
132
  } while (!message);
150
133
  return message;
151
134
  }
152
- // TODO: support non-conventional commits messages (will require significant changelog renderer changes)
153
- async function _promptForMessage() {
135
+ async function _promptForMessage(versionPlanName) {
154
136
  try {
155
137
  const reply = await (0, enquirer_1.prompt)([
156
138
  {
157
139
  name: 'message',
158
- message: 'What changelog message would you like associated with this change?',
140
+ message: 'What changelog message would you like associated with this change? (Leave blank to open an external editor for multi-line messages/easier editing)',
159
141
  type: 'input',
160
142
  },
161
143
  ]);
162
- const conventionalCommitsMessage = (0, git_1.parseConventionalCommitsMessage)(reply.message);
163
- if (!conventionalCommitsMessage) {
144
+ let message = reply.message.trim();
145
+ if (!message.length) {
146
+ const tmpDir = (0, tmp_1.dirSync)().name;
147
+ const messageFilePath = (0, node_path_1.join)(tmpDir, `DRAFT_MESSAGE__${versionPlanName}.md`);
148
+ (0, fs_extra_1.writeFileSync)(messageFilePath, '');
149
+ await (0, launch_editor_1.launchEditor)(messageFilePath);
150
+ message = (0, fs_extra_1.readFileSync)(messageFilePath, 'utf-8');
151
+ }
152
+ message = message.trim();
153
+ if (!message) {
164
154
  output_1.output.warn({
165
- title: 'Changelog message is not in conventional commits format.',
166
- bodyLines: [
167
- 'Please ensure your message is in the form of:',
168
- ' type(optional scope): description',
169
- '',
170
- 'For example:',
171
- ' feat(pkg-b): add new feature',
172
- ' fix(pkg-a): correct a bug',
173
- ' chore: update build process',
174
- ' fix(core)!: breaking change in core package',
175
- ],
155
+ title: 'A changelog message is required in order to create the version plan file',
156
+ bodyLines: [],
176
157
  });
177
- return null;
178
158
  }
179
- return reply.message;
159
+ return message;
180
160
  }
181
161
  catch (e) {
182
162
  output_1.output.log({
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateVersionPlanContent = generateVersionPlanContent;
4
4
  function generateVersionPlanContent(bumps, message) {
5
- return `---
5
+ const frontMatter = `---
6
6
  ${Object.entries(bumps)
7
7
  .filter(([_, version]) => version !== 'none')
8
8
  .map(([projectOrGroup, version]) => {
@@ -15,7 +15,6 @@ ${Object.entries(bumps)
15
15
  })
16
16
  .join('\n')}
17
17
  ---
18
-
19
- ${message}
20
18
  `;
19
+ return `${frontMatter}${message ? `\n${message}\n` : ''}`;
21
20
  }
@@ -30,6 +30,11 @@ export interface ReleaseVersionGeneratorSchema {
30
30
  * This is only applicable to independently released projects.
31
31
  */
32
32
  updateDependents?: 'never' | 'auto';
33
+ /**
34
+ * Whether or not to completely omit project logs when that project has no applicable changes. This can be useful for
35
+ * large monorepos which have a large number of projects, especially when only a subset are released together.
36
+ */
37
+ logUnchangedProjects?: boolean;
33
38
  }
34
39
  export interface NxReleaseVersionResult {
35
40
  /**