nx 20.7.1 → 20.8.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.eslintrc.json +3 -1
  2. package/package.json +11 -11
  3. package/release/index.d.ts +1 -1
  4. package/release/index.js +2 -1
  5. package/schemas/nx-schema.json +133 -33
  6. package/src/command-line/release/changelog.js +15 -10
  7. package/src/command-line/release/command-object.d.ts +1 -0
  8. package/src/command-line/release/command-object.js +4 -0
  9. package/src/command-line/release/config/config.d.ts +8 -7
  10. package/src/command-line/release/config/config.js +122 -42
  11. package/src/command-line/release/config/use-legacy-versioning.d.ts +2 -0
  12. package/src/command-line/release/config/use-legacy-versioning.js +9 -0
  13. package/src/command-line/release/index.d.ts +4 -0
  14. package/src/command-line/release/index.js +6 -1
  15. package/src/command-line/release/plan-check.js +6 -3
  16. package/src/command-line/release/plan.js +7 -3
  17. package/src/command-line/release/publish.js +5 -3
  18. package/src/command-line/release/release.js +8 -3
  19. package/src/command-line/release/utils/batch-projects-by-generator-config.js +6 -3
  20. package/src/command-line/release/utils/git.d.ts +2 -1
  21. package/src/command-line/release/utils/git.js +10 -2
  22. package/src/command-line/release/utils/github.js +3 -1
  23. package/src/command-line/release/utils/resolve-semver-specifier.d.ts +2 -1
  24. package/src/command-line/release/utils/resolve-semver-specifier.js +2 -1
  25. package/src/command-line/release/utils/semver.d.ts +8 -0
  26. package/src/command-line/release/utils/semver.js +8 -0
  27. package/src/command-line/release/utils/shared-legacy.d.ts +25 -0
  28. package/src/command-line/release/utils/shared-legacy.js +2 -0
  29. package/src/command-line/release/utils/shared.d.ts +11 -17
  30. package/src/command-line/release/version/derive-specifier-from-conventional-commits.d.ts +7 -0
  31. package/src/command-line/release/version/derive-specifier-from-conventional-commits.js +47 -0
  32. package/src/command-line/release/version/deriver-specifier-from-version-plans.d.ts +8 -0
  33. package/src/command-line/release/version/deriver-specifier-from-version-plans.js +59 -0
  34. package/src/command-line/release/version/project-logger.d.ts +8 -0
  35. package/src/command-line/release/version/project-logger.js +45 -0
  36. package/src/command-line/release/version/release-group-processor.d.ts +251 -0
  37. package/src/command-line/release/version/release-group-processor.js +1040 -0
  38. package/src/command-line/release/version/resolve-current-version.d.ts +32 -0
  39. package/src/command-line/release/version/resolve-current-version.js +241 -0
  40. package/src/command-line/release/version/test-utils.d.ts +95 -0
  41. package/src/command-line/release/version/test-utils.js +416 -0
  42. package/src/command-line/release/version/topological-sort.d.ts +9 -0
  43. package/src/command-line/release/version/topological-sort.js +41 -0
  44. package/src/command-line/release/version/version-actions.d.ts +170 -0
  45. package/src/command-line/release/version/version-actions.js +183 -0
  46. package/src/command-line/release/version-legacy.d.ts +46 -0
  47. package/src/command-line/release/version-legacy.js +453 -0
  48. package/src/command-line/release/version.d.ts +0 -40
  49. package/src/command-line/release/version.js +80 -262
  50. package/src/config/nx-json.d.ts +110 -12
  51. package/src/config/workspace-json-project-json.d.ts +2 -2
  52. package/src/core/graph/main.js +1 -1
  53. package/src/core/graph/styles.css +1 -1
  54. package/src/native/index.d.ts +22 -16
  55. package/src/native/native-bindings.js +1 -0
  56. package/src/native/nx.wasi-browser.js +7 -7
  57. package/src/native/nx.wasm32-wasi.wasm +0 -0
  58. package/src/plugins/js/lock-file/utils/package-json.d.ts +1 -1
  59. package/src/plugins/js/lock-file/utils/package-json.js +2 -1
  60. package/src/plugins/js/lock-file/yarn-parser.js +75 -29
  61. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +10 -1
  62. package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +59 -6
  63. package/src/project-graph/error-types.js +28 -1
  64. package/src/tasks-runner/cache.d.ts +1 -0
  65. package/src/tasks-runner/cache.js +11 -0
  66. package/src/tasks-runner/run-command.js +9 -9
  67. package/src/utils/handle-errors.js +15 -0
@@ -1,36 +1,33 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.releaseVersionCLIHandler = exports.validReleaseVersionPrefixes = exports.deriveNewSemverVersion = void 0;
3
+ exports.releaseVersionCLIHandler = exports.validReleaseVersionPrefixes = void 0;
4
4
  exports.createAPI = createAPI;
