nx 20.0.0-beta.6 → 20.0.0-beta.7
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.
- package/package.json +11 -11
- package/release/changelog-renderer/index.d.ts +60 -38
- package/release/changelog-renderer/index.js +260 -236
- package/src/command-line/add/add.js +2 -2
- package/src/command-line/nx-commands.js +31 -10
- package/src/command-line/release/changelog.d.ts +2 -2
- package/src/command-line/release/changelog.js +28 -29
- package/src/command-line/release/utils/resolve-changelog-renderer.d.ts +2 -2
- package/src/command-line/release/utils/resolve-changelog-renderer.js +3 -3
- package/src/command-line/yargs-utils/shared-options.js +2 -2
- package/src/config/nx-json.d.ts +2 -1
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/tasks-runner/cache.d.ts +2 -0
- package/src/tasks-runner/cache.js +6 -2
- package/src/tasks-runner/create-task-graph.js +4 -4
- package/src/tasks-runner/run-command.js +15 -2
- package/src/utils/command-line-utils.d.ts +3 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "20.0.0-beta.
|
3
|
+
"version": "20.0.0-beta.7",
|
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": {
|
@@ -80,16 +80,16 @@
|
|
80
80
|
}
|
81
81
|
},
|
82
82
|
"optionalDependencies": {
|
83
|
-
"@nx/nx-darwin-x64": "20.0.0-beta.
|
84
|
-
"@nx/nx-darwin-arm64": "20.0.0-beta.
|
85
|
-
"@nx/nx-linux-x64-gnu": "20.0.0-beta.
|
86
|
-
"@nx/nx-linux-x64-musl": "20.0.0-beta.
|
87
|
-
"@nx/nx-win32-x64-msvc": "20.0.0-beta.
|
88
|
-
"@nx/nx-linux-arm64-gnu": "20.0.0-beta.
|
89
|
-
"@nx/nx-linux-arm64-musl": "20.0.0-beta.
|
90
|
-
"@nx/nx-linux-arm-gnueabihf": "20.0.0-beta.
|
91
|
-
"@nx/nx-win32-arm64-msvc": "20.0.0-beta.
|
92
|
-
"@nx/nx-freebsd-x64": "20.0.0-beta.
|
83
|
+
"@nx/nx-darwin-x64": "20.0.0-beta.7",
|
84
|
+
"@nx/nx-darwin-arm64": "20.0.0-beta.7",
|
85
|
+
"@nx/nx-linux-x64-gnu": "20.0.0-beta.7",
|
86
|
+
"@nx/nx-linux-x64-musl": "20.0.0-beta.7",
|
87
|
+
"@nx/nx-win32-x64-msvc": "20.0.0-beta.7",
|
88
|
+
"@nx/nx-linux-arm64-gnu": "20.0.0-beta.7",
|
89
|
+
"@nx/nx-linux-arm64-musl": "20.0.0-beta.7",
|
90
|
+
"@nx/nx-linux-arm-gnueabihf": "20.0.0-beta.7",
|
91
|
+
"@nx/nx-win32-arm64-msvc": "20.0.0-beta.7",
|
92
|
+
"@nx/nx-freebsd-x64": "20.0.0-beta.7"
|
93
93
|
},
|
94
94
|
"nx-migrations": {
|
95
95
|
"migrations": "./migrations.json",
|
@@ -1,15 +1,13 @@
|
|
1
1
|
import { ChangelogChange } from '../../src/command-line/release/changelog';
|
2
2
|
import { NxReleaseConfig } from '../../src/command-line/release/config/config';
|
3
|
-
import {
|
4
|
-
import { GithubRepoData, RepoSlug } from '../../src/command-line/release/utils/github';
|
5
|
-
import type { ProjectGraph } from '../../src/config/project-graph';
|
3
|
+
import { GithubRepoData } from '../../src/command-line/release/utils/github';
|
6
4
|
/**
|
7
5
|
* The ChangelogRenderOptions are specific to each ChangelogRenderer implementation, and are taken
|
8
6
|
* from the user's nx.json configuration and passed as is into the ChangelogRenderer function.
|
9
7
|
*/
|
10
8
|
export type ChangelogRenderOptions = Record<string, unknown>;
|
11
9
|
/**
|
12
|
-
* When versioning projects independently and enabling `"updateDependents": "
|
10
|
+
* When versioning projects independently and enabling `"updateDependents": "auto"`, there could
|
13
11
|
* be additional dependency bump information that is not captured in the commit data, but that nevertheless
|
14
12
|
* should be included in the rendered changelog.
|
15
13
|
*/
|
@@ -17,34 +15,6 @@ export type DependencyBump = {
|
|
17
15
|
dependencyName: string;
|
18
16
|
newVersion: string;
|
19
17
|
};
|
20
|
-
/**
|
21
|
-
* A ChangelogRenderer function takes in the extracted commits and other relevant metadata
|
22
|
-
* and returns a string, or a Promise of a string of changelog contents (usually markdown).
|
23
|
-
*
|
24
|
-
* @param {Object} config The configuration object for the ChangelogRenderer
|
25
|
-
* @param {ProjectGraph} config.projectGraph The project graph for the workspace
|
26
|
-
* @param {GitCommit[]} config.commits DEPRECATED [Use 'config.changes' instead] - The collection of extracted commits to generate a changelog for
|
27
|
-
* @param {ChangelogChange[]} config.changes The collection of changes to show in the changelog
|
28
|
-
* @param {string} config.releaseVersion The version that is being released
|
29
|
-
* @param {string | null} config.project The name of specific project to generate a changelog for, or `null` if the overall workspace changelog
|
30
|
-
* @param {string | false} config.entryWhenNoChanges The (already interpolated) string to use as the changelog entry when there are no changes, or `false` if no entry should be generated
|
31
|
-
* @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
|
32
|
-
* @param {DependencyBump[]} config.dependencyBumps Optional list of additional dependency bumps that occurred as part of the release, outside of the commit data
|
33
|
-
* @param {GithubRepoData} config.repoData Resolved data for the current GitHub repository
|
34
|
-
*/
|
35
|
-
export type ChangelogRenderer = (config: {
|
36
|
-
projectGraph: ProjectGraph;
|
37
|
-
commits?: GitCommit[];
|
38
|
-
changes?: ChangelogChange[];
|
39
|
-
releaseVersion: string;
|
40
|
-
project: string | null;
|
41
|
-
entryWhenNoChanges: string | false;
|
42
|
-
changelogRenderOptions: DefaultChangelogRenderOptions;
|
43
|
-
dependencyBumps?: DependencyBump[];
|
44
|
-
repoSlug?: RepoSlug;
|
45
|
-
repoData?: GithubRepoData;
|
46
|
-
conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'] | null;
|
47
|
-
}) => Promise<string> | string;
|
48
18
|
/**
|
49
19
|
* The specific options available to the default implementation of the ChangelogRenderer that nx exports
|
50
20
|
* for the common case.
|
@@ -72,9 +42,61 @@ export interface DefaultChangelogRenderOptions extends ChangelogRenderOptions {
|
|
72
42
|
*/
|
73
43
|
versionTitleDate?: boolean;
|
74
44
|
}
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
45
|
+
export default class DefaultChangelogRenderer {
|
46
|
+
protected changes: ChangelogChange[];
|
47
|
+
protected changelogEntryVersion: string;
|
48
|
+
protected project: string | null;
|
49
|
+
protected entryWhenNoChanges: string | false;
|
50
|
+
protected changelogRenderOptions: DefaultChangelogRenderOptions;
|
51
|
+
protected isVersionPlans: boolean;
|
52
|
+
protected dependencyBumps?: DependencyBump[];
|
53
|
+
protected repoData?: GithubRepoData;
|
54
|
+
protected conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'] | null;
|
55
|
+
protected relevantChanges: ChangelogChange[];
|
56
|
+
protected breakingChanges: string[];
|
57
|
+
protected additionalChangesForAuthorsSection: ChangelogChange[];
|
58
|
+
/**
|
59
|
+
* A ChangelogRenderer class takes in the determined changes and other relevant metadata
|
60
|
+
* and returns a string, or a Promise of a string of changelog contents (usually markdown).
|
61
|
+
*
|
62
|
+
* @param {Object} config The configuration object for the ChangelogRenderer
|
63
|
+
* @param {ChangelogChange[]} config.changes The collection of changes to show in the changelog
|
64
|
+
* @param {string} config.changelogEntryVersion The version for which we are rendering the current changelog entry
|
65
|
+
* @param {string | null} config.project The name of specific project to generate a changelog entry for, or `null` if the overall workspace changelog
|
66
|
+
* @param {string | false} config.entryWhenNoChanges The (already interpolated) string to use as the changelog entry when there are no changes, or `false` if no entry should be generated
|
67
|
+
* @param {boolean} config.isVersionPlans Whether or not Nx release version plans are the source of truth for the changelog entry
|
68
|
+
* @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
|
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
|
+
* @param {NxReleaseConfig['conventionalCommits'] | null} config.conventionalCommitsConfig The configuration for conventional commits, or null if version plans are being used
|
72
|
+
*/
|
73
|
+
constructor(config: {
|
74
|
+
changes: ChangelogChange[];
|
75
|
+
changelogEntryVersion: string;
|
76
|
+
project: string | null;
|
77
|
+
entryWhenNoChanges: string | false;
|
78
|
+
isVersionPlans: boolean;
|
79
|
+
changelogRenderOptions: DefaultChangelogRenderOptions;
|
80
|
+
dependencyBumps?: DependencyBump[];
|
81
|
+
repoData?: GithubRepoData;
|
82
|
+
conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'] | null;
|
83
|
+
});
|
84
|
+
protected filterChanges(changes: ChangelogChange[], project: string | null): ChangelogChange[];
|
85
|
+
render(): Promise<string>;
|
86
|
+
protected preprocessChanges(): void;
|
87
|
+
protected shouldRenderEmptyEntry(): boolean;
|
88
|
+
protected renderEmptyEntry(): string;
|
89
|
+
protected renderVersionTitle(): string;
|
90
|
+
protected renderChangesByType(): string[];
|
91
|
+
protected hasBreakingChanges(): boolean;
|
92
|
+
protected renderBreakingChanges(): string[];
|
93
|
+
protected hasDependencyBumps(): boolean;
|
94
|
+
protected renderDependencyBumps(): string[];
|
95
|
+
protected shouldRenderAuthors(): boolean;
|
96
|
+
protected renderAuthors(): Promise<string[]>;
|
97
|
+
protected formatChange(change: ChangelogChange): string;
|
98
|
+
protected groupChangesByType(): Record<string, ChangelogChange[]>;
|
99
|
+
protected groupChangesByScope(changes: ChangelogChange[]): Record<string, ChangelogChange[]>;
|
100
|
+
protected extractBreakingChangeExplanation(message: string): string | null;
|
101
|
+
protected formatName(name?: string): string;
|
102
|
+
}
|
@@ -6,182 +6,239 @@ const github_1 = require("../../src/command-line/release/utils/github");
|
|
6
6
|
// axios types and values don't seem to match
|
7
7
|
const _axios = require("axios");
|
8
8
|
const axios = _axios;
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
9
|
+
class DefaultChangelogRenderer {
|
10
|
+
/**
|
11
|
+
* A ChangelogRenderer class takes in the determined changes and other relevant metadata
|
12
|
+
* and returns a string, or a Promise of a string of changelog contents (usually markdown).
|
13
|
+
*
|
14
|
+
* @param {Object} config The configuration object for the ChangelogRenderer
|
15
|
+
* @param {ChangelogChange[]} config.changes The collection of changes to show in the changelog
|
16
|
+
* @param {string} config.changelogEntryVersion The version for which we are rendering the current changelog entry
|
17
|
+
* @param {string | null} config.project The name of specific project to generate a changelog entry for, or `null` if the overall workspace changelog
|
18
|
+
* @param {string | false} config.entryWhenNoChanges The (already interpolated) string to use as the changelog entry when there are no changes, or `false` if no entry should be generated
|
19
|
+
* @param {boolean} config.isVersionPlans Whether or not Nx release version plans are the source of truth for the changelog entry
|
20
|
+
* @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
|
21
|
+
* @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
|
+
* @param {NxReleaseConfig['conventionalCommits'] | null} config.conventionalCommitsConfig The configuration for conventional commits, or null if version plans are being used
|
24
|
+
*/
|
25
|
+
constructor(config) {
|
26
|
+
this.changes = this.filterChanges(config.changes, config.project);
|
27
|
+
this.changelogEntryVersion = config.changelogEntryVersion;
|
28
|
+
this.project = config.project;
|
29
|
+
this.entryWhenNoChanges = config.entryWhenNoChanges;
|
30
|
+
this.isVersionPlans = config.isVersionPlans;
|
31
|
+
this.changelogRenderOptions = config.changelogRenderOptions;
|
32
|
+
this.dependencyBumps = config.dependencyBumps;
|
33
|
+
this.repoData = config.repoData;
|
34
|
+
this.conventionalCommitsConfig = config.conventionalCommitsConfig;
|
35
|
+
this.relevantChanges = [];
|
36
|
+
this.breakingChanges = [];
|
37
|
+
this.additionalChangesForAuthorsSection = [];
|
38
|
+
}
|
39
|
+
filterChanges(changes, project) {
|
40
|
+
if (project === null) {
|
41
|
+
return changes;
|
25
42
|
}
|
43
|
+
return changes.filter((c) => c.affectedProjects &&
|
44
|
+
(c.affectedProjects === '*' || c.affectedProjects.includes(project)));
|
26
45
|
}
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
// but keep track of the changes for the purposes of the authors section
|
44
|
-
// TODO(v20): Clean this abstraction up as part of the larger overall refactor of changelog rendering
|
45
|
-
for (let i = 0; i < relevantChanges.length; i++) {
|
46
|
-
if (relevantChanges[i].isBreaking) {
|
47
|
-
const change = relevantChanges[i];
|
48
|
-
additionalChangesForAuthorsSection.push(change);
|
49
|
-
const line = formatChange(change, changelogRenderOptions, isVersionPlans, repoData);
|
50
|
-
breakingChanges.push(line);
|
51
|
-
relevantChanges.splice(i, 1);
|
52
|
-
}
|
46
|
+
async render() {
|
47
|
+
const sections = [];
|
48
|
+
this.preprocessChanges();
|
49
|
+
if (this.shouldRenderEmptyEntry()) {
|
50
|
+
return this.renderEmptyEntry();
|
51
|
+
}
|
52
|
+
sections.push([this.renderVersionTitle()]);
|
53
|
+
const changesByType = this.renderChangesByType();
|
54
|
+
if (changesByType.length > 0) {
|
55
|
+
sections.push(changesByType);
|
56
|
+
}
|
57
|
+
if (this.hasBreakingChanges()) {
|
58
|
+
sections.push(this.renderBreakingChanges());
|
59
|
+
}
|
60
|
+
if (this.hasDependencyBumps()) {
|
61
|
+
sections.push(this.renderDependencyBumps());
|
53
62
|
}
|
63
|
+
if (this.shouldRenderAuthors()) {
|
64
|
+
sections.push(await this.renderAuthors());
|
65
|
+
}
|
66
|
+
// Join sections with double newlines, and trim any extra whitespace
|
67
|
+
return sections
|
68
|
+
.filter((section) => section.length > 0)
|
69
|
+
.map((section) => section.join('\n').trim())
|
70
|
+
.join('\n\n')
|
71
|
+
.trim();
|
54
72
|
}
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
preprocessChanges() {
|
74
|
+
this.relevantChanges = [...this.changes];
|
75
|
+
this.breakingChanges = [];
|
76
|
+
this.additionalChangesForAuthorsSection = [];
|
77
|
+
// Filter out reverted changes
|
78
|
+
for (let i = this.relevantChanges.length - 1; i >= 0; i--) {
|
79
|
+
const change = this.relevantChanges[i];
|
80
|
+
if (change.type === 'revert' && change.revertedHashes) {
|
81
|
+
for (const revertedHash of change.revertedHashes) {
|
82
|
+
const revertedCommitIndex = this.relevantChanges.findIndex((c) => c.shortHash && revertedHash.startsWith(c.shortHash));
|
83
|
+
if (revertedCommitIndex !== -1) {
|
84
|
+
this.relevantChanges.splice(revertedCommitIndex, 1);
|
85
|
+
this.relevantChanges.splice(i, 1);
|
86
|
+
i--;
|
87
|
+
break;
|
88
|
+
}
|
89
|
+
}
|
70
90
|
}
|
71
|
-
return markdownLines.join('\n').trim();
|
72
91
|
}
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
92
|
+
if (this.isVersionPlans) {
|
93
|
+
this.conventionalCommitsConfig = {
|
94
|
+
types: {
|
95
|
+
feat: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG.types.feat,
|
96
|
+
fix: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG.types.fix,
|
97
|
+
},
|
98
|
+
};
|
99
|
+
for (let i = this.relevantChanges.length - 1; i >= 0; i--) {
|
100
|
+
if (this.relevantChanges[i].isBreaking) {
|
101
|
+
const change = this.relevantChanges[i];
|
102
|
+
this.additionalChangesForAuthorsSection.push(change);
|
103
|
+
const line = this.formatChange(change);
|
104
|
+
this.breakingChanges.push(line);
|
105
|
+
this.relevantChanges.splice(i, 1);
|
106
|
+
}
|
79
107
|
}
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
const scopesSortedAlphabetically = Object.keys(changesGroupedByScope).sort();
|
89
|
-
for (const scope of scopesSortedAlphabetically) {
|
90
|
-
const changes = changesGroupedByScope[scope];
|
91
|
-
for (const change of changes) {
|
92
|
-
const line = formatChange(change, changelogRenderOptions, isVersionPlans, repoData);
|
93
|
-
markdownLines.push(line);
|
94
|
-
if (change.isBreaking) {
|
95
|
-
const breakingChangeExplanation = extractBreakingChangeExplanation(change.body);
|
96
|
-
breakingChanges.push(breakingChangeExplanation
|
97
|
-
? `- ${change.scope ? `**${change.scope.trim()}:** ` : ''}${breakingChangeExplanation}`
|
98
|
-
: line);
|
99
|
-
}
|
108
|
+
}
|
109
|
+
else {
|
110
|
+
for (const change of this.relevantChanges) {
|
111
|
+
if (change.isBreaking) {
|
112
|
+
const breakingChangeExplanation = this.extractBreakingChangeExplanation(change.body);
|
113
|
+
this.breakingChanges.push(breakingChangeExplanation
|
114
|
+
? `- ${change.scope ? `**${change.scope.trim()}:** ` : ''}${breakingChangeExplanation}`
|
115
|
+
: this.formatChange(change));
|
100
116
|
}
|
101
117
|
}
|
102
118
|
}
|
103
119
|
}
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
markdownLines.push('', `${createVersionTitle(releaseVersion, changelogRenderOptions)}\n\n${entryWhenNoChanges}`, '');
|
120
|
-
}
|
121
|
-
return markdownLines.join('\n').trim();
|
120
|
+
shouldRenderEmptyEntry() {
|
121
|
+
return (this.relevantChanges.length === 0 &&
|
122
|
+
this.breakingChanges.length === 0 &&
|
123
|
+
!this.hasDependencyBumps());
|
124
|
+
}
|
125
|
+
renderEmptyEntry() {
|
126
|
+
if (this.hasDependencyBumps()) {
|
127
|
+
return [
|
128
|
+
this.renderVersionTitle(),
|
129
|
+
'',
|
130
|
+
...this.renderDependencyBumps(),
|
131
|
+
].join('\n');
|
132
|
+
}
|
133
|
+
else if (this.entryWhenNoChanges) {
|
134
|
+
return `${this.renderVersionTitle()}\n\n${this.entryWhenNoChanges}`;
|
122
135
|
}
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
136
|
+
return '';
|
137
|
+
}
|
138
|
+
renderVersionTitle() {
|
139
|
+
const isMajorVersion = `${(0, semver_1.major)(this.changelogEntryVersion)}.0.0` ===
|
140
|
+
this.changelogEntryVersion.replace(/^v/, '');
|
141
|
+
let maybeDateStr = '';
|
142
|
+
if (this.changelogRenderOptions.versionTitleDate) {
|
143
|
+
const dateStr = new Date().toISOString().slice(0, 10);
|
144
|
+
maybeDateStr = ` (${dateStr})`;
|
145
|
+
}
|
146
|
+
return isMajorVersion
|
147
|
+
? `# ${this.changelogEntryVersion}${maybeDateStr}`
|
148
|
+
: `## ${this.changelogEntryVersion}${maybeDateStr}`;
|
149
|
+
}
|
150
|
+
renderChangesByType() {
|
151
|
+
const markdownLines = [];
|
152
|
+
const typeGroups = this.groupChangesByType();
|
153
|
+
const changeTypes = this.conventionalCommitsConfig.types;
|
127
154
|
for (const type of Object.keys(changeTypes)) {
|
128
155
|
const group = typeGroups[type];
|
129
156
|
if (!group || group.length === 0) {
|
130
157
|
continue;
|
131
158
|
}
|
132
159
|
markdownLines.push('', `### ${changeTypes[type].changelog.title}`, '');
|
133
|
-
|
134
|
-
|
135
|
-
const
|
136
|
-
|
137
|
-
|
138
|
-
const
|
139
|
-
|
140
|
-
|
141
|
-
|
160
|
+
if (this.project === null) {
|
161
|
+
const changesGroupedByScope = this.groupChangesByScope(group);
|
162
|
+
const scopesSortedAlphabetically = Object.keys(changesGroupedByScope).sort();
|
163
|
+
for (const scope of scopesSortedAlphabetically) {
|
164
|
+
const changes = changesGroupedByScope[scope];
|
165
|
+
for (const change of changes.reverse()) {
|
166
|
+
const line = this.formatChange(change);
|
167
|
+
markdownLines.push(line);
|
168
|
+
if (change.isBreaking && !this.isVersionPlans) {
|
169
|
+
const breakingChangeExplanation = this.extractBreakingChangeExplanation(change.body);
|
170
|
+
this.breakingChanges.push(breakingChangeExplanation
|
171
|
+
? `- ${change.scope ? `**${change.scope.trim()}:** ` : ''}${breakingChangeExplanation}`
|
172
|
+
: line);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
else {
|
178
|
+
// For project-specific changelogs, maintain the original order
|
179
|
+
for (const change of group) {
|
180
|
+
const line = this.formatChange(change);
|
181
|
+
markdownLines.push(line);
|
182
|
+
if (change.isBreaking && !this.isVersionPlans) {
|
183
|
+
const breakingChangeExplanation = this.extractBreakingChangeExplanation(change.body);
|
184
|
+
this.breakingChanges.push(breakingChangeExplanation
|
185
|
+
? `- ${change.scope ? `**${change.scope.trim()}:** ` : ''}${breakingChangeExplanation}`
|
186
|
+
: line);
|
187
|
+
}
|
142
188
|
}
|
143
189
|
}
|
144
190
|
}
|
191
|
+
return markdownLines;
|
192
|
+
}
|
193
|
+
hasBreakingChanges() {
|
194
|
+
return this.breakingChanges.length > 0;
|
145
195
|
}
|
146
|
-
|
147
|
-
|
196
|
+
renderBreakingChanges() {
|
197
|
+
const uniqueBreakingChanges = Array.from(new Set(this.breakingChanges));
|
198
|
+
return ['### ⚠️ Breaking Changes', '', ...uniqueBreakingChanges];
|
148
199
|
}
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
200
|
+
hasDependencyBumps() {
|
201
|
+
return this.dependencyBumps && this.dependencyBumps.length > 0;
|
202
|
+
}
|
203
|
+
renderDependencyBumps() {
|
204
|
+
const markdownLines = ['', '### 🧱 Updated Dependencies', ''];
|
205
|
+
this.dependencyBumps.forEach(({ dependencyName, newVersion }) => {
|
206
|
+
markdownLines.push(`- Updated ${dependencyName} to ${newVersion}`);
|
155
207
|
});
|
208
|
+
return markdownLines;
|
209
|
+
}
|
210
|
+
shouldRenderAuthors() {
|
211
|
+
return this.changelogRenderOptions.authors;
|
156
212
|
}
|
157
|
-
|
213
|
+
async renderAuthors() {
|
214
|
+
const markdownLines = [];
|
158
215
|
const _authors = new Map();
|
159
216
|
for (const change of [
|
160
|
-
...relevantChanges,
|
161
|
-
...additionalChangesForAuthorsSection,
|
217
|
+
...this.relevantChanges,
|
218
|
+
...this.additionalChangesForAuthorsSection,
|
162
219
|
]) {
|
163
|
-
if (!change.
|
220
|
+
if (!change.authors) {
|
164
221
|
continue;
|
165
222
|
}
|
166
|
-
const
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
223
|
+
for (const author of change.authors) {
|
224
|
+
const name = this.formatName(author.name);
|
225
|
+
if (!name || name.includes('[bot]')) {
|
226
|
+
continue;
|
227
|
+
}
|
228
|
+
if (_authors.has(name)) {
|
229
|
+
const entry = _authors.get(name);
|
230
|
+
entry.email.add(author.email);
|
231
|
+
}
|
232
|
+
else {
|
233
|
+
_authors.set(name, { email: new Set([author.email]) });
|
234
|
+
}
|
176
235
|
}
|
177
236
|
}
|
178
|
-
|
179
|
-
|
237
|
+
if (this.repoData &&
|
238
|
+
this.changelogRenderOptions.mapAuthorsToGitHubUsernames) {
|
180
239
|
await Promise.all([..._authors.keys()].map(async (authorName) => {
|
181
240
|
const meta = _authors.get(authorName);
|
182
241
|
for (const email of meta.email) {
|
183
|
-
// For these pseudo-anonymized emails we can just extract the Github username from before the @
|
184
|
-
// It could either be in the format: username@ or github_id+username@
|
185
242
|
if (email.endsWith('@users.noreply.github.com')) {
|
186
243
|
const match = email.match(/^(\d+\+)?([^@]+)@users\.noreply\.github\.com$/);
|
187
244
|
if (match && match[2]) {
|
@@ -189,7 +246,6 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
189
246
|
break;
|
190
247
|
}
|
191
248
|
}
|
192
|
-
// Look up any other emails against the ungh.cc API
|
193
249
|
const { data } = await axios
|
194
250
|
.get(`https://ungh.cc/users/find/${email}`)
|
195
251
|
.catch(() => ({ data: { user: null } }));
|
@@ -206,110 +262,78 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
206
262
|
}));
|
207
263
|
if (authors.length > 0) {
|
208
264
|
markdownLines.push('', '### ' + '❤️ Thank You', '', ...authors
|
209
|
-
// Sort the contributors by name
|
210
265
|
.sort((a, b) => a.name.localeCompare(b.name))
|
211
266
|
.map((i) => {
|
212
|
-
// Tag the author's Github username if we were able to resolve it so that Github adds them as a contributor
|
213
267
|
const github = i.github ? ` @${i.github}` : '';
|
214
268
|
return `- ${i.name}${github}`;
|
215
269
|
}));
|
216
270
|
}
|
271
|
+
return markdownLines;
|
217
272
|
}
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
}
|
234
|
-
|
235
|
-
|
236
|
-
.
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
groups[item[key]] = groups[item[key]] || [];
|
244
|
-
groups[item[key]].push(item);
|
245
|
-
}
|
246
|
-
return groups;
|
247
|
-
}
|
248
|
-
function formatChange(change, changelogRenderOptions, isVersionPlans, repoData) {
|
249
|
-
let description = change.description;
|
250
|
-
let extraLines = [];
|
251
|
-
let extraLinesStr = '';
|
252
|
-
if (description.includes('\n')) {
|
253
|
-
[description, ...extraLines] = description.split('\n');
|
254
|
-
// Align the extra lines with the start of the description for better readability
|
255
|
-
const indentation = ' ';
|
256
|
-
extraLinesStr = extraLines
|
257
|
-
.filter((l) => l.trim().length > 0)
|
258
|
-
.map((l) => `${indentation}${l}`)
|
259
|
-
.join('\n');
|
260
|
-
}
|
261
|
-
/**
|
262
|
-
* In version plans changelogs:
|
263
|
-
* - don't repeat the breaking change icon
|
264
|
-
* - don't render the scope
|
265
|
-
*/
|
266
|
-
let changeLine = '- ' +
|
267
|
-
(!isVersionPlans && change.isBreaking ? '⚠️ ' : '') +
|
268
|
-
(!isVersionPlans && change.scope ? `**${change.scope.trim()}:** ` : '') +
|
269
|
-
description;
|
270
|
-
if (repoData && changelogRenderOptions.commitReferences) {
|
271
|
-
changeLine += (0, github_1.formatReferences)(change.githubReferences, repoData);
|
272
|
-
}
|
273
|
-
if (extraLinesStr) {
|
274
|
-
changeLine += '\n\n' + extraLinesStr;
|
275
|
-
}
|
276
|
-
return changeLine;
|
277
|
-
}
|
278
|
-
/**
|
279
|
-
* It is common to add further information about a breaking change in the commit body,
|
280
|
-
* and it is naturally that information that should be included in the BREAKING CHANGES
|
281
|
-
* section of changelog, rather than repeating the commit title/description.
|
282
|
-
*/
|
283
|
-
function extractBreakingChangeExplanation(message) {
|
284
|
-
if (!message) {
|
285
|
-
return null;
|
273
|
+
formatChange(change) {
|
274
|
+
let description = change.description;
|
275
|
+
let extraLines = [];
|
276
|
+
let extraLinesStr = '';
|
277
|
+
if (description.includes('\n')) {
|
278
|
+
[description, ...extraLines] = description.split('\n');
|
279
|
+
const indentation = ' ';
|
280
|
+
extraLinesStr = extraLines
|
281
|
+
.filter((l) => l.trim().length > 0)
|
282
|
+
.map((l) => `${indentation}${l}`)
|
283
|
+
.join('\n');
|
284
|
+
}
|
285
|
+
let changeLine = '- ' +
|
286
|
+
(!this.isVersionPlans && change.isBreaking ? '⚠️ ' : '') +
|
287
|
+
(!this.isVersionPlans && change.scope
|
288
|
+
? `**${change.scope.trim()}:** `
|
289
|
+
: '') +
|
290
|
+
description;
|
291
|
+
if (this.repoData && this.changelogRenderOptions.commitReferences) {
|
292
|
+
changeLine += (0, github_1.formatReferences)(change.githubReferences, this.repoData);
|
293
|
+
}
|
294
|
+
if (extraLinesStr) {
|
295
|
+
changeLine += '\n\n' + extraLinesStr;
|
296
|
+
}
|
297
|
+
return changeLine;
|
286
298
|
}
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
299
|
+
groupChangesByType() {
|
300
|
+
const typeGroups = {};
|
301
|
+
for (const change of this.relevantChanges) {
|
302
|
+
typeGroups[change.type] = typeGroups[change.type] || [];
|
303
|
+
typeGroups[change.type].push(change);
|
304
|
+
}
|
305
|
+
return typeGroups;
|
292
306
|
}
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
307
|
+
groupChangesByScope(changes) {
|
308
|
+
const scopeGroups = {};
|
309
|
+
for (const change of changes) {
|
310
|
+
const scope = change.scope || '';
|
311
|
+
scopeGroups[scope] = scopeGroups[scope] || [];
|
312
|
+
scopeGroups[scope].push(change);
|
313
|
+
}
|
314
|
+
return scopeGroups;
|
298
315
|
}
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
const
|
309
|
-
|
316
|
+
extractBreakingChangeExplanation(message) {
|
317
|
+
if (!message) {
|
318
|
+
return null;
|
319
|
+
}
|
320
|
+
const breakingChangeIdentifier = 'BREAKING CHANGE:';
|
321
|
+
const startIndex = message.indexOf(breakingChangeIdentifier);
|
322
|
+
if (startIndex === -1) {
|
323
|
+
return null;
|
324
|
+
}
|
325
|
+
const startOfBreakingChange = startIndex + breakingChangeIdentifier.length;
|
326
|
+
const endOfBreakingChange = message.indexOf('\n', startOfBreakingChange);
|
327
|
+
if (endOfBreakingChange === -1) {
|
328
|
+
return message.substring(startOfBreakingChange).trim();
|
329
|
+
}
|
330
|
+
return message.substring(startOfBreakingChange, endOfBreakingChange).trim();
|
310
331
|
}
|
311
|
-
|
312
|
-
return
|
332
|
+
formatName(name = '') {
|
333
|
+
return name
|
334
|
+
.split(' ')
|
335
|
+
.map((p) => p.trim())
|
336
|
+
.join(' ');
|
313
337
|
}
|
314
|
-
return `## ${version}${maybeDateStr}`;
|
315
338
|
}
|
339
|
+
exports.default = DefaultChangelogRenderer;
|
@@ -103,8 +103,8 @@ async function initializePlugin(pkgName, options, nxJson) {
|
|
103
103
|
if (options.__overrides_unparsed__.length) {
|
104
104
|
args.push(...options.__overrides_unparsed__);
|
105
105
|
}
|
106
|
-
|
107
|
-
|
106
|
+
(0, child_process_2.runNxSync)(`g ${pkgName}:${initGenerator} ${args.join(' ')}`, {
|
107
|
+
stdio: [0, 1, 2],
|
108
108
|
});
|
109
109
|
}
|
110
110
|
catch (e) {
|
@@ -29,6 +29,7 @@ const command_object_23 = require("./login/command-object");
|
|
29
29
|
const command_object_24 = require("./logout/command-object");
|
30
30
|
const command_objects_1 = require("./deprecated/command-objects");
|
31
31
|
const command_object_25 = require("./sync/command-object");
|
32
|
+
const output_1 = require("../utils/output");
|
32
33
|
// Ensure that the output takes up the available width of the terminal.
|
33
34
|
yargs.wrap(yargs.terminalWidth());
|
34
35
|
exports.parserConfiguration = {
|
@@ -82,26 +83,46 @@ exports.commandsObject = yargs
|
|
82
83
|
.command(command_object_23.yargsLoginCommand)
|
83
84
|
.command(command_object_24.yargsLogoutCommand)
|
84
85
|
.command(resolveConformanceCommandObject())
|
86
|
+
.command(resolveConformanceCheckCommandObject())
|
85
87
|
.scriptName('nx')
|
86
88
|
.help()
|
87
89
|
// NOTE: we handle --version in nx.ts, this just tells yargs that the option exists
|
88
90
|
// so that it shows up in help. The default yargs implementation of --version is not
|
89
91
|
// hit, as the implementation in nx.ts is hit first and calls process.exit(0).
|
90
92
|
.version();
|
93
|
+
function createMissingConformanceCommand(command) {
|
94
|
+
return {
|
95
|
+
command,
|
96
|
+
// Hide from --help output in the common case of not having the plugin installed
|
97
|
+
describe: false,
|
98
|
+
handler: () => {
|
99
|
+
output_1.output.error({
|
100
|
+
title: `${command} is not available`,
|
101
|
+
bodyLines: [
|
102
|
+
`In order to use the \`nx ${command}\` command you must have an active Powerpack license and the \`@nx/powerpack-conformance\` plugin installed.`,
|
103
|
+
'',
|
104
|
+
'To learn more, visit https://nx.dev/features/powerpack/conformance',
|
105
|
+
],
|
106
|
+
});
|
107
|
+
process.exit(1);
|
108
|
+
},
|
109
|
+
};
|
110
|
+
}
|
91
111
|
function resolveConformanceCommandObject() {
|
92
112
|
try {
|
93
113
|
const { yargsConformanceCommand } = require('@nx/powerpack-conformance');
|
94
114
|
return yargsConformanceCommand;
|
95
115
|
}
|
96
|
-
catch
|
97
|
-
return
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
116
|
+
catch {
|
117
|
+
return createMissingConformanceCommand('conformance');
|
118
|
+
}
|
119
|
+
}
|
120
|
+
function resolveConformanceCheckCommandObject() {
|
121
|
+
try {
|
122
|
+
const { yargsConformanceCheckCommand, } = require('@nx/powerpack-conformance');
|
123
|
+
return yargsConformanceCheckCommand;
|
124
|
+
}
|
125
|
+
catch {
|
126
|
+
return createMissingConformanceCommand('conformance:check');
|
106
127
|
}
|
107
128
|
}
|
@@ -22,10 +22,10 @@ export interface ChangelogChange {
|
|
22
22
|
body?: string;
|
23
23
|
isBreaking?: boolean;
|
24
24
|
githubReferences?: Reference[];
|
25
|
-
|
25
|
+
authors?: {
|
26
26
|
name: string;
|
27
27
|
email: string;
|
28
|
-
};
|
28
|
+
}[];
|
29
29
|
shortHash?: string;
|
30
30
|
revertedHashes?: string[];
|
31
31
|
}
|
@@ -162,7 +162,8 @@ function createAPI(overrideReleaseConfig) {
|
|
162
162
|
body: '',
|
163
163
|
isBreaking: releaseType.isBreaking,
|
164
164
|
githubReferences,
|
165
|
-
|
165
|
+
// TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
|
166
|
+
authors: [author],
|
166
167
|
affectedProjects: '*',
|
167
168
|
}
|
168
169
|
: vp.triggeredByProjects.map((project) => {
|
@@ -173,7 +174,8 @@ function createAPI(overrideReleaseConfig) {
|
|
173
174
|
body: '',
|
174
175
|
isBreaking: releaseType.isBreaking,
|
175
176
|
githubReferences,
|
176
|
-
|
177
|
+
// TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
|
178
|
+
authors: [author],
|
177
179
|
affectedProjects: [project],
|
178
180
|
};
|
179
181
|
});
|
@@ -209,7 +211,7 @@ function createAPI(overrideReleaseConfig) {
|
|
209
211
|
body: c.body,
|
210
212
|
isBreaking: c.isBreaking,
|
211
213
|
githubReferences: c.references,
|
212
|
-
|
214
|
+
authors: [c.author],
|
213
215
|
shortHash: c.shortHash,
|
214
216
|
revertedHashes: c.revertedHashes,
|
215
217
|
affectedProjects: '*',
|
@@ -313,13 +315,14 @@ function createAPI(overrideReleaseConfig) {
|
|
313
315
|
}
|
314
316
|
const releaseType = versionPlanSemverReleaseTypeToChangelogType(bumpForProject);
|
315
317
|
let githubReferences = [];
|
316
|
-
let
|
318
|
+
let authors = [];
|
317
319
|
const parsedCommit = vp.commit
|
318
320
|
? (0, git_1.parseGitCommit)(vp.commit, true)
|
319
321
|
: null;
|
320
322
|
if (parsedCommit) {
|
321
323
|
githubReferences = parsedCommit.references;
|
322
|
-
|
324
|
+
// TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
|
325
|
+
authors = [parsedCommit.author];
|
323
326
|
}
|
324
327
|
return {
|
325
328
|
type: releaseType.type,
|
@@ -329,7 +332,7 @@ function createAPI(overrideReleaseConfig) {
|
|
329
332
|
isBreaking: releaseType.isBreaking,
|
330
333
|
affectedProjects: Object.keys(vp.projectVersionBumps),
|
331
334
|
githubReferences,
|
332
|
-
|
335
|
+
authors,
|
333
336
|
};
|
334
337
|
})
|
335
338
|
.filter(Boolean);
|
@@ -365,7 +368,8 @@ function createAPI(overrideReleaseConfig) {
|
|
365
368
|
body: c.body,
|
366
369
|
isBreaking: c.isBreaking,
|
367
370
|
githubReferences: c.references,
|
368
|
-
|
371
|
+
// TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
|
372
|
+
authors: [c.author],
|
369
373
|
shortHash: c.shortHash,
|
370
374
|
revertedHashes: c.revertedHashes,
|
371
375
|
affectedProjects: commitChangesNonProjectFiles(c, fileMap.nonProjectFiles)
|
@@ -376,15 +380,12 @@ function createAPI(overrideReleaseConfig) {
|
|
376
380
|
const projectChangelogs = await generateChangelogForProjects({
|
377
381
|
tree,
|
378
382
|
args,
|
379
|
-
projectGraph,
|
380
383
|
changes,
|
381
384
|
projectsVersionData,
|
382
385
|
releaseGroup,
|
383
386
|
projects: [project],
|
384
387
|
nxReleaseConfig,
|
385
388
|
projectToAdditionalDependencyBumps,
|
386
|
-
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
387
|
-
commits: filterHiddenCommits(commits, nxReleaseConfig.conventionalCommits),
|
388
389
|
});
|
389
390
|
let hasPushed = false;
|
390
391
|
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
@@ -436,7 +437,8 @@ function createAPI(overrideReleaseConfig) {
|
|
436
437
|
body: '',
|
437
438
|
isBreaking: releaseType.isBreaking,
|
438
439
|
githubReferences,
|
439
|
-
|
440
|
+
// TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
|
441
|
+
authors: [author],
|
440
442
|
affectedProjects: '*',
|
441
443
|
}
|
442
444
|
: vp.triggeredByProjects.map((project) => {
|
@@ -447,7 +449,8 @@ function createAPI(overrideReleaseConfig) {
|
|
447
449
|
body: '',
|
448
450
|
isBreaking: releaseType.isBreaking,
|
449
451
|
githubReferences,
|
450
|
-
|
452
|
+
// TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
|
453
|
+
authors: [author],
|
451
454
|
affectedProjects: [project],
|
452
455
|
};
|
453
456
|
});
|
@@ -482,7 +485,8 @@ function createAPI(overrideReleaseConfig) {
|
|
482
485
|
body: c.body,
|
483
486
|
isBreaking: c.isBreaking,
|
484
487
|
githubReferences: c.references,
|
485
|
-
|
488
|
+
// TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
|
489
|
+
authors: [c.author],
|
486
490
|
shortHash: c.shortHash,
|
487
491
|
revertedHashes: c.revertedHashes,
|
488
492
|
affectedProjects: commitChangesNonProjectFiles(c, fileMap.nonProjectFiles)
|
@@ -493,15 +497,12 @@ function createAPI(overrideReleaseConfig) {
|
|
493
497
|
const projectChangelogs = await generateChangelogForProjects({
|
494
498
|
tree,
|
495
499
|
args,
|
496
|
-
projectGraph,
|
497
500
|
changes,
|
498
501
|
projectsVersionData,
|
499
502
|
releaseGroup,
|
500
503
|
projects: projectNodes,
|
501
504
|
nxReleaseConfig,
|
502
505
|
projectToAdditionalDependencyBumps,
|
503
|
-
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
504
|
-
commits: filterHiddenCommits(commits, nxReleaseConfig.conventionalCommits),
|
505
506
|
});
|
506
507
|
let hasPushed = false;
|
507
508
|
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
@@ -716,7 +717,7 @@ async function generateChangelogForWorkspace({ tree, args, projectGraph, nxRelea
|
|
716
717
|
const interactive = args.interactive === 'all' || args.interactive === 'workspace';
|
717
718
|
const dryRun = !!args.dryRun;
|
718
719
|
const gitRemote = args.gitRemote;
|
719
|
-
const
|
720
|
+
const ChangelogRendererClass = (0, resolve_changelog_renderer_1.resolveChangelogRenderer)(config.renderer);
|
720
721
|
let interpolatedTreePath = config.file || '';
|
721
722
|
if (interpolatedTreePath) {
|
722
723
|
interpolatedTreePath = (0, utils_1.interpolate)(interpolatedTreePath, {
|
@@ -736,18 +737,17 @@ async function generateChangelogForWorkspace({ tree, args, projectGraph, nxRelea
|
|
736
737
|
});
|
737
738
|
}
|
738
739
|
const githubRepoData = (0, github_1.getGitHubRepoData)(gitRemote, config.createRelease);
|
739
|
-
|
740
|
-
projectGraph,
|
740
|
+
const changelogRenderer = new ChangelogRendererClass({
|
741
741
|
changes,
|
742
|
-
|
743
|
-
releaseVersion: releaseVersion.rawVersion,
|
742
|
+
changelogEntryVersion: releaseVersion.rawVersion,
|
744
743
|
project: null,
|
745
|
-
|
744
|
+
isVersionPlans: false,
|
746
745
|
repoData: githubRepoData,
|
747
746
|
entryWhenNoChanges: config.entryWhenNoChanges,
|
748
747
|
changelogRenderOptions: config.renderOptions,
|
749
748
|
conventionalCommitsConfig: nxReleaseConfig.conventionalCommits,
|
750
749
|
});
|
750
|
+
let contents = await changelogRenderer.render();
|
751
751
|
/**
|
752
752
|
* If interactive mode, make the changelog contents available for the user to modify in their editor of choice,
|
753
753
|
* in a similar style to git interactive rebases/merges.
|
@@ -789,7 +789,7 @@ async function generateChangelogForWorkspace({ tree, args, projectGraph, nxRelea
|
|
789
789
|
contents,
|
790
790
|
};
|
791
791
|
}
|
792
|
-
async function generateChangelogForProjects({ tree, args,
|
792
|
+
async function generateChangelogForProjects({ tree, args, changes, projectsVersionData, releaseGroup, projects, nxReleaseConfig, projectToAdditionalDependencyBumps, }) {
|
793
793
|
const config = releaseGroup.changelog;
|
794
794
|
// The entire feature is disabled at the release group level, exit early
|
795
795
|
if (config === false) {
|
@@ -799,7 +799,7 @@ async function generateChangelogForProjects({ tree, args, projectGraph, changes,
|
|
799
799
|
const interactive = args.interactive === 'all' || args.interactive === 'projects';
|
800
800
|
const dryRun = !!args.dryRun;
|
801
801
|
const gitRemote = args.gitRemote;
|
802
|
-
const
|
802
|
+
const ChangelogRendererClass = (0, resolve_changelog_renderer_1.resolveChangelogRenderer)(config.renderer);
|
803
803
|
const projectChangelogs = {};
|
804
804
|
for (const project of projects) {
|
805
805
|
let interpolatedTreePath = config.file || '';
|
@@ -829,13 +829,10 @@ async function generateChangelogForProjects({ tree, args, projectGraph, changes,
|
|
829
829
|
});
|
830
830
|
}
|
831
831
|
const githubRepoData = (0, github_1.getGitHubRepoData)(gitRemote, config.createRelease);
|
832
|
-
|
833
|
-
projectGraph,
|
832
|
+
const changelogRenderer = new ChangelogRendererClass({
|
834
833
|
changes,
|
835
|
-
|
836
|
-
releaseVersion: releaseVersion.rawVersion,
|
834
|
+
changelogEntryVersion: releaseVersion.rawVersion,
|
837
835
|
project: project.name,
|
838
|
-
repoSlug: githubRepoData?.slug,
|
839
836
|
repoData: githubRepoData,
|
840
837
|
entryWhenNoChanges: typeof config.entryWhenNoChanges === 'string'
|
841
838
|
? (0, utils_1.interpolate)(config.entryWhenNoChanges, {
|
@@ -845,11 +842,13 @@ async function generateChangelogForProjects({ tree, args, projectGraph, changes,
|
|
845
842
|
})
|
846
843
|
: false,
|
847
844
|
changelogRenderOptions: config.renderOptions,
|
845
|
+
isVersionPlans: !!releaseGroup.versionPlans,
|
848
846
|
conventionalCommitsConfig: releaseGroup.versionPlans
|
849
847
|
? null
|
850
848
|
: nxReleaseConfig.conventionalCommits,
|
851
849
|
dependencyBumps: projectToAdditionalDependencyBumps.get(project.name),
|
852
850
|
});
|
851
|
+
let contents = await changelogRenderer.render();
|
853
852
|
/**
|
854
853
|
* If interactive mode, make the changelog contents available for the user to modify in their editor of choice,
|
855
854
|
* in a similar style to git interactive rebases/merges.
|
@@ -1,2 +1,2 @@
|
|
1
|
-
import type
|
2
|
-
export declare function resolveChangelogRenderer(changelogRendererPath: string): ChangelogRenderer;
|
1
|
+
import type ChangelogRenderer from '../../../../release/changelog-renderer';
|
2
|
+
export declare function resolveChangelogRenderer(changelogRendererPath: string): typeof ChangelogRenderer;
|
@@ -10,7 +10,7 @@ function resolveChangelogRenderer(changelogRendererPath) {
|
|
10
10
|
workspaceRoot: workspace_root_1.workspaceRoot,
|
11
11
|
});
|
12
12
|
// Try and load the provided (or default) changelog renderer
|
13
|
-
let
|
13
|
+
let ChangelogRendererClass;
|
14
14
|
let cleanupTranspiler = () => { };
|
15
15
|
try {
|
16
16
|
const rootTsconfigPath = (0, typescript_1.getRootTsConfigPath)();
|
@@ -18,7 +18,7 @@ function resolveChangelogRenderer(changelogRendererPath) {
|
|
18
18
|
cleanupTranspiler = (0, register_1.registerTsProject)(rootTsconfigPath);
|
19
19
|
}
|
20
20
|
const r = require(interpolatedChangelogRendererPath);
|
21
|
-
|
21
|
+
ChangelogRendererClass = r.default || r;
|
22
22
|
}
|
23
23
|
catch (err) {
|
24
24
|
throw err;
|
@@ -26,5 +26,5 @@ function resolveChangelogRenderer(changelogRendererPath) {
|
|
26
26
|
finally {
|
27
27
|
cleanupTranspiler();
|
28
28
|
}
|
29
|
-
return
|
29
|
+
return ChangelogRendererClass;
|
30
30
|
}
|
@@ -81,9 +81,9 @@ function withRunOptions(yargs) {
|
|
81
81
|
default: false,
|
82
82
|
})
|
83
83
|
.option('skipSync', {
|
84
|
+
describe: 'Skips running the sync generators associated with the tasks.',
|
84
85
|
type: 'boolean',
|
85
|
-
|
86
|
-
hidden: true,
|
86
|
+
default: false,
|
87
87
|
})
|
88
88
|
.options('cloud', {
|
89
89
|
type: 'boolean',
|
package/src/config/nx-json.d.ts
CHANGED
@@ -353,7 +353,8 @@ export interface NxJsonConfiguration<T = '*' | string[]> {
|
|
353
353
|
appsDir?: string;
|
354
354
|
};
|
355
355
|
/**
|
356
|
-
*
|
356
|
+
* @deprecated Custom task runners will no longer be supported in Nx 21. Use Nx Cloud or Nx Powerpack instead.
|
357
|
+
* Available Task Runners for Nx to use
|
357
358
|
*/
|
358
359
|
tasksRunnerOptions?: {
|
359
360
|
[tasksRunnerName: string]: {
|
Binary file
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { DefaultTasksRunnerOptions, RemoteCache } from './default-tasks-runner';
|
2
2
|
import { Task } from '../config/task-graph';
|
3
|
+
import { NxJsonConfiguration } from '../config/nx-json';
|
3
4
|
export type CachedResult = {
|
4
5
|
terminalOutput: string;
|
5
6
|
outputsPath: string;
|
@@ -10,6 +11,7 @@ export type TaskWithCachedResult = {
|
|
10
11
|
task: Task;
|
11
12
|
cachedResult: CachedResult;
|
12
13
|
};
|
14
|
+
export declare function dbCacheEnabled(nxJson?: NxJsonConfiguration): boolean;
|
13
15
|
export declare function getCache(options: DefaultTasksRunnerOptions): DbCache | Cache;
|
14
16
|
export declare class DbCache {
|
15
17
|
private readonly options;
|
@@ -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,11 +20,14 @@ 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");
|
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
|
+
}
|
22
27
|
// Do not change the order of these arguments as this function is used by nx cloud
|
23
28
|
function getCache(options) {
|
24
29
|
const nxJson = (0, nx_json_1.readNxJson)();
|
25
|
-
return
|
26
|
-
(nxJson.enableDbCache === true || process.env.NX_DB_CACHE === 'true')
|
30
|
+
return dbCacheEnabled(nxJson)
|
27
31
|
? new DbCache({
|
28
32
|
// Remove this in Nx 21
|
29
33
|
nxCloudRemoteCache: (0, nx_cloud_utils_1.isNxCloudUsed)(nxJson) ? options.remoteCache : null,
|
@@ -54,10 +54,10 @@ class ProcessTasks {
|
|
54
54
|
}
|
55
55
|
}
|
56
56
|
this.filterDummyTasks();
|
57
|
-
for (const
|
58
|
-
if (this.dependencies[
|
59
|
-
this.dependencies[
|
60
|
-
...new Set(this.dependencies[
|
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(),
|
61
61
|
];
|
62
62
|
}
|
63
63
|
}
|
@@ -511,12 +511,21 @@ function loadTasksRunner(modulePath) {
|
|
511
511
|
}
|
512
512
|
function getRunner(nxArgs, nxJson) {
|
513
513
|
let runner = nxArgs.runner;
|
514
|
-
runner = runner
|
514
|
+
runner = runner ?? 'default';
|
515
515
|
if (runner !== 'default' && !nxJson.tasksRunnerOptions?.[runner]) {
|
516
516
|
throw new Error(`Could not find runner configuration for ${runner}`);
|
517
517
|
}
|
518
518
|
const modulePath = getTasksRunnerPath(runner, nxJson);
|
519
519
|
try {
|
520
|
+
if (isCustomRunnerPath(modulePath)) {
|
521
|
+
output_1.output.warn({
|
522
|
+
title: `Custom task runners will no longer be supported in Nx 21.`,
|
523
|
+
bodyLines: [
|
524
|
+
`Use Nx Cloud or the Nx Powerpack caches instead.`,
|
525
|
+
`For more information, see https://nx.dev/features/powerpack/custom-caching`,
|
526
|
+
],
|
527
|
+
});
|
528
|
+
}
|
520
529
|
const tasksRunner = loadTasksRunner(modulePath);
|
521
530
|
return {
|
522
531
|
tasksRunner,
|
@@ -527,6 +536,7 @@ function getRunner(nxArgs, nxJson) {
|
|
527
536
|
throw new Error(`Could not find runner configuration for ${runner}`);
|
528
537
|
}
|
529
538
|
}
|
539
|
+
const defaultTasksRunnerPath = require.resolve('./default-tasks-runner');
|
530
540
|
function getTasksRunnerPath(runner, nxJson) {
|
531
541
|
let modulePath = nxJson.tasksRunnerOptions?.[runner]?.runner;
|
532
542
|
if (modulePath) {
|
@@ -544,7 +554,7 @@ function getTasksRunnerPath(runner, nxJson) {
|
|
544
554
|
process.env.NX_CLOUD_ACCESS_TOKEN ||
|
545
555
|
// Nx Cloud ID specified in nxJson
|
546
556
|
nxJson.nxCloudId;
|
547
|
-
return isCloudRunner ? 'nx-cloud' :
|
557
|
+
return isCloudRunner ? 'nx-cloud' : defaultTasksRunnerPath;
|
548
558
|
}
|
549
559
|
function getRunnerOptions(runner, nxJson, nxArgs, isCloudDefault) {
|
550
560
|
const defaultCacheableOperations = [];
|
@@ -588,3 +598,6 @@ function getRunnerOptions(runner, nxJson, nxArgs, isCloudDefault) {
|
|
588
598
|
}
|
589
599
|
return result;
|
590
600
|
}
|
601
|
+
function isCustomRunnerPath(modulePath) {
|
602
|
+
return !['nx-cloud', '@nrwl/nx-cloud', defaultTasksRunnerPath].includes(modulePath);
|
603
|
+
}
|
@@ -7,6 +7,9 @@ export interface RawNxArgs extends NxArgs {
|
|
7
7
|
export interface NxArgs {
|
8
8
|
targets?: string[];
|
9
9
|
configuration?: string;
|
10
|
+
/**
|
11
|
+
* @deprecated Custom task runners will no longer be supported in Nx 21. Use Nx Cloud or Nx Powerpack instead.
|
12
|
+
*/
|
10
13
|
runner?: string;
|
11
14
|
parallel?: number;
|
12
15
|
untracked?: boolean;
|