nx 20.0.0-canary.20241002-1d10a19 → 20.0.0-canary.20241003-84a5c7a
Sign up to get free protection for your applications and to get access to all the features.
- package/.eslintrc.json +12 -2
- package/migrations.json +0 -37
- 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/index.d.ts +5 -2
- package/src/command-line/release/publish.d.ts +6 -1
- package/src/command-line/release/publish.js +31 -25
- package/src/command-line/release/utils/print-changes.js +6 -4
- 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/release/utils/resolve-nx-json-error-message.js +4 -3
- package/src/command-line/release/version.d.ts +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/nx-cloud/utilities/axios.js +1 -2
- package/src/nx-cloud/utilities/onboarding.js +2 -2
- package/src/nx-cloud/utilities/url-shorten.js +5 -5
- package/src/project-graph/file-utils.d.ts +2 -2
- package/src/project-graph/file-utils.js +2 -2
- package/src/tasks-runner/cache.d.ts +2 -1
- package/src/tasks-runner/cache.js +10 -6
- package/src/tasks-runner/create-task-graph.d.ts +2 -0
- package/src/tasks-runner/create-task-graph.js +39 -5
- package/src/tasks-runner/run-command.js +15 -2
- package/src/tasks-runner/task-orchestrator.js +1 -1
- package/src/utils/command-line-utils.d.ts +3 -0
- package/src/utils/git-utils.js +2 -2
- package/src/migrations/update-15-0-0/prefix-outputs.d.ts +0 -2
- package/src/migrations/update-15-0-0/prefix-outputs.js +0 -49
- package/src/migrations/update-16-0-0/remove-nrwl-cli.d.ts +0 -2
- package/src/migrations/update-16-0-0/remove-nrwl-cli.js +0 -16
- package/src/migrations/update-16-0-0/update-depends-on-to-tokens.d.ts +0 -2
- package/src/migrations/update-16-0-0/update-depends-on-to-tokens.js +0 -97
- package/src/migrations/update-16-0-0/update-nx-cloud-runner.d.ts +0 -2
- package/src/migrations/update-16-0-0/update-nx-cloud-runner.js +0 -29
- package/src/migrations/update-16-2-0/remove-run-commands-output-path.d.ts +0 -2
- package/src/migrations/update-16-2-0/remove-run-commands-output-path.js +0 -45
- package/src/migrations/update-16-8-0/escape-dollar-sign-env-variables.d.ts +0 -12
- package/src/migrations/update-16-8-0/escape-dollar-sign-env-variables.js +0 -67
@@ -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
|
}
|