5
5
  const chalk = require("chalk");
6
6
  const node_child_process_1 = require("node:child_process");
7
7
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = require("node:path");
9
8
  const nx_json_1 = require("../../config/nx-json");
9
+ const format_changed_files_with_prettier_if_available_1 = require("../../generators/internal-utils/format-changed-files-with-prettier-if-available");
10
10
  const tree_1 = require("../../generators/tree");
11
11
  const file_map_utils_1 = require("../../project-graph/file-map-utils");
12
12
  const project_graph_1 = require("../../project-graph/project-graph");
13
+ const handle_errors_1 = require("../../utils/handle-errors");
13
14
  const output_1 = require("../../utils/output");
14
- const params_1 = require("../../utils/params");
15
15
  const path_1 = require("../../utils/path");
16
16
  const workspace_root_1 = require("../../utils/workspace-root");
17
- const generate_1 = require("../generate/generate");
18
- const generator_utils_1 = require("../generate/generator-utils");
19
17
  const config_1 = require("./config/config");
20
18
  const deep_merge_json_1 = require("./config/deep-merge-json");
21
19
  const filter_release_groups_1 = require("./config/filter-release-groups");
22
20
  const version_plans_1 = require("./config/version-plans");
23
- const batch_projects_by_generator_config_1 = require("./utils/batch-projects-by-generator-config");
24
21
  const git_1 = require("./utils/git");
25
22
  const print_changes_1 = require("./utils/print-changes");
26
23
  const print_config_1 = require("./utils/print-config");
27
24
  const resolve_nx_json_error_message_1 = require("./utils/resolve-nx-json-error-message");
28
25
  const shared_1 = require("./utils/shared");
29
- const handle_errors_1 = require("../../utils/handle-errors");
26
+ const version_legacy_1 = require("./version-legacy");
27
+ const release_group_processor_1 = require("./version/release-group-processor");
28
+ const use_legacy_versioning_1 = require("./config/use-legacy-versioning");
30
29
  const LARGE_BUFFER = 1024 * 1000000;
31
30
  // Reexport some utils for use in plugin release-version generator implementations
32
- var semver_1 = require("./utils/semver");
33
- Object.defineProperty(exports, "deriveNewSemverVersion", { enumerable: true, get: function () { return semver_1.deriveNewSemverVersion; } });
34
31
  exports.validReleaseVersionPrefixes = ['auto', '', '~', '^', '='];
35
32
  const releaseVersionCLIHandler = (args) => (0, handle_errors_1.handleErrors)(args.verbose, () => createAPI({})(args));
36
33
  exports.releaseVersionCLIHandler = releaseVersionCLIHandler;
