nx 21.0.0-canary.20250429-cf4a1f3 → 21.0.0-canary.20250501-8f50358

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 (63) hide show
  1. package/migrations.json +16 -1
  2. package/package.json +11 -11
  3. package/release/changelog-renderer/index.d.ts +7 -7
  4. package/release/changelog-renderer/index.js +12 -31
  5. package/schemas/nx-schema.json +8 -3
  6. package/src/command-line/migrate/migrate-ui-api.d.ts +2 -1
  7. package/src/command-line/migrate/migrate-ui-api.js +4 -3
  8. package/src/command-line/migrate/migrate.d.ts +12 -6
  9. package/src/command-line/migrate/migrate.js +31 -9
  10. package/src/command-line/release/changelog.d.ts +3 -2
  11. package/src/command-line/release/changelog.js +57 -70
  12. package/src/command-line/release/command-object.d.ts +1 -1
  13. package/src/command-line/release/config/config.d.ts +8 -1
  14. package/src/command-line/release/config/config.js +18 -11
  15. package/src/command-line/release/release.js +30 -18
  16. package/src/command-line/release/utils/git.d.ts +1 -0
  17. package/src/command-line/release/utils/git.js +27 -8
  18. package/src/command-line/release/utils/remote-release-clients/github.d.ts +57 -0
  19. package/src/command-line/release/utils/remote-release-clients/github.js +309 -0
  20. package/src/command-line/release/utils/remote-release-clients/gitlab.d.ts +62 -0
  21. package/src/command-line/release/utils/remote-release-clients/gitlab.js +271 -0
  22. package/src/command-line/release/utils/remote-release-clients/remote-release-client.d.ts +111 -0
  23. package/src/command-line/release/utils/remote-release-clients/remote-release-client.js +136 -0
  24. package/src/command-line/repair/repair.js +8 -2
  25. package/src/command-line/report/report.js +1 -1
  26. package/src/command-line/yargs-utils/shared-options.d.ts +1 -1
  27. package/src/command-line/yargs-utils/shared-options.js +22 -3
  28. package/src/config/misc-interfaces.d.ts +9 -1
  29. package/src/config/nx-json.d.ts +8 -5
  30. package/src/core/graph/main.js +1 -1
  31. package/src/core/graph/styles.css +1 -1
  32. package/src/devkit-exports.d.ts +1 -1
  33. package/src/migrations/update-21-0-0/release-changelog-config-changes.d.ts +2 -0
  34. package/src/migrations/update-21-0-0/release-changelog-config-changes.js +38 -0
  35. package/src/migrations/update-21-0-0/remove-custom-tasks-runner.d.ts +2 -0
  36. package/src/migrations/update-21-0-0/remove-custom-tasks-runner.js +38 -0
  37. package/src/migrations/update-21-0-0/remove-legacy-cache.d.ts +2 -0
  38. package/src/migrations/update-21-0-0/remove-legacy-cache.js +17 -0
  39. package/src/native/index.d.ts +6 -1
  40. package/src/native/native-bindings.js +1 -0
  41. package/src/native/native-file-cache-location.js +2 -1
  42. package/src/native/nx.wasm32-wasi.wasm +0 -0
  43. package/src/project-graph/plugins/get-plugins.js +19 -14
  44. package/src/tasks-runner/batch/run-batch.js +1 -1
  45. package/src/tasks-runner/cache.d.ts +1 -2
  46. package/src/tasks-runner/cache.js +2 -18
  47. package/src/tasks-runner/is-tui-enabled.d.ts +16 -1
  48. package/src/tasks-runner/is-tui-enabled.js +40 -28
  49. package/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +8 -7
  50. package/src/tasks-runner/pseudo-terminal.d.ts +1 -0
  51. package/src/tasks-runner/pseudo-terminal.js +11 -1
  52. package/src/tasks-runner/run-command.js +5 -27
  53. package/src/tasks-runner/running-tasks/node-child-process.d.ts +1 -0
  54. package/src/tasks-runner/running-tasks/node-child-process.js +7 -0
  55. package/src/tasks-runner/task-graph-utils.d.ts +3 -0
  56. package/src/tasks-runner/task-graph-utils.js +31 -2
  57. package/src/tasks-runner/task-orchestrator.js +16 -4
  58. package/src/utils/is-ci.d.ts +1 -1
  59. package/src/utils/is-ci.js +4 -1
  60. package/src/utils/package-manager.d.ts +1 -0
  61. package/src/utils/package-manager.js +29 -16
  62. package/src/command-line/release/utils/github.d.ts +0 -32
  63. package/src/command-line/release/utils/github.js +0 -326
