nx 20.0.0-beta.6 → 20.0.0-beta.7
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|