@@ -42,13 +39,13 @@ function createAPI(overrideReleaseConfig) {
42
39
  */
43
40
  return async function releaseVersion(args) {
44
41
  const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
45
- const { projects } = (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
46
42
  const nxJson = (0, nx_json_1.readNxJson)();
47
43
  const userProvidedReleaseConfig = (0, deep_merge_json_1.deepMergeJson)(nxJson.release ?? {}, overrideReleaseConfig ?? {});
44
+ const USE_LEGACY_VERSIONING = (0, use_legacy_versioning_1.shouldUseLegacyVersioning)(userProvidedReleaseConfig);
48
45
  // Apply default configuration to any optional user configuration
49
46
  const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig);
50
47
  if (configError) {
51
- return await (0, config_1.handleNxReleaseConfigError)(configError);
48
+ return await (0, config_1.handleNxReleaseConfigError)(configError, USE_LEGACY_VERSIONING);
52
49
  }
53
50
  // --print-config exits directly as it is not designed to be combined with any other programmatic operations
54
51
  if (args.printConfig) {
@@ -58,6 +55,10 @@ function createAPI(overrideReleaseConfig) {
58
55
  isDebug: args.printConfig === 'debug',
59
56
  });
60
57
  }
58
+ // TODO(v22): Remove support for the legacy versioning implementation in Nx v22
59
+ if (USE_LEGACY_VERSIONING) {
60
+ return await (0, version_legacy_1.releaseVersionLegacy)(projectGraph, args, nxJson, nxReleaseConfig, userProvidedReleaseConfig);
61
+ }
61
62
  // The nx release top level command will always override these three git args. This is how we can tell
62
63
  // if the top level release command was used or if the user is using the changelog subcommand.
63
64
  // If the user explicitly overrides these args, then it doesn't matter if the top level config is set,
@@ -98,169 +99,71 @@ function createAPI(overrideReleaseConfig) {
98
99
  // default to not delete version plans after versioning as they may be needed for changelog generation
99
100
  args.deleteVersionPlans = false;
100
101
  }
102
+ /**
103
+ * Run any configured top level pre-version command
104
+ */
101
105
  runPreVersionCommand(nxReleaseConfig.version.preVersionCommand, {
102
106
  dryRun: args.dryRun,
103
107
  verbose: args.verbose,
104
108
  });
109
+ /**
110
+ * Run any configured pre-version command for the selected release groups
111
+ */
112
+ for (const releaseGroup of releaseGroups) {
113
+ runPreVersionCommand(releaseGroup.version.groupPreVersionCommand, {
114
+ dryRun: args.dryRun,
115
+ verbose: args.verbose,
116
+ }, releaseGroup);
117
+ }
105
118
  const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
106
- const versionData = {};
107
119
  const commitMessage = args.gitCommitMessage || nxReleaseConfig.version.git.commitMessage;
108
- const generatorCallbacks = [];
109
120
  /**
110
121
  * additionalChangedFiles are files which need to be updated as a side-effect of versioning (such as package manager lock files),
111
122
  * and need to get staged and committed as part of the existing commit, if applicable.
112
123
  */
113
124
  const additionalChangedFiles = new Set();
114
125
  const additionalDeletedFiles = new Set();
115
- if (args.projects?.length) {
116
- /**
117
- * Run versioning for all remaining release groups and filtered projects within them
118
- */
119
- for (const releaseGroup of releaseGroups) {
120
- const releaseGroupName = releaseGroup.name;
121
- const releaseGroupProjectNames = Array.from(releaseGroupToFilteredProjects.get(releaseGroup));
122
- const projectBatches = (0, batch_projects_by_generator_config_1.batchProjectsByGeneratorConfig)(projectGraph, releaseGroup,
123
- // Only batch based on the filtered projects within the release group
124
- releaseGroupProjectNames);
125
- for (const [generatorConfigString, projectNames,] of projectBatches.entries()) {
126
- const [generatorName, generatorOptions] = JSON.parse(generatorConfigString);
127
- // Resolve the generator for the batch and run versioning on the projects within the batch
128
- const generatorData = resolveGeneratorData({
129
- ...extractGeneratorCollectionAndName(`batch "${JSON.stringify(projectNames)}" for release-group "${releaseGroupName}"`, generatorName),
130
- configGeneratorOptions: generatorOptions,
131
- // all project data from the project graph (not to be confused with projectNamesToRunVersionOn)
132
- projects,
133
- });
134
- const generatorCallback = await runVersionOnProjects(projectGraph, nxJson, args, tree, generatorData, args.generatorOptionsOverrides, projectNames, releaseGroup, versionData, nxReleaseConfig.conventionalCommits);
135
- // Capture the callback so that we can run it after flushing the changes to disk
136
- generatorCallbacks.push(async () => {
137
- const result = await generatorCallback(tree, {
138
- dryRun: !!args.dryRun,
139
- verbose: !!args.verbose,
140
- generatorOptions: {
141
- ...generatorOptions,
142
- ...args.generatorOptionsOverrides,
143
- },
144
- });
145
- const { changedFiles, deletedFiles } = parseGeneratorCallbackResult(result);
146
- changedFiles.forEach((f) => additionalChangedFiles.add(f));
147
- deletedFiles.forEach((f) => additionalDeletedFiles.add(f));
148
- });
149
- }
150
- }
151
- // Resolve any git tags as early as possible so that we can hard error in case of any duplicates before reaching the actual git command
152
- const gitTagValues = args.gitTag ?? nxReleaseConfig.version.git.tag
153
- ? (0, shared_1.createGitTagValues)(releaseGroups, releaseGroupToFilteredProjects, versionData)
154
- : [];
155
- (0, shared_1.handleDuplicateGitTags)(gitTagValues);
156
- printAndFlushChanges(tree, !!args.dryRun);
157
- for (const generatorCallback of generatorCallbacks) {
158
- await generatorCallback();
159
- }
160
- const changedFiles = [
161
- ...tree.listChanges().map((f) => f.path),
162
- ...additionalChangedFiles,
163
- ];
164
- // No further actions are necessary in this scenario (e.g. if conventional commits detected no changes)
165
- if (!changedFiles.length) {
166
- return {
167
- // An overall workspace version cannot be relevant when filtering to independent projects
168
- workspaceVersion: undefined,
169
- projectsVersionData: versionData,
170
- };
171
- }
172
- if (args.gitCommit ?? nxReleaseConfig.version.git.commit) {
173
- await (0, shared_1.commitChanges)({
174
- changedFiles,
175
- deletedFiles: Array.from(additionalDeletedFiles),
176
- isDryRun: !!args.dryRun,
177
- isVerbose: !!args.verbose,
178
- gitCommitMessages: (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, commitMessage),
179
- gitCommitArgs: args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs,
180
- });
181
- }
182
- else if (args.stageChanges ??
183
- nxReleaseConfig.version.git.stageChanges) {
184
- output_1.output.logSingleLine(`Staging changed files with git`);
185
- await (0, git_1.gitAdd)({
186
- changedFiles,
187
- dryRun: args.dryRun,
188
- verbose: args.verbose,
189
- });
190
- }
191
- if (args.gitTag ?? nxReleaseConfig.version.git.tag) {
192
- output_1.output.logSingleLine(`Tagging commit with git`);
193
- for (const tag of gitTagValues) {
194
- await (0, git_1.gitTag)({
195
- tag,
196
- message: args.gitTagMessage || nxReleaseConfig.version.git.tagMessage,
197
- additionalArgs: args.gitTagArgs || nxReleaseConfig.version.git.tagArgs,
198
- dryRun: args.dryRun,
199
- verbose: args.verbose,
200
- });
201
- }
202
- }
203
- if (args.gitPush ?? nxReleaseConfig.version.git.push) {
204
- output_1.output.logSingleLine(`Pushing to git remote "${args.gitRemote}"`);
205
- await (0, git_1.gitPush)({
206
- gitRemote: args.gitRemote,
207
- dryRun: args.dryRun,
208
- verbose: args.verbose,
209
- });
126
+ const processor = new release_group_processor_1.ReleaseGroupProcessor(tree, projectGraph, nxReleaseConfig, releaseGroups, releaseGroupToFilteredProjects, {
127
+ dryRun: args.dryRun,
128
+ verbose: args.verbose,
129
+ firstRelease: args.firstRelease,
130
+ preid: args.preid ?? '',
131
+ userGivenSpecifier: args.specifier,
132
+ filters: {
133
+ projects: args.projects,
134
+ groups: args.groups,
135
+ },
136
+ });
137
+ try {
138
+ await processor.init();
139
+ await processor.processGroups();
140
+ // Delete processed version plan files if applicable
141
+ if (args.deleteVersionPlans) {
142
+ processor.deleteProcessedVersionPlanFiles();
210
143
  }
211
- return {
212
- // An overall workspace version cannot be relevant when filtering to independent projects
213
- workspaceVersion: undefined,
214
- projectsVersionData: versionData,
215
- };
144
+ }
145
+ catch (err) {
146
+ // Flush any pending project logs before printing the error to make troubleshooting easier
147
+ processor.flushAllProjectLoggers();
148
+ // Bubble up the error so that the CLI can print the error and exit, or the programmatic API can handle it
149
+ throw err;
216
150
  }
217
151
  /**
218
- * Run versioning for all remaining release groups
152
+ * Ensure that formatting is applied so that version bump diffs are as minimal as possible
153
+ * within the context of the user's workspace.
219
154
  */
220
- for (const releaseGroup of releaseGroups) {
221
- const releaseGroupName = releaseGroup.name;
222
- runPreVersionCommand(releaseGroup.version.groupPreVersionCommand, {
223
- dryRun: args.dryRun,
224
- verbose: args.verbose,
225
- }, releaseGroup);
226
- const projectBatches = (0, batch_projects_by_generator_config_1.batchProjectsByGeneratorConfig)(projectGraph, releaseGroup,
227
- // Batch based on all projects within the release group
228
- releaseGroup.projects);
229
- for (const [generatorConfigString, projectNames,] of projectBatches.entries()) {
230
- const [generatorName, generatorOptions] = JSON.parse(generatorConfigString);
231
- // Resolve the generator for the batch and run versioning on the projects within the batch
232
- const generatorData = resolveGeneratorData({
233
- ...extractGeneratorCollectionAndName(`batch "${JSON.stringify(projectNames)}" for release-group "${releaseGroupName}"`, generatorName),
234
- configGeneratorOptions: generatorOptions,
235
- // all project data from the project graph (not to be confused with projectNamesToRunVersionOn)
236
- projects,
237
- });
238
- const generatorCallback = await runVersionOnProjects(projectGraph, nxJson, args, tree, generatorData, args.generatorOptionsOverrides, projectNames, releaseGroup, versionData, nxReleaseConfig.conventionalCommits);
239
- // Capture the callback so that we can run it after flushing the changes to disk
240
- generatorCallbacks.push(async () => {
241
- const result = await generatorCallback(tree, {
242
- dryRun: !!args.dryRun,
243
- verbose: !!args.verbose,
244
- generatorOptions: {
245
- ...generatorOptions,
246
- ...args.generatorOptionsOverrides,
247
- },
248
- });
249
- const { changedFiles, deletedFiles } = parseGeneratorCallbackResult(result);
250
- changedFiles.forEach((f) => additionalChangedFiles.add(f));
251
- deletedFiles.forEach((f) => additionalDeletedFiles.add(f));
252
- });
253
- }
254
- }
155
+ await (0, format_changed_files_with_prettier_if_available_1.formatChangedFilesWithPrettierIfAvailable)(tree, { silent: true });
156
+ const versionData = processor.getVersionData();
255
157
  // Resolve any git tags as early as possible so that we can hard error in case of any duplicates before reaching the actual git command
256
158
  const gitTagValues = args.gitTag ?? nxReleaseConfig.version.git.tag
257
159
  ? (0, shared_1.createGitTagValues)(releaseGroups, releaseGroupToFilteredProjects, versionData)
258
160
  : [];
259
161
  (0, shared_1.handleDuplicateGitTags)(gitTagValues);
260
162
  printAndFlushChanges(tree, !!args.dryRun);
261
- for (const generatorCallback of generatorCallbacks) {
262
- await generatorCallback();
263
- }
163
+ const { changedFiles: changed, deletedFiles: deleted } = await processor.afterAllProjectsVersioned(nxReleaseConfig.version
164
+ .versionActionsOptions);
165
+ changed.forEach((f) => additionalChangedFiles.add(f));
166
+ deleted.forEach((f) => additionalDeletedFiles.add(f));
264
167
  // Only applicable when there is a single release group with a fixed relationship
265
168
  let workspaceVersion = undefined;
266
169
  if (releaseGroups.length === 1) {
@@ -314,11 +217,12 @@ function createAPI(overrideReleaseConfig) {
314
217
  }
315
218
  }
316
219
  if (args.gitPush ?? nxReleaseConfig.version.git.push) {
317
- output_1.output.logSingleLine(`Pushing to git remote "${args.gitRemote}"`);
220
+ output_1.output.logSingleLine(`Pushing to git remote "${args.gitRemote ?? 'origin'}"`);
318
221
  await (0, git_1.gitPush)({
319
222
  gitRemote: args.gitRemote,
320
223
  dryRun: args.dryRun,
321
224
  verbose: args.verbose,
225
+ additionalArgs: args.gitPushArgs || nxReleaseConfig.version.git.pushArgs,
322
226
  });
323
227
  }
324
228
  return {
@@ -327,109 +231,34 @@ function createAPI(overrideReleaseConfig) {
327
231
  };
328
232
  };
329
233
  }
330
- function appendVersionData(existingVersionData, newVersionData) {
331
- // Mutate the existing version data
332
- for (const [key, value] of Object.entries(newVersionData)) {
333
- if (existingVersionData[key]) {
334
- throw new Error(`Version data key "${key}" already exists in version data. This is likely a bug, please report your use-case on https://github.com/nrwl/nx`);
335
- }
336
- existingVersionData[key] = value;
337
- }
338
- return existingVersionData;
339
- }
340
- async function runVersionOnProjects(projectGraph, nxJson, args, tree, generatorData, generatorOverrides, projectNames, releaseGroup, versionData, conventionalCommitsConfig) {
341
- const generatorOptions = {
342
- // Always ensure a string to avoid generator schema validation errors
343
- specifier: args.specifier ?? '',
344
- preid: args.preid ?? '',
345
- ...generatorData.configGeneratorOptions,
346
- ...(generatorOverrides ?? {}),
347
- // The following are not overridable by user config
348
- projects: projectNames.map((p) => projectGraph.nodes[p]),
349
- projectGraph,
350
- releaseGroup,
351
- firstRelease: args.firstRelease ?? false,
352
- conventionalCommitsConfig,
353
- deleteVersionPlans: args.deleteVersionPlans,
354
- };
355
- // Apply generator defaults from schema.json file etc
356
- const combinedOpts = await (0, params_1.combineOptionsForGenerator)(generatorOptions, generatorData.collectionName, generatorData.normalizedGeneratorName, (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph), nxJson, generatorData.schema, false, null, (0, node_path_1.relative)(process.cwd(), workspace_root_1.workspaceRoot), args.verbose);
357
- const releaseVersionGenerator = generatorData.implementationFactory();
358
- // We expect all version generator implementations to return a ReleaseVersionGeneratorResult object, rather than a GeneratorCallback
359
- const versionResult = (await releaseVersionGenerator(tree, combinedOpts));
360
- if (typeof versionResult === 'function') {
361
- throw new Error(`The version generator ${generatorData.collectionName}:${generatorData.normalizedGeneratorName} returned a function instead of an expected ReleaseVersionGeneratorResult`);
362
- }
363
- // Merge the extra version data into the existing
364
- appendVersionData(versionData, versionResult.data);
365
- return versionResult.callback;
366
- }
367
234
  function printAndFlushChanges(tree, isDryRun) {
368
235
  const changes = tree.listChanges();
369
236
  console.log('');
370
- // Print the changes
371
- changes.forEach((f) => {
372
- if (f.type === 'CREATE') {
373
- console.error(`${chalk.green('CREATE')} ${f.path}${isDryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
374
- (0, print_changes_1.printDiff)('', f.content?.toString() || '');
375
- }
376
- else if (f.type === 'UPDATE') {
377
- console.error(`${chalk.white('UPDATE')} ${f.path}${isDryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
378
- const currentContentsOnDisk = (0, node_fs_1.readFileSync)((0, path_1.joinPathFragments)(tree.root, f.path)).toString();
379
- (0, print_changes_1.printDiff)(currentContentsOnDisk, f.content?.toString() || '');
380
- }
381
- else if (f.type === 'DELETE' && !f.path.includes('.nx')) {
382
- throw new Error('Unexpected DELETE change, please report this as an issue');
383
- }
384
- });
385
- if (!isDryRun) {
386
- (0, tree_1.flushChanges)(workspace_root_1.workspaceRoot, changes);
387
- }
388
- }
389
- function extractGeneratorCollectionAndName(description, generatorString) {
390
- let collectionName;
391
- let generatorName;
392
- const parsedGeneratorString = (0, generate_1.parseGeneratorString)(generatorString);
393
- collectionName = parsedGeneratorString.collection;
394
- generatorName = parsedGeneratorString.generator;
395
- if (!collectionName || !generatorName) {
396
- throw new Error(`Invalid generator string: ${generatorString} used for ${description}. Must be in the format of [collectionName]:[generatorName]`);
397
- }
398
- return { collectionName, generatorName };
399
- }
400
- function resolveGeneratorData({ collectionName, generatorName, configGeneratorOptions, projects, }) {
401
- try {
402
- const { normalizedGeneratorName, schema, implementationFactory } = (0, generator_utils_1.getGeneratorInformation)(collectionName, generatorName, workspace_root_1.workspaceRoot, projects);
403
- return {
404
- collectionName,
405
- generatorName,
406
- configGeneratorOptions,
407
- normalizedGeneratorName,
408
- schema,
409
- implementationFactory,
410
- };
411
- }
412
- catch (err) {
413
- if (err.message.startsWith('Unable to resolve')) {
414
- // See if it is because the plugin is not installed
415
- try {
416
- require.resolve(collectionName);
417
- // is installed
418
- throw new Error(`Unable to resolve the generator called "${generatorName}" within the "${collectionName}" package`);
237
+ if (changes.length > 0) {
238
+ // Print the changes
239
+ changes.forEach((f) => {
240
+ if (f.type === 'CREATE') {
241
+ console.error(`${chalk.green('CREATE')} ${f.path}${isDryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
242
+ (0, print_changes_1.printDiff)('', f.content?.toString() || '');
419
243
  }
420
- catch {
421
- /**
422
- * Special messaging for the most common case (especially as the user is unlikely to explicitly have
423
- * the @nx/js generator config in their nx.json so we need to be clear about what the problem is)
424
- */
425
- if (collectionName === '@nx/js') {
426
- throw new Error('The @nx/js plugin is required in order to version your JavaScript packages. Run "nx add @nx/js" to add it to your workspace.');
427
- }
428
- throw new Error(`Unable to resolve the package ${collectionName} in order to load the generator called ${generatorName}. Is the package installed?`);
244
+ else if (f.type === 'UPDATE') {
245
+ console.error(`${chalk.white('UPDATE')} ${f.path}${isDryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
246
+ const currentContentsOnDisk = (0, node_fs_1.readFileSync)((0, path_1.joinPathFragments)(tree.root, f.path)).toString();
247
+ (0, print_changes_1.printDiff)(currentContentsOnDisk, f.content?.toString() || '');
429
248
  }
430
- }
431
- // Unexpected error, rethrow
432
- throw err;
249
+ else if (f.type === 'DELETE' && !f.path.includes('.nx')) {
250
+ throw new Error('Unexpected DELETE change, please report this as an issue');
251
+ }
252
+ });
253
+ }
254
+ else {
255
+ let text = isDryRun ? ' would be ' : ' ';
256
+ output_1.output.warn({
257
+ title: `No files${text}changed as a result of running versioning`,
258
+ });
259
+ }
260
+ if (!isDryRun) {
261
+ (0, tree_1.flushChanges)(workspace_root_1.workspaceRoot, changes);
433
262
  }
434
263
  }
435
264
  function runPreVersionCommand(preVersionCommand, { dryRun, verbose }, releaseGroup) {
@@ -470,14 +299,3 @@ function runPreVersionCommand(preVersionCommand, { dryRun, verbose }, releaseGro
470
299
  process.exit(1);
471
300
  }
472
301
  }
473
- function parseGeneratorCallbackResult(result) {
474
- if (Array.isArray(result)) {
475
- return {
476
- changedFiles: result,
477
- deletedFiles: [],
478
- };
479
- }
480
- else {
481
- return result;
482
- }
483
- }
@@ -1,4 +1,5 @@
1
1
  import type { ChangelogRenderOptions } from '../../release/changelog-renderer';
2
+ import { validReleaseVersionPrefixes } from '../command-line/release/version';
2
3
  import type { PackageManager } from '../utils/package-manager';
3
4
  import type { InputDefinition, TargetConfiguration, TargetDependencyConfig } from './workspace-json-project-json';
4
5
  export type ImplicitDependencyEntry<T = '*' | string[]> = {
@@ -35,6 +36,12 @@ interface NxInstallationConfiguration {
35
36
  */
36
37
  plugins?: Record<string, string>;
37
38
  }
39
+ /**
40
+ * This named configuration interface will be changing in Nx v21. This interface will be made available
41
+ * under LegacyNxReleaseVersionConfiguration, which is already available as an alias.
42
+ *
43
+ * In Nx v22, this configuration interface will no longer be valid.
44
+ */
38
45
  export interface NxReleaseVersionConfiguration {
39
46
  generator?: string;
40
47
  generatorOptions?: Record<string, unknown>;
@@ -50,6 +57,100 @@ export interface NxReleaseVersionConfiguration {
50
57
  */
51
58
  conventionalCommits?: boolean;
52
59
  }
60
+ export type LegacyNxReleaseVersionConfiguration = NxReleaseVersionConfiguration;
61
+ export interface NxReleaseVersionV2Configuration {
62
+ /**
63
+ * Whether to use the legacy versioning strategy. This value will be true in Nx v20 and false in Nx v21.
64
+ * The legacy versioning implementation will be removed in Nx v22, as will this flag.
65
+ */
66
+ useLegacyVersioning?: boolean;
67
+ /**
68
+ * Shorthand for enabling the current version of projects to be resolved from git tags,
69
+ * and the next version to be determined by analyzing commit messages according to the
70
+ * Conventional Commits specification.
71
+ */
72
+ conventionalCommits?: boolean;
73
+ /**
74
+ * A command to run after validation of nx release configuration, but before versioning begins.
75
+ * Useful for preparing build artifacts. If --dry-run is passed, the command is still executed,
76
+ * but with the NX_DRY_RUN environment variable set to 'true'.
77
+ */
78
+ preVersionCommand?: string;
79
+ /**
80
+ * The source to use for determining the specifier to use when versioning.
81
+ * 'prompt' is the default and will interactively prompt the user for an explicit/imperative specifier.
82
+ * 'conventional-commits' will attempt determine a specifier from commit messages conforming to the Conventional Commits specification.
83
+ * 'version-plans' will determine the specifier from the version plan files available on disk.
84
+ */
85
+ specifierSource?: 'prompt' | 'conventional-commits' | 'version-plans';
86
+ /**
87
+ * A list of directories containing manifest files (such as package.json) to apply updates to when versioning.
88
+ *
89
+ * By default, only the project root will be used, but you could customize this to only version a manifest in a
90
+ * dist directory, or even version multiple manifests in different directories, such as both source and dist.
91
+ */
92
+ manifestRootsToUpdate?: string[];
93
+ /**
94
+ * The resolver to use for determining the current version of a project during versioning.
95
+ * This is needed for versioning approaches which involve relatively modifying a current version
96
+ * to arrive at a new version, such as semver bumps like 'patch', 'minor' etc.
97
+ *
98
+ * Using 'none' explicitly declares that the current version is not needed to compute the new version, and
99
+ * should only be used with appropriate version actions implementations that support it.
100
+ */
101
+ currentVersionResolver?: 'registry' | 'disk' | 'git-tag' | 'none';
102
+ /**
103
+ * Metadata to provide to the configured currentVersionResolver to help it in determining the current version.
104
+ * What to pass here is specific to each resolver.
105
+ */
106
+ currentVersionResolverMetadata?: Record<string, unknown>;
107
+ /**
108
+ * The fallback version resolver to use when the configured currentVersionResolver fails to resolve the current version.
109
+ */
110
+ fallbackCurrentVersionResolver?: 'disk';
111
+ /**
112
+ * Whether or not this is the first release of one of more projects.
113
+ * This removes certain validation checks that are not possible to enforce if the project has never been released before.
114
+ */
115
+ firstRelease?: boolean;
116
+ /**
117
+ * The prefix to use when versioning dependencies.
118
+ * This can be one of the following: auto, '', '~', '^', '=', where auto means the existing prefix will be preserved.
119
+ */
120
+ versionPrefix?: (typeof validReleaseVersionPrefixes)[number];
121
+ /**
122
+ * Whether to delete the processed version plans file after versioning is complete. This is false by default because the
123
+ * version plans are also needed for changelog generation.
124
+ */
125
+ deleteVersionPlans?: boolean;
126
+ /**
127
+ * When versioning independent projects, this controls whether to update their dependents (i.e. the things that depend on them).
128
+ * 'never' means no dependents will be updated (unless they happen to be versioned directly as well).
129
+ * 'auto' is the default and will cause dependents to be updated (a patch version bump) when a dependency is versioned.
130
+ */
131
+ updateDependents?: 'auto' | 'never';
132
+ /**
133
+ * Whether to log projects that have not changed during versioning.
134
+ */
135
+ logUnchangedProjects?: boolean;
136
+ /**
137
+ * The path to the version actions implementation to use for releasing all projects by default.
138
+ * This can also be overridden on the release group and project levels.
139
+ */
140
+ versionActions?: string;
141
+ /**
142
+ * The specific options that are defined by each version actions implementation.
143
+ * They will be passed to the version actions implementation when running a release.
144
+ */
145
+ versionActionsOptions?: Record<string, unknown>;
146
+ /**
147
+ * Whether to preserve local dependency protocols (e.g. file references, or the `workspace:` protocol in package.json files)
148
+ * of local dependencies when updating them during versioning.
149
+ *
150
+ * This was false by default in legacy versioning, but is true by default now.
151
+ */
152
+ preserveLocalDependencyProtocols?: boolean;
153
+ }
53
154
  export interface NxReleaseChangelogConfiguration {
54
155
  /**
55
156
  * Optionally create a release containing all relevant changes on a supported version control system, it
@@ -131,6 +232,10 @@ export interface NxReleaseGitConfiguration {
131
232
  * Whether or not to automatically push the changes made by this command to the remote git repository.
132
233
  */
133
234
  push?: boolean;
235
+ /**
236
+ * Additional arguments to pass to the `git push` command invoked behind the scenes. May be a string or array of strings.
237
+ */
238
+ pushArgs?: string | string[];
134
239
  }
135
240
  export interface NxReleaseConventionalCommitsConfiguration {
136
241
  types?: Record<string,
@@ -190,7 +295,7 @@ export interface NxReleaseConfiguration {
190
295
  *
191
296
  * NOTE: git configuration is not supported at the group level, only the root/command level
192
297
  */
193
- version?: NxReleaseVersionConfiguration & {
298
+ version?: (LegacyNxReleaseVersionConfiguration | NxReleaseVersionV2Configuration) & {
194
299
  /**
195
300
  * A command to run after validation of nx release configuration, but before versioning begins.
196
301
  * Used for preparing build artifacts. If --dry-run is passed, the command is still executed, but
@@ -264,19 +369,12 @@ export interface NxReleaseConfiguration {
264
369
  automaticFromRef?: boolean;
265
370
  };
266
371
  /**
267
- * If no version config is provided, we will assume that @nx/js:release-version
268
- * is the desired generator implementation, allowing for terser config for the common case.
372
+ * If no version configuration is provided, we will assume that TypeScript/JavaScript experience is what is desired,
373
+ * allowing for terser release configuration for the common case.
269
374
  */
270
- version?: NxReleaseVersionConfiguration & {
271
- /**
272
- * Enable or override configuration for git operations as part of the version subcommand
273
- */
375
+ version?: (LegacyNxReleaseVersionConfiguration | NxReleaseVersionV2Configuration) & {
376
+ useLegacyVersioning?: boolean;
274
377
  git?: NxReleaseGitConfiguration;
275
- /**
276
- * A command to run after validation of nx release configuration, but before versioning begins.
277
- * Used for preparing build artifacts. If --dry-run is passed, the command is still executed, but
278
- * with the NX_DRY_RUN environment variable set to 'true'.
279
- */
280
378
  preVersionCommand?: string;
281
379
  };
282
380
  /**
@@ -1,5 +1,5 @@
1
1
  import type { PackageJson } from '../utils/package-json';
2
- import type { NxJsonConfiguration, NxReleaseVersionConfiguration } from './nx-json';
2
+ import type { NxJsonConfiguration, NxReleaseVersionConfiguration, NxReleaseVersionV2Configuration } from './nx-json';
3
3
  /**
4
4
  * @deprecated use ProjectsConfigurations or NxJsonConfiguration
5
5
  */
@@ -98,7 +98,7 @@ export interface ProjectConfiguration {
98
98
  * Project specific configuration for `nx release`
99
99
  */
100
100
  release?: {
101
- version?: Pick<NxReleaseVersionConfiguration, 'generator' | 'generatorOptions'>;
101
+ version?: Pick<NxReleaseVersionConfiguration, 'generator' | 'generatorOptions'> | Pick<NxReleaseVersionV2Configuration, 'versionActions' | 'versionActionsOptions' | 'manifestRootsToUpdate' | 'currentVersionResolver' | 'currentVersionResolverMetadata' | 'fallbackCurrentVersionResolver' | 'versionPrefix' | 'preserveLocalDependencyProtocols'>;
102
102
  };
103
103
  /**
104
104
  * Metadata about the project