package/migrations.json CHANGED
@@ -29,10 +29,25 @@
29
29
  "implementation": "./src/migrations/update-20-0-1/use-legacy-cache",
30
30
  "x-repair-skip": true
31
31
  },
32
+ "remove-legacy-cache": {
33
+ "version": "21.0.0-beta.8",
34
+ "description": "Removes the legacy cache configuration from nx.json",
35
+ "implementation": "./src/migrations/update-21-0-0/remove-legacy-cache"
36
+ },
37
+ "remove-custom-tasks-runner": {
38
+ "version": "21.0.0-beta.8",
39
+ "description": "Removes the legacy cache configuration from nx.json",
40
+ "implementation": "./src/migrations/update-21-0-0/remove-custom-tasks-runner"
41
+ },
32
42
  "release-version-config-changes": {
33
- "version": "21.0.0-beta.1",
43
+ "version": "21.0.0-beta.11",
34
44
  "description": "Updates release version config based on the breaking changes in Nx v21",
35
45
  "implementation": "./src/migrations/update-21-0-0/release-version-config-changes"
46
+ },
47
+ "release-changelog-config-changes": {
48
+ "version": "21.0.0-beta.11",
49
+ "description": "Updates release changelog config based on the breaking changes in Nx v21",
50
+ "implementation": "./src/migrations/update-21-0-0/release-changelog-config-changes"
36
51
  }
37
52
  }
38
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "21.0.0-canary.20250429-cf4a1f3",
3
+ "version": "21.0.0-canary.20250501-8f50358",
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": {
@@ -83,16 +83,16 @@
83
83
  }
84
84
  },
85
85
  "optionalDependencies": {
86
- "@nx/nx-darwin-arm64": "21.0.0-canary.20250429-cf4a1f3",
87
- "@nx/nx-darwin-x64": "21.0.0-canary.20250429-cf4a1f3",
88
- "@nx/nx-freebsd-x64": "21.0.0-canary.20250429-cf4a1f3",
89
- "@nx/nx-linux-arm-gnueabihf": "21.0.0-canary.20250429-cf4a1f3",
90
- "@nx/nx-linux-arm64-gnu": "21.0.0-canary.20250429-cf4a1f3",
91
- "@nx/nx-linux-arm64-musl": "21.0.0-canary.20250429-cf4a1f3",
92
- "@nx/nx-linux-x64-gnu": "21.0.0-canary.20250429-cf4a1f3",
93
- "@nx/nx-linux-x64-musl": "21.0.0-canary.20250429-cf4a1f3",
94
- "@nx/nx-win32-arm64-msvc": "21.0.0-canary.20250429-cf4a1f3",
95
- "@nx/nx-win32-x64-msvc": "21.0.0-canary.20250429-cf4a1f3"
86
+ "@nx/nx-darwin-arm64": "21.0.0-canary.20250501-8f50358",
87
+ "@nx/nx-darwin-x64": "21.0.0-canary.20250501-8f50358",
88
+ "@nx/nx-freebsd-x64": "21.0.0-canary.20250501-8f50358",
89
+ "@nx/nx-linux-arm-gnueabihf": "21.0.0-canary.20250501-8f50358",
90
+ "@nx/nx-linux-arm64-gnu": "21.0.0-canary.20250501-8f50358",
91
+ "@nx/nx-linux-arm64-musl": "21.0.0-canary.20250501-8f50358",
92
+ "@nx/nx-linux-x64-gnu": "21.0.0-canary.20250501-8f50358",
93
+ "@nx/nx-linux-x64-musl": "21.0.0-canary.20250501-8f50358",
94
+ "@nx/nx-win32-arm64-msvc": "21.0.0-canary.20250501-8f50358",
95
+ "@nx/nx-win32-x64-msvc": "21.0.0-canary.20250501-8f50358"
96
96
  },
97
97
  "nx-migrations": {
98
98
  "migrations": "./migrations.json",
@@ -1,6 +1,6 @@
1
- import { ChangelogChange } from '../../src/command-line/release/changelog';
2
- import { NxReleaseConfig } from '../../src/command-line/release/config/config';
3
- import { GithubRepoData } from '../../src/command-line/release/utils/github';
1
+ import type { ChangelogChange } from '../../src/command-line/release/changelog';
2
+ import type { NxReleaseConfig } from '../../src/command-line/release/config/config';
3
+ import type { RemoteReleaseClient } from '../../src/command-line/release/utils/remote-release-clients/remote-release-client';
4
4
  /**
5
5
  * The ChangelogRenderOptions are specific to each ChangelogRenderer implementation, and are taken
6
6
  * from the user's nx.json configuration and passed as is into the ChangelogRenderer function.
@@ -30,7 +30,7 @@ export interface DefaultChangelogRenderOptions extends ChangelogRenderOptions {
30
30
  * using https://ungh.cc (from https://github.com/unjs/ungh) and the email addresses found in the commits.
31
31
  * Defaults to true.
32
32
  */
33
- mapAuthorsToGitHubUsernames?: boolean;
33
+ applyUsernameToAuthors?: boolean;
34
34
  /**
35
35
  * Whether or not the commit references (such as commit and/or PR links) should be included in the changelog.
36
36
  * Defaults to true.
@@ -50,11 +50,11 @@ export default class DefaultChangelogRenderer {
50
50
  protected changelogRenderOptions: DefaultChangelogRenderOptions;
51
51
  protected isVersionPlans: boolean;
52
52
  protected dependencyBumps?: DependencyBump[];
53
- protected repoData?: GithubRepoData;
54
53
  protected conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'] | null;
55
54
  protected relevantChanges: ChangelogChange[];
56
55
  protected breakingChanges: string[];
57
56
  protected additionalChangesForAuthorsSection: ChangelogChange[];
57
+ protected remoteReleaseClient: RemoteReleaseClient<unknown>;
58
58
  /**
59
59
  * A ChangelogRenderer class takes in the determined changes and other relevant metadata
60
60
  * and returns a string, or a Promise of a string of changelog contents (usually markdown).
@@ -67,8 +67,8 @@ export default class DefaultChangelogRenderer {
67
67
  * @param {boolean} config.isVersionPlans Whether or not Nx release version plans are the source of truth for the changelog entry
68
68
  * @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
69
69
  * @param {DependencyBump[]} config.dependencyBumps Optional list of additional dependency bumps that occurred as part of the release, outside of the change data
70
- * @param {GithubRepoData} config.repoData Resolved data for the current GitHub repository
71
70
  * @param {NxReleaseConfig['conventionalCommits'] | null} config.conventionalCommitsConfig The configuration for conventional commits, or null if version plans are being used
71
+ * @param {RemoteReleaseClient} config.remoteReleaseClient The remote release client to use for formatting references
72
72
  */
73
73
  constructor(config: {
74
74
  changes: ChangelogChange[];
@@ -78,8 +78,8 @@ export default class DefaultChangelogRenderer {
78
78
  isVersionPlans: boolean;
79
79
  changelogRenderOptions: DefaultChangelogRenderOptions;
80
80
  dependencyBumps?: DependencyBump[];
81
- repoData?: GithubRepoData;
82
81
  conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'] | null;
82
+ remoteReleaseClient: RemoteReleaseClient<unknown>;
83
83
  });
84
84
  protected filterChanges(changes: ChangelogChange[], project: string | null): ChangelogChange[];
85
85
  render(): Promise<string>;
@@ -2,10 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const semver_1 = require("semver");
4
4
  const conventional_commits_1 = require("../../src/command-line/release/config/conventional-commits");
5
- const github_1 = require("../../src/command-line/release/utils/github");
6
- // axios types and values don't seem to match
7
- const _axios = require("axios");
8
- const axios = _axios;
9
5
  class DefaultChangelogRenderer {
10
6
  /**
11
7
  * A ChangelogRenderer class takes in the determined changes and other relevant metadata
@@ -19,8 +15,8 @@ class DefaultChangelogRenderer {
19
15
  * @param {boolean} config.isVersionPlans Whether or not Nx release version plans are the source of truth for the changelog entry
20
16
  * @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
21
17
  * @param {DependencyBump[]} config.dependencyBumps Optional list of additional dependency bumps that occurred as part of the release, outside of the change data
22
- * @param {GithubRepoData} config.repoData Resolved data for the current GitHub repository
23
18
  * @param {NxReleaseConfig['conventionalCommits'] | null} config.conventionalCommitsConfig The configuration for conventional commits, or null if version plans are being used
19
+ * @param {RemoteReleaseClient} config.remoteReleaseClient The remote release client to use for formatting references
24
20
  */
25
21
  constructor(config) {
26
22
  this.changes = this.filterChanges(config.changes, config.project);
@@ -30,8 +26,8 @@ class DefaultChangelogRenderer {
30
26
  this.isVersionPlans = config.isVersionPlans;
31
27
  this.changelogRenderOptions = config.changelogRenderOptions;
32
28
  this.dependencyBumps = config.dependencyBumps;
33
- this.repoData = config.repoData;
34
29
  this.conventionalCommitsConfig = config.conventionalCommitsConfig;
30
+ this.remoteReleaseClient = config.remoteReleaseClient;
35
31
  this.relevantChanges = [];
36
32
  this.breakingChanges = [];
37
33
  this.additionalChangesForAuthorsSection = [];
@@ -234,27 +230,11 @@ class DefaultChangelogRenderer {
234
230
  }
235
231
  }
236
232
  }
237
- if (this.repoData &&
238
- this.changelogRenderOptions.mapAuthorsToGitHubUsernames) {
239
- await Promise.all([..._authors.keys()].map(async (authorName) => {
240
- const meta = _authors.get(authorName);
241
- for (const email of meta.email) {
242
- if (email.endsWith('@users.noreply.github.com')) {
243
- const match = email.match(/^(\d+\+)?([^@]+)@users\.noreply\.github\.com$/);
244
- if (match && match[2]) {
245
- meta.github = match[2];
246
- break;
247
- }
248
- }
249
- const { data } = await axios
250
- .get(`https://ungh.cc/users/find/${email}`)
251
- .catch(() => ({ data: { user: null } }));
252
- if (data?.user) {
253
- meta.github = data.user.username;
254
- break;
255
- }
256
- }
257
- }));
233
+ if (this.remoteReleaseClient.getRemoteRepoData() &&
234
+ this.changelogRenderOptions.applyUsernameToAuthors &&
235
+ // TODO: Explore if it is possible to support GitLab username resolution
236
+ this.remoteReleaseClient.remoteReleaseProviderName === 'GitHub') {
237
+ await this.remoteReleaseClient.applyUsernameToAuthors(_authors);
258
238
  }
259
239
  const authors = [..._authors.entries()].map((e) => ({
260
240
  name: e[0],
@@ -264,8 +244,8 @@ class DefaultChangelogRenderer {
264
244
  markdownLines.push('', '### ' + '❤️ Thank You', '', ...authors
265
245
  .sort((a, b) => a.name.localeCompare(b.name))
266
246
  .map((i) => {
267
- const github = i.github ? ` @${i.github}` : '';
268
- return `- ${i.name}${github}`;
247
+ const username = i.username ? ` @${i.username}` : '';
248
+ return `- ${i.name}${username}`;
269
249
  }));
270
250
  }
271
251
  return markdownLines;
@@ -288,8 +268,9 @@ class DefaultChangelogRenderer {
288
268
  ? `**${change.scope.trim()}:** `
289
269
  : '') +
290
270
  description;
291
- if (this.repoData && this.changelogRenderOptions.commitReferences) {
292
- changeLine += (0, github_1.formatReferences)(change.githubReferences, this.repoData);
271
+ if (this.remoteReleaseClient.getRemoteRepoData() &&
272
+ this.changelogRenderOptions.commitReferences) {
273
+ changeLine += this.remoteReleaseClient.formatReferences(change.githubReferences);
293
274
  }
294
275
  if (extraLinesStr) {
295
276
  changeLine += '\n\n' + extraLinesStr;
@@ -543,6 +543,11 @@
543
543
  "type": "object"
544
544
  }
545
545
  },
546
+ "continuous": {
547
+ "type": "boolean",
548
+ "default": false,
549
+ "description": "Whether this target runs continuously until stopped"
550
+ },
546
551
  "parallelism": {
547
552
  "type": "boolean",
548
553
  "default": true,
@@ -849,7 +854,7 @@
849
854
  "oneOf": [
850
855
  {
851
856
  "type": "string",
852
- "enum": ["github"]
857
+ "enum": ["github", "gitlab"]
853
858
  },
854
859
  {
855
860
  "type": "boolean",
@@ -895,7 +900,7 @@
895
900
  "properties": {
896
901
  "provider": {
897
902
  "type": "string",
898
- "enum": ["github-enterprise-server"]
903
+ "enum": ["github-enterprise-server", "gitlab"]
899
904
  },
900
905
  "hostname": {
901
906
  "type": "string",
@@ -903,7 +908,7 @@
903
908
  },
904
909
  "apiBaseUrl": {
905
910
  "type": "string",
906
- "description": "The base URL for the relevant VCS provider API. If not set, this will default to `https://${hostname}/api/v3`"
911
+ "description": "The base URL for the relevant VCS provider API. If not set, this will default to `https://${hostname}/api/v3` (github) or `https://${hostname}/api/v4` (gitlab)."
907
912
  }
908
913
  },
909
914
  "required": ["provider", "hostname"]
@@ -15,6 +15,7 @@ export type SuccessfulMigration = {
15
15
  name: string;
16
16
  changedFiles: Omit<FileChange, 'content'>[];
17
17
  ref: string;
18
+ nextSteps?: string[];
18
19
  };
19
20
  export type FailedMigration = {
20
21
  type: 'failed';
@@ -32,7 +33,7 @@ export declare function runSingleMigration(workspacePath: string, migration: Mig
32
33
  }): Promise<void>;
33
34
  export declare function getImplementationPath(workspacePath: string, migration: MigrationDetailsWithId): Promise<string>;
34
35
  export declare function modifyMigrationsJsonMetadata(workspacePath: string, modify: (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata): void;
35
- export declare function addSuccessfulMigration(id: string, fileChanges: Omit<FileChange, 'content'>[], ref: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata;
36
+ export declare function addSuccessfulMigration(id: string, fileChanges: Omit<FileChange, 'content'>[], ref: string, nextSteps: string[]): (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata;
36
37
  export declare function updateRefForSuccessfulMigration(id: string, ref: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => MigrationsJsonMetadata;
37
38
  export declare function addFailedMigration(id: string, error: string): (migrationsJsonMetadata: MigrationsJsonMetadata) => {
38
39
  completedMigrations?: Record<string, SuccessfulMigration | FailedMigration | SkippedMigration>;
@@ -72,7 +72,7 @@ async function runSingleMigration(workspacePath, migration, configuration) {
72
72
  // 1. The CLI path to the migrated modules. The version of Nx is of the user's choosing. This may or may not have the new migrate API, so Console will check that `runSingleMigration` exists before using it.
73
73
  // 2. Bundled into Console, so the version is fixed to what we build Console with.
74
74
  const updatedMigrateModule = await Promise.resolve().then(() => require('./migrate.js'));
75
- const fileChanges = await updatedMigrateModule.runNxOrAngularMigration(workspacePath, migration, false, configuration.createCommits, configuration.commitPrefix || 'chore: [nx migration] ', undefined, true);
75
+ const { changes: fileChanges, nextSteps } = await updatedMigrateModule.runNxOrAngularMigration(workspacePath, migration, false, configuration.createCommits, configuration.commitPrefix || 'chore: [nx migration] ', undefined, true);
76
76
  const gitRefAfter = (0, child_process_1.execSync)('git rev-parse HEAD', {
77
77
  cwd: workspacePath,
78
78
  encoding: 'utf-8',
@@ -80,7 +80,7 @@ async function runSingleMigration(workspacePath, migration, configuration) {
80
80
  modifyMigrationsJsonMetadata(workspacePath, addSuccessfulMigration(migration.id, fileChanges.map((change) => ({
81
81
  path: change.path,
82
82
  type: change.type,
83
- })), gitRefAfter));
83
+ })), gitRefAfter, nextSteps));
84
84
  if (gitRefBefore !== gitRefAfter) {
85
85
  (0, child_process_1.execSync)('git add migrations.json', {
86
86
  cwd: workspacePath,
@@ -120,7 +120,7 @@ function modifyMigrationsJsonMetadata(workspacePath, modify) {
120
120
  migrationsJson['nx-console'] = modify(migrationsJson['nx-console']);
121
121
  (0, fs_1.writeFileSync)(migrationsJsonPath, JSON.stringify(migrationsJson, null, 2));
122
122
  }
123
- function addSuccessfulMigration(id, fileChanges, ref) {
123
+ function addSuccessfulMigration(id, fileChanges, ref, nextSteps) {
124
124
  return (migrationsJsonMetadata) => {
125
125
  const copied = { ...migrationsJsonMetadata };
126
126
  if (!copied.completedMigrations) {
@@ -133,6 +133,7 @@ function addSuccessfulMigration(id, fileChanges, ref) {
133
133
  name: id,
134
134
  changedFiles: fileChanges,
135
135
  ref,
136
+ nextSteps,
136
137
  },
137
138
  };
138
139
  return copied;
@@ -101,17 +101,23 @@ export declare function executeMigrations(root: string, migrations: {
101
101
  description?: string;
102
102
  version: string;
103
103
  }[], isVerbose: boolean, shouldCreateCommits: boolean, commitPrefix: string): Promise<{
104
- package: string;
105
- name: string;
106
- description?: string;
107
- version: string;
108
- }[]>;
104
+ migrationsWithNoChanges: {
105
+ package: string;
106
+ name: string;
107
+ description?: string;
108
+ version: string;
109
+ }[];
110
+ nextSteps: string[];
111
+ }>;
109
112
  export declare function runNxOrAngularMigration(root: string, migration: {
110
113
  package: string;
111
114
  name: string;
112
115
  description?: string;
113
116
  version: string;
114
- }, isVerbose: boolean, shouldCreateCommits: boolean, commitPrefix: string, installDepsIfChanged?: () => void, handleInstallDeps?: boolean): Promise<FileChange[]>;
117
+ }, isVerbose: boolean, shouldCreateCommits: boolean, commitPrefix: string, installDepsIfChanged?: () => void, handleInstallDeps?: boolean): Promise<{
118
+ changes: FileChange[];
119
+ nextSteps: string[];
120
+ }>;
115
121
  export declare function migrate(root: string, args: {
116
122
  [k: string]: any;
117
123
  }, rawArgs: string[]): Promise<number>;
@@ -935,10 +935,12 @@ async function executeMigrations(root, migrations, isVerbose, shouldCreateCommit
935
935
  logger_1.logger.info(`Running the following migrations:`);
936
936
  sortedMigrations.forEach((m) => logger_1.logger.info(`- ${m.package}: ${m.name} (${m.description})`));
937
937
  logger_1.logger.info(`---------------------------------------------------------\n`);
938
+ const allNextSteps = [];
938
939
  for (const m of sortedMigrations) {
939
940
  logger_1.logger.info(`Running migration ${m.package}: ${m.name}`);
940
941
  try {
941
- const changes = await runNxOrAngularMigration(root, m, isVerbose, shouldCreateCommits, commitPrefix, () => changedDepInstaller.installDepsIfChanged());
942
+ const { changes, nextSteps } = await runNxOrAngularMigration(root, m, isVerbose, shouldCreateCommits, commitPrefix, () => changedDepInstaller.installDepsIfChanged());
943
+ allNextSteps.push(...nextSteps);
942
944
  if (changes.length === 0) {
943
945
  migrationsWithNoChanges.push(m);
944
946
  }
@@ -954,7 +956,7 @@ async function executeMigrations(root, migrations, isVerbose, shouldCreateCommit
954
956
  if (!shouldCreateCommits) {
955
957
  changedDepInstaller.installDepsIfChanged();
956
958
  }
957
- return migrationsWithNoChanges;
959
+ return { migrationsWithNoChanges, nextSteps: allNextSteps };
958
960
  }
959
961
  class ChangedDepInstaller {
960
962
  constructor(root) {
@@ -976,13 +978,14 @@ async function runNxOrAngularMigration(root, migration, isVerbose, shouldCreateC
976
978
  }
977
979
  const { collection, collectionPath } = readMigrationCollection(migration.package, root);
978
980
  let changes = [];
981
+ let nextSteps = [];
979
982
  if (!isAngularMigration(collection, migration.name)) {
980
- changes = await runNxMigration(root, collectionPath, collection, migration.name);
983
+ ({ nextSteps, changes } = await runNxMigration(root, collectionPath, collection, migration.name));
981
984
  logger_1.logger.info(`Ran ${migration.name} from ${migration.package}`);
982
985
  logger_1.logger.info(` ${migration.description}\n`);
983
986
  if (changes.length < 1) {
984
987
  logger_1.logger.info(`No changes were made\n`);
985
- return [];
988
+ return { changes, nextSteps };
986
989
  }
987
990
  logger_1.logger.info('Changes:');
988
991
  (0, tree_1.printChanges)(changes, ' ');
@@ -996,7 +999,7 @@ async function runNxOrAngularMigration(root, migration, isVerbose, shouldCreateC
996
999
  logger_1.logger.info(` ${migration.description}\n`);
997
1000
  if (!madeChanges) {
998
1001
  logger_1.logger.info(`No changes were made\n`);
999
- return [];
1002
+ return { changes, nextSteps };
1000
1003
  }
1001
1004
  logger_1.logger.info('Changes:');
1002
1005
  loggingQueue.forEach((log) => logger_1.logger.info(' ' + log));
@@ -1022,7 +1025,7 @@ async function runNxOrAngularMigration(root, migration, isVerbose, shouldCreateC
1022
1025
  else if (handleInstallDeps) {
1023
1026
  installDepsIfChanged();
1024
1027
  }
1025
- return changes;
1028
+ return { changes, nextSteps };
1026
1029
  }
1027
1030
  async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits = false, commitPrefix) {
1028
1031
  if (!process.env.NX_MIGRATE_SKIP_INSTALL) {
@@ -1056,7 +1059,7 @@ async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits =
1056
1059
  (shouldCreateCommits ? ', with each applied in a dedicated commit' : ''),
1057
1060
  });
1058
1061
  const migrations = (0, fileutils_1.readJsonFile)((0, path_1.join)(root, opts.runMigrations)).migrations;
1059
- const migrationsWithNoChanges = await executeMigrations(root, migrations, isVerbose, shouldCreateCommits, commitPrefix);
1062
+ const { migrationsWithNoChanges, nextSteps } = await executeMigrations(root, migrations, isVerbose, shouldCreateCommits, commitPrefix);
1060
1063
  if (migrationsWithNoChanges.length < migrations.length) {
1061
1064
  output_1.output.success({
1062
1065
  title: `Successfully finished running migrations from '${opts.runMigrations}'. This workspace is up to date!`,
@@ -1067,6 +1070,12 @@ async function runMigrations(root, opts, args, isVerbose, shouldCreateCommits =
1067
1070
  title: `No changes were made from running '${opts.runMigrations}'. This workspace is up to date!`,
1068
1071
  });
1069
1072
  }
1073
+ if (nextSteps.length > 0) {
1074
+ output_1.output.log({
1075
+ title: `Some migrations have additional information, see below.`,
1076
+ bodyLines: nextSteps.map((line) => `- ${line}`),
1077
+ });
1078
+ }
1070
1079
  }
1071
1080
  function getStringifiedPackageJsonDeps(root) {
1072
1081
  try {
@@ -1083,11 +1092,18 @@ async function runNxMigration(root, collectionPath, collection, name) {
1083
1092
  const { path: implPath, fnSymbol } = getImplementationPath(collection, collectionPath, name);
1084
1093
  const fn = require(implPath)[fnSymbol];
1085
1094
  const host = new tree_1.FsTree(root, process.env.NX_VERBOSE_LOGGING === 'true', `migration ${collection.name}:${name}`);
1086
- await fn(host, {});
1095
+ let nextSteps = await fn(host, {});
1096
+ // This accounts for migrations that mistakenly return a generator callback
1097
+ // from a migration. We've never executed these, so its not a breaking change that
1098
+ // we don't call them now... but currently shipping a migration with one wouldn't break
1099
+ // the migrate flow, so we are being cautious.
1100
+ if (!isStringArray(nextSteps)) {
1101
+ nextSteps = [];
1102
+ }
1087
1103
  host.lock();
1088
1104
  const changes = host.listChanges();
1089
1105
  (0, tree_1.flushChanges)(root, changes);
1090
- return changes;
1106
+ return { changes, nextSteps };
1091
1107
  }
1092
1108
  async function migrate(root, args, rawArgs) {
1093
1109
  await client_1.daemonClient.stop();
@@ -1230,3 +1246,9 @@ const getNgCompatLayer = (() => {
1230
1246
  return _ngCliAdapter;
1231
1247
  };
1232
1248
  })();
1249
+ function isStringArray(value) {
1250
+ if (!Array.isArray(value)) {
1251
+ return false;
1252
+ }
1253
+ return value.every((v) => typeof v === 'string');
1254
+ }
@@ -1,17 +1,18 @@
1
1
  import { NxReleaseConfiguration } from '../../config/nx-json';
2
2
  import { ChangelogOptions } from './command-object';
3
- import { NxReleaseConfig } from './config/config';
4
3
  import { Reference } from './utils/git';
5
4
  import { ReleaseVersion } from './utils/shared';
6
5
  export interface NxReleaseChangelogResult {
7
6
  workspaceChangelog?: {
8
7
  releaseVersion: ReleaseVersion;
9
8
  contents: string;
9
+ postGitTask: PostGitTask | null;
10
10
  };
11
11
  projectChangelogs?: {
12
12
  [projectName: string]: {
13
13
  releaseVersion: ReleaseVersion;
14
14
  contents: string;
15
+ postGitTask: PostGitTask | null;
15
16
  };
16
17
  };
17
18
  }
@@ -30,6 +31,6 @@ export interface ChangelogChange {
30
31
  shortHash?: string;
31
32
  revertedHashes?: string[];
32
33
  }
34
+ export type PostGitTask = (latestCommit: string) => Promise<void>;
33
35
  export declare const releaseChangelogCLIHandler: (args: ChangelogOptions) => Promise<number>;
34
36
  export declare function createAPI(overrideReleaseConfig: NxReleaseConfiguration): (args: ChangelogOptions) => Promise<NxReleaseChangelogResult>;
35
- export declare function shouldCreateGitHubRelease(changelogConfig: NxReleaseConfig['changelog']['workspaceChangelog'] | NxReleaseConfig['changelog']['projectChangelogs'] | NxReleaseConfig['groups'][number]['changelog'], createReleaseArg?: ChangelogOptions['createRelease'] | undefined): boolean;