nx 19.7.0-canary.20240903-9039e5e → 19.7.0-canary.20240905-ccda7f9
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 +12 -12
- package/release/changelog-renderer/index.d.ts +1 -1
- package/release/changelog-renderer/index.js +46 -11
- package/src/command-line/login/command-object.js +1 -1
- package/src/command-line/logout/command-object.js +1 -1
- package/src/command-line/release/changelog.js +42 -11
- package/src/command-line/release/command-object.d.ts +1 -0
- package/src/command-line/release/command-object.js +7 -8
- package/src/command-line/release/config/version-plans.d.ts +14 -1
- package/src/command-line/release/config/version-plans.js +33 -1
- package/src/command-line/release/plan-check.js +1 -1
- package/src/command-line/release/publish.js +3 -0
- package/src/command-line/release/release.js +1 -1
- package/src/command-line/release/utils/git.d.ts +1 -1
- package/src/command-line/release/utils/git.js +46 -19
- package/src/command-line/release/version.js +1 -1
- package/src/command-line/yargs-utils/shared-options.d.ts +2 -1
- package/src/command-line/yargs-utils/shared-options.js +5 -0
- package/src/core/graph/main.js +1 -1
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +42 -6
- package/src/tasks-runner/run-command.js +4 -1
- package/src/utils/command-line-utils.d.ts +1 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "19.7.0-canary.
|
3
|
+
"version": "19.7.0-canary.20240905-ccda7f9",
|
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": {
|
@@ -71,7 +71,7 @@
|
|
71
71
|
"yargs-parser": "21.1.1",
|
72
72
|
"node-machine-id": "1.1.12",
|
73
73
|
"ora": "5.3.0",
|
74
|
-
"@nrwl/tao": "19.7.0-canary.
|
74
|
+
"@nrwl/tao": "19.7.0-canary.20240905-ccda7f9"
|
75
75
|
},
|
76
76
|
"peerDependencies": {
|
77
77
|
"@swc-node/register": "^1.8.0",
|
@@ -86,16 +86,16 @@
|
|
86
86
|
}
|
87
87
|
},
|
88
88
|
"optionalDependencies": {
|
89
|
-
"@nx/nx-darwin-x64": "19.7.0-canary.
|
90
|
-
"@nx/nx-darwin-arm64": "19.7.0-canary.
|
91
|
-
"@nx/nx-linux-x64-gnu": "19.7.0-canary.
|
92
|
-
"@nx/nx-linux-x64-musl": "19.7.0-canary.
|
93
|
-
"@nx/nx-win32-x64-msvc": "19.7.0-canary.
|
94
|
-
"@nx/nx-linux-arm64-gnu": "19.7.0-canary.
|
95
|
-
"@nx/nx-linux-arm64-musl": "19.7.0-canary.
|
96
|
-
"@nx/nx-linux-arm-gnueabihf": "19.7.0-canary.
|
97
|
-
"@nx/nx-win32-arm64-msvc": "19.7.0-canary.
|
98
|
-
"@nx/nx-freebsd-x64": "19.7.0-canary.
|
89
|
+
"@nx/nx-darwin-x64": "19.7.0-canary.20240905-ccda7f9",
|
90
|
+
"@nx/nx-darwin-arm64": "19.7.0-canary.20240905-ccda7f9",
|
91
|
+
"@nx/nx-linux-x64-gnu": "19.7.0-canary.20240905-ccda7f9",
|
92
|
+
"@nx/nx-linux-x64-musl": "19.7.0-canary.20240905-ccda7f9",
|
93
|
+
"@nx/nx-win32-x64-msvc": "19.7.0-canary.20240905-ccda7f9",
|
94
|
+
"@nx/nx-linux-arm64-gnu": "19.7.0-canary.20240905-ccda7f9",
|
95
|
+
"@nx/nx-linux-arm64-musl": "19.7.0-canary.20240905-ccda7f9",
|
96
|
+
"@nx/nx-linux-arm-gnueabihf": "19.7.0-canary.20240905-ccda7f9",
|
97
|
+
"@nx/nx-win32-arm64-msvc": "19.7.0-canary.20240905-ccda7f9",
|
98
|
+
"@nx/nx-freebsd-x64": "19.7.0-canary.20240905-ccda7f9"
|
99
99
|
},
|
100
100
|
"nx-migrations": {
|
101
101
|
"migrations": "./migrations.json",
|
@@ -41,7 +41,7 @@ export type ChangelogRenderer = (config: {
|
|
41
41
|
changelogRenderOptions: DefaultChangelogRenderOptions;
|
42
42
|
dependencyBumps?: DependencyBump[];
|
43
43
|
repoSlug?: RepoSlug;
|
44
|
-
conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'];
|
44
|
+
conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'] | null;
|
45
45
|
}) => Promise<string> | string;
|
46
46
|
/**
|
47
47
|
* The specific options available to the default implementation of the ChangelogRenderer that nx exports
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
const semver_1 = require("semver");
|
4
|
+
const conventional_commits_1 = require("../../src/command-line/release/config/conventional-commits");
|
4
5
|
const github_1 = require("../../src/command-line/release/utils/github");
|
5
6
|
// axios types and values don't seem to match
|
6
7
|
const _axios = require("axios");
|
@@ -10,9 +11,7 @@ const axios = _axios;
|
|
10
11
|
* from the given commits and other metadata.
|
11
12
|
*/
|
12
13
|
const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion, project, entryWhenNoChanges, changelogRenderOptions, dependencyBumps, repoSlug, conventionalCommitsConfig, }) => {
|
13
|
-
const changeTypes = conventionalCommitsConfig.types;
|
14
14
|
const markdownLines = [];
|
15
|
-
const breakingChanges = [];
|
16
15
|
// If the current range of changes contains both a commit and its revert, we strip them both from the final list. Changes from version plans are unaffected, as they have no hashes.
|
17
16
|
for (const change of changes) {
|
18
17
|
if (change.type === 'revert' && change.revertedHashes) {
|
@@ -26,10 +25,38 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
26
25
|
}
|
27
26
|
}
|
28
27
|
let relevantChanges = changes;
|
28
|
+
const breakingChanges = [];
|
29
|
+
// For now to keep the interface of the changelog renderer non-breaking for v19 releases we have a somewhat indirect check for whether or not we are generating a changelog for version plans
|
30
|
+
const isVersionPlans = !conventionalCommitsConfig;
|
31
|
+
// Only applicable for version plans
|
32
|
+
const additionalChangesForAuthorsSection = [];
|
33
|
+
// Provide a default configuration for version plans to allow most of the subsequent logic to work in the same way it would for conventional commits
|
34
|
+
// NOTE: The one exception is breaking/major changes, where we do not follow the same structure and instead only show the changes once
|
35
|
+
if (isVersionPlans) {
|
36
|
+
conventionalCommitsConfig = {
|
37
|
+
types: {
|
38
|
+
feat: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG.types.feat,
|
39
|
+
fix: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG.types.fix,
|
40
|
+
},
|
41
|
+
};
|
42
|
+
// Trim down "relevant changes" to only include non-breaking ones so that we can render them differently under version plans,
|
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, repoSlug);
|
50
|
+
breakingChanges.push(line);
|
51
|
+
relevantChanges.splice(i, 1);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
const changeTypes = conventionalCommitsConfig.types;
|
29
56
|
// workspace root level changelog
|
30
57
|
if (project === null) {
|
31
58
|
// No changes for the workspace
|
32
|
-
if (relevantChanges.length === 0) {
|
59
|
+
if (relevantChanges.length === 0 && breakingChanges.length === 0) {
|
33
60
|
if (dependencyBumps?.length) {
|
34
61
|
applyAdditionalDependencyBumps({
|
35
62
|
markdownLines,
|
@@ -62,7 +89,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
62
89
|
for (const scope of scopesSortedAlphabetically) {
|
63
90
|
const changes = changesGroupedByScope[scope];
|
64
91
|
for (const change of changes) {
|
65
|
-
const line = formatChange(change, changelogRenderOptions, repoSlug);
|
92
|
+
const line = formatChange(change, changelogRenderOptions, isVersionPlans, repoSlug);
|
66
93
|
markdownLines.push(line);
|
67
94
|
if (change.isBreaking) {
|
68
95
|
const breakingChangeExplanation = extractBreakingChangeExplanation(change.body);
|
@@ -79,7 +106,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
79
106
|
relevantChanges = relevantChanges.filter((c) => c.affectedProjects &&
|
80
107
|
(c.affectedProjects === '*' || c.affectedProjects.includes(project)));
|
81
108
|
// Generating for a named project, but that project has no relevant changes in the current set of commits, exit early
|
82
|
-
if (relevantChanges.length === 0) {
|
109
|
+
if (relevantChanges.length === 0 && breakingChanges.length === 0) {
|
83
110
|
if (dependencyBumps?.length) {
|
84
111
|
applyAdditionalDependencyBumps({
|
85
112
|
markdownLines,
|
@@ -105,7 +132,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
105
132
|
markdownLines.push('', `### ${changeTypes[type].changelog.title}`, '');
|
106
133
|
const changesInChronologicalOrder = group.reverse();
|
107
134
|
for (const change of changesInChronologicalOrder) {
|
108
|
-
const line = formatChange(change, changelogRenderOptions, repoSlug);
|
135
|
+
const line = formatChange(change, changelogRenderOptions, isVersionPlans, repoSlug);
|
109
136
|
markdownLines.push(line + '\n');
|
110
137
|
if (change.isBreaking) {
|
111
138
|
const breakingChangeExplanation = extractBreakingChangeExplanation(change.body);
|
@@ -117,7 +144,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
117
144
|
}
|
118
145
|
}
|
119
146
|
if (breakingChanges.length > 0) {
|
120
|
-
markdownLines.push('', '
|
147
|
+
markdownLines.push('', '### ⚠️ Breaking Changes', '', ...breakingChanges);
|
121
148
|
}
|
122
149
|
if (dependencyBumps?.length) {
|
123
150
|
applyAdditionalDependencyBumps({
|
@@ -129,7 +156,10 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
129
156
|
}
|
130
157
|
if (changelogRenderOptions.authors) {
|
131
158
|
const _authors = new Map();
|
132
|
-
for (const change of
|
159
|
+
for (const change of [
|
160
|
+
...relevantChanges,
|
161
|
+
...additionalChangesForAuthorsSection,
|
162
|
+
]) {
|
133
163
|
if (!change.author) {
|
134
164
|
continue;
|
135
165
|
}
|
@@ -215,7 +245,7 @@ function groupBy(items, key) {
|
|
215
245
|
}
|
216
246
|
return groups;
|
217
247
|
}
|
218
|
-
function formatChange(change, changelogRenderOptions, repoSlug) {
|
248
|
+
function formatChange(change, changelogRenderOptions, isVersionPlans, repoSlug) {
|
219
249
|
let description = change.description;
|
220
250
|
let extraLines = [];
|
221
251
|
let extraLinesStr = '';
|
@@ -228,9 +258,14 @@ function formatChange(change, changelogRenderOptions, repoSlug) {
|
|
228
258
|
.map((l) => `${indentation}${l}`)
|
229
259
|
.join('\n');
|
230
260
|
}
|
261
|
+
/**
|
262
|
+
* In version plans changelogs:
|
263
|
+
* - don't repeat the breaking change icon
|
264
|
+
* - don't render the scope
|
265
|
+
*/
|
231
266
|
let changeLine = '- ' +
|
232
|
-
(change.isBreaking ? '⚠️ ' : '') +
|
233
|
-
(change.scope ? `**${change.scope.trim()}:** ` : '') +
|
267
|
+
(!isVersionPlans && change.isBreaking ? '⚠️ ' : '') +
|
268
|
+
(!isVersionPlans && change.scope ? `**${change.scope.trim()}:** ` : '') +
|
234
269
|
description;
|
235
270
|
if (repoSlug && changelogRenderOptions.commitReferences) {
|
236
271
|
changeLine += (0, github_1.formatReferences)(change.githubReferences, repoSlug);
|
@@ -4,7 +4,7 @@ exports.yargsLoginCommand = void 0;
|
|
4
4
|
const shared_options_1 = require("../../command-line/yargs-utils/shared-options");
|
5
5
|
exports.yargsLoginCommand = {
|
6
6
|
command: 'login [nxCloudUrl]',
|
7
|
-
describe:
|
7
|
+
describe: false,
|
8
8
|
builder: (yargs) => (0, shared_options_1.withVerbose)(yargs.positional('nxCloudUrl', {
|
9
9
|
describe: 'The Nx Cloud URL of the instance you are trying to connect to. If no positional argument is provided, this command will connect to https://cloud.nx.app.',
|
10
10
|
type: 'string',
|
@@ -4,7 +4,7 @@ exports.yargsLogoutCommand = void 0;
|
|
4
4
|
const shared_options_1 = require("../../command-line/yargs-utils/shared-options");
|
5
5
|
exports.yargsLogoutCommand = {
|
6
6
|
command: 'logout',
|
7
|
-
describe:
|
7
|
+
describe: false,
|
8
8
|
builder: (yargs) => (0, shared_options_1.withVerbose)(yargs),
|
9
9
|
handler: async (args) => {
|
10
10
|
process.exit(await (await Promise.resolve().then(() => require('./logout'))).logoutHandler(args));
|
@@ -81,7 +81,7 @@ function createAPI(overrideReleaseConfig) {
|
|
81
81
|
process.exit(1);
|
82
82
|
}
|
83
83
|
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
84
|
-
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
84
|
+
await (0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes), args.verbose);
|
85
85
|
if (args.deleteVersionPlans === undefined) {
|
86
86
|
// default to deleting version plans in this command instead of after versioning
|
87
87
|
args.deleteVersionPlans = true;
|
@@ -146,6 +146,15 @@ function createAPI(overrideReleaseConfig) {
|
|
146
146
|
workspaceChangelogChanges = versionPlans
|
147
147
|
.flatMap((vp) => {
|
148
148
|
const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
|
149
|
+
let githubReferences = [];
|
150
|
+
let author = undefined;
|
151
|
+
const parsedCommit = vp.commit
|
152
|
+
? (0, git_1.parseGitCommit)(vp.commit, true)
|
153
|
+
: null;
|
154
|
+
if (parsedCommit) {
|
155
|
+
githubReferences = parsedCommit.references;
|
156
|
+
author = parsedCommit.author;
|
157
|
+
}
|
149
158
|
const changes = !vp.triggeredByProjects
|
150
159
|
? {
|
151
160
|
type: releaseType.type,
|
@@ -153,7 +162,8 @@ function createAPI(overrideReleaseConfig) {
|
|
153
162
|
description: vp.message,
|
154
163
|
body: '',
|
155
164
|
isBreaking: releaseType.isBreaking,
|
156
|
-
githubReferences
|
165
|
+
githubReferences,
|
166
|
+
author,
|
157
167
|
affectedProjects: '*',
|
158
168
|
}
|
159
169
|
: vp.triggeredByProjects.map((project) => {
|
@@ -162,9 +172,9 @@ function createAPI(overrideReleaseConfig) {
|
|
162
172
|
scope: project,
|
163
173
|
description: vp.message,
|
164
174
|
body: '',
|
165
|
-
// TODO: what about github references?
|
166
175
|
isBreaking: releaseType.isBreaking,
|
167
|
-
githubReferences
|
176
|
+
githubReferences,
|
177
|
+
author,
|
168
178
|
affectedProjects: [project],
|
169
179
|
};
|
170
180
|
});
|
@@ -301,6 +311,15 @@ function createAPI(overrideReleaseConfig) {
|
|
301
311
|
return null;
|
302
312
|
}
|
303
313
|
const releaseType = versionPlanSemverReleaseTypeToChangelogType(bumpForProject);
|
314
|
+
let githubReferences = [];
|
315
|
+
let author = undefined;
|
316
|
+
const parsedCommit = vp.commit
|
317
|
+
? (0, git_1.parseGitCommit)(vp.commit, true)
|
318
|
+
: null;
|
319
|
+
if (parsedCommit) {
|
320
|
+
githubReferences = parsedCommit.references;
|
321
|
+
author = parsedCommit.author;
|
322
|
+
}
|
304
323
|
return {
|
305
324
|
type: releaseType.type,
|
306
325
|
scope: project.name,
|
@@ -308,8 +327,8 @@ function createAPI(overrideReleaseConfig) {
|
|
308
327
|
body: '',
|
309
328
|
isBreaking: releaseType.isBreaking,
|
310
329
|
affectedProjects: Object.keys(vp.projectVersionBumps),
|
311
|
-
|
312
|
-
|
330
|
+
githubReferences,
|
331
|
+
author,
|
313
332
|
};
|
314
333
|
})
|
315
334
|
.filter(Boolean);
|
@@ -397,6 +416,15 @@ function createAPI(overrideReleaseConfig) {
|
|
397
416
|
changes = releaseGroup.resolvedVersionPlans
|
398
417
|
.flatMap((vp) => {
|
399
418
|
const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
|
419
|
+
let githubReferences = [];
|
420
|
+
let author = undefined;
|
421
|
+
const parsedCommit = vp.commit
|
422
|
+
? (0, git_1.parseGitCommit)(vp.commit, true)
|
423
|
+
: null;
|
424
|
+
if (parsedCommit) {
|
425
|
+
githubReferences = parsedCommit.references;
|
426
|
+
author = parsedCommit.author;
|
427
|
+
}
|
400
428
|
const changes = !vp.triggeredByProjects
|
401
429
|
? {
|
402
430
|
type: releaseType.type,
|
@@ -404,7 +432,8 @@ function createAPI(overrideReleaseConfig) {
|
|
404
432
|
description: vp.message,
|
405
433
|
body: '',
|
406
434
|
isBreaking: releaseType.isBreaking,
|
407
|
-
githubReferences
|
435
|
+
githubReferences,
|
436
|
+
author,
|
408
437
|
affectedProjects: '*',
|
409
438
|
}
|
410
439
|
: vp.triggeredByProjects.map((project) => {
|
@@ -413,9 +442,9 @@ function createAPI(overrideReleaseConfig) {
|
|
413
442
|
scope: project,
|
414
443
|
description: vp.message,
|
415
444
|
body: '',
|
416
|
-
// TODO: what about github references?
|
417
445
|
isBreaking: releaseType.isBreaking,
|
418
|
-
githubReferences
|
446
|
+
githubReferences,
|
447
|
+
author,
|
419
448
|
affectedProjects: [project],
|
420
449
|
};
|
421
450
|
});
|
@@ -579,7 +608,7 @@ async function applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTa
|
|
579
608
|
}
|
580
609
|
const changedFiles = changes.map((f) => f.path);
|
581
610
|
let deletedFiles = [];
|
582
|
-
if (args.deleteVersionPlans
|
611
|
+
if (args.deleteVersionPlans) {
|
583
612
|
const planFiles = new Set();
|
584
613
|
releaseGroups.forEach((group) => {
|
585
614
|
if (group.resolvedVersionPlans) {
|
@@ -811,7 +840,9 @@ async function generateChangelogForProjects({ tree, args, projectGraph, changes,
|
|
811
840
|
})
|
812
841
|
: false,
|
813
842
|
changelogRenderOptions: config.renderOptions,
|
814
|
-
conventionalCommitsConfig:
|
843
|
+
conventionalCommitsConfig: releaseGroup.versionPlans
|
844
|
+
? null
|
845
|
+
: nxReleaseConfig.conventionalCommits,
|
815
846
|
dependencyBumps: projectToAdditionalDependencyBumps.get(project.name),
|
816
847
|
});
|
817
848
|
/**
|
@@ -187,6 +187,11 @@ const publishCommand = {
|
|
187
187
|
.option('tag', {
|
188
188
|
type: 'string',
|
189
189
|
description: 'The distribution tag to apply to the published package',
|
190
|
+
})
|
191
|
+
.option('access', {
|
192
|
+
type: 'string',
|
193
|
+
choices: ['public', 'restricted'],
|
194
|
+
description: 'Overrides the access level of the published package. Unscoped packages cannot be set to restricted. See the npm publish documentation for more information.',
|
190
195
|
})
|
191
196
|
.option('otp', {
|
192
197
|
type: 'number',
|
@@ -203,10 +208,7 @@ const publishCommand = {
|
|
203
208
|
const planCommand = {
|
204
209
|
command: 'plan [bump]',
|
205
210
|
aliases: ['pl'],
|
206
|
-
|
207
|
-
// Create a plan to pick a new version and generate a changelog entry.
|
208
|
-
// Hidden for now until the feature is more stable
|
209
|
-
describe: false,
|
211
|
+
describe: 'Create a version plan file to specify the desired semver bump for one or more projects or groups, as well as the relevant changelog entry',
|
210
212
|
builder: (yargs) => (0, shared_options_1.withAffectedOptions)(yargs)
|
211
213
|
.positional('bump', {
|
212
214
|
type: 'string',
|
@@ -242,10 +244,7 @@ const planCommand = {
|
|
242
244
|
};
|
243
245
|
const planCheckCommand = {
|
244
246
|
command: 'plan:check',
|
245
|
-
|
246
|
-
// Create a plan to pick a new version and generate a changelog entry.
|
247
|
-
// Hidden for now until the feature is more stable
|
248
|
-
describe: false,
|
247
|
+
describe: 'Ensure that all touched projects have an applicable version plan created for them',
|
249
248
|
builder: (yargs) => (0, shared_options_1.withAffectedOptions)(yargs),
|
250
249
|
handler: async (args) => {
|
251
250
|
const release = await Promise.resolve().then(() => require('./plan-check'));
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { ReleaseType } from 'semver';
|
2
|
+
import { RawGitCommit } from '../utils/git';
|
2
3
|
import { ReleaseGroupWithName } from './filter-release-groups';
|
3
4
|
export interface VersionPlanFile {
|
4
5
|
absolutePath: string;
|
@@ -12,9 +13,21 @@ export interface RawVersionPlan extends VersionPlanFile {
|
|
12
13
|
}
|
13
14
|
export interface VersionPlan extends VersionPlanFile {
|
14
15
|
message: string;
|
16
|
+
/**
|
17
|
+
* The commit that added the version plan file, will be null if the file was never committed.
|
18
|
+
* For optimal performance, we don't apply it at the time of reading the raw contents, because
|
19
|
+
* it hasn't yet passed further validation at that point.
|
20
|
+
*/
|
21
|
+
commit: RawGitCommit | null;
|
15
22
|
}
|
16
23
|
export interface GroupVersionPlan extends VersionPlan {
|
17
24
|
groupVersionBump: ReleaseType;
|
25
|
+
/**
|
26
|
+
* The commit that added the version plan file, will be null if the file was never committed.
|
27
|
+
* For optimal performance, we don't apply it at the time of reading the raw contents, because.
|
28
|
+
* it hasn't yet passed validation.
|
29
|
+
*/
|
30
|
+
commit: RawGitCommit | null;
|
18
31
|
/**
|
19
32
|
* Will not be set if the group name was the trigger, otherwise will be a list of
|
20
33
|
* all the individual project names explicitly found in the version plan file.
|
@@ -25,5 +38,5 @@ export interface ProjectsVersionPlan extends VersionPlan {
|
|
25
38
|
projectVersionBumps: Record<string, ReleaseType>;
|
26
39
|
}
|
27
40
|
export declare function readRawVersionPlans(): Promise<RawVersionPlan[]>;
|
28
|
-
export declare function setResolvedVersionPlansOnGroups(rawVersionPlans: RawVersionPlan[], releaseGroups: ReleaseGroupWithName[], allProjectNamesInWorkspace: string[]): ReleaseGroupWithName[]
|
41
|
+
export declare function setResolvedVersionPlansOnGroups(rawVersionPlans: RawVersionPlan[], releaseGroups: ReleaseGroupWithName[], allProjectNamesInWorkspace: string[], isVerbose: boolean): Promise<ReleaseGroupWithName[]>;
|
29
42
|
export declare function getVersionPlansAbsolutePath(): string;
|
@@ -5,6 +5,7 @@ exports.setResolvedVersionPlansOnGroups = setResolvedVersionPlansOnGroups;
|
|
5
5
|
exports.getVersionPlansAbsolutePath = getVersionPlansAbsolutePath;
|
6
6
|
const fs_1 = require("fs");
|
7
7
|
const fs_extra_1 = require("fs-extra");
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
8
9
|
const path_1 = require("path");
|
9
10
|
const semver_1 = require("semver");
|
10
11
|
const workspace_root_1 = require("../../../utils/workspace-root");
|
@@ -35,7 +36,7 @@ async function readRawVersionPlans() {
|
|
35
36
|
}
|
36
37
|
return versionPlans;
|
37
38
|
}
|
38
|
-
function setResolvedVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNamesInWorkspace) {
|
39
|
+
async function setResolvedVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNamesInWorkspace, isVerbose) {
|
39
40
|
const groupsByName = releaseGroups.reduce((acc, group) => acc.set(group.name, group), new Map());
|
40
41
|
const isDefaultGroup = isDefault(releaseGroups);
|
41
42
|
for (const rawVersionPlan of rawVersionPlans) {
|
@@ -88,6 +89,7 @@ function setResolvedVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProj
|
|
88
89
|
createdOnMs: rawVersionPlan.createdOnMs,
|
89
90
|
message: rawVersionPlan.message,
|
90
91
|
groupVersionBump: value,
|
92
|
+
commit: await getCommitForVersionPlanFile(rawVersionPlan, isVerbose),
|
91
93
|
});
|
92
94
|
}
|
93
95
|
}
|
@@ -130,6 +132,7 @@ function setResolvedVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProj
|
|
130
132
|
projectVersionBumps: {
|
131
133
|
[key]: value,
|
132
134
|
},
|
135
|
+
commit: await getCommitForVersionPlanFile(rawVersionPlan, isVerbose),
|
133
136
|
});
|
134
137
|
}
|
135
138
|
}
|
@@ -161,6 +164,7 @@ function setResolvedVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProj
|
|
161
164
|
// but we track the projects that triggered the version bump so that we can accurately produce changelog entries.
|
162
165
|
groupVersionBump: value,
|
163
166
|
triggeredByProjects: [key],
|
167
|
+
commit: await getCommitForVersionPlanFile(rawVersionPlan, isVerbose),
|
164
168
|
});
|
165
169
|
}
|
166
170
|
}
|
@@ -185,3 +189,31 @@ function getVersionPlansAbsolutePath() {
|
|
185
189
|
function isReleaseType(value) {
|
186
190
|
return semver_1.RELEASE_TYPES.includes(value);
|
187
191
|
}
|
192
|
+
async function getCommitForVersionPlanFile(rawVersionPlan, isVerbose) {
|
193
|
+
return new Promise((resolve) => {
|
194
|
+
(0, node_child_process_1.exec)(`git log --diff-filter=A --pretty=format:"%s|%h|%an|%ae|%b" -n 1 -- ${rawVersionPlan.absolutePath}`, (error, stdout, stderr) => {
|
195
|
+
if (error) {
|
196
|
+
if (isVerbose) {
|
197
|
+
console.error(`Error executing git command for ${rawVersionPlan.relativePath}: ${error.message}`);
|
198
|
+
}
|
199
|
+
return resolve(null);
|
200
|
+
}
|
201
|
+
if (stderr) {
|
202
|
+
if (isVerbose) {
|
203
|
+
console.error(`Git command stderr for ${rawVersionPlan.relativePath}: ${stderr}`);
|
204
|
+
}
|
205
|
+
return resolve(null);
|
206
|
+
}
|
207
|
+
const [message, shortHash, authorName, authorEmail, ...body] = stdout
|
208
|
+
.trim()
|
209
|
+
.split('|');
|
210
|
+
const commitDetails = {
|
211
|
+
message: message || '',
|
212
|
+
shortHash: shortHash || '',
|
213
|
+
author: { name: authorName || '', email: authorEmail || '' },
|
214
|
+
body: body.join('|') || '', // Handle case where body might be empty or contain multiple '|'
|
215
|
+
};
|
216
|
+
return resolve(commitDetails);
|
217
|
+
});
|
218
|
+
});
|
219
|
+
}
|
@@ -53,7 +53,7 @@ function createAPI(overrideReleaseConfig) {
|
|
53
53
|
return 1;
|
54
54
|
}
|
55
55
|
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
56
|
-
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
56
|
+
await (0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes), args.verbose);
|
57
57
|
// Resolve the final values for base, head etc to use when resolving the changes to consider
|
58
58
|
const { nxArgs } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'affected', {
|
59
59
|
printWarnings: args.verbose,
|
@@ -103,6 +103,9 @@ async function runPublishOnProjects(args, projectGraph, nxJson, projectNames, is
|
|
103
103
|
if (args.otp) {
|
104
104
|
overrides.otp = args.otp;
|
105
105
|
}
|
106
|
+
if (args.access) {
|
107
|
+
overrides.access = args.access;
|
108
|
+
}
|
106
109
|
if (args.dryRun) {
|
107
110
|
overrides.dryRun = args.dryRun;
|
108
111
|
/**
|
@@ -94,7 +94,7 @@ function createAPI(overrideReleaseConfig) {
|
|
94
94
|
output_1.output.error(filterError);
|
95
95
|
process.exit(1);
|
96
96
|
}
|
97
|
-
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
97
|
+
await (0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes), args.verbose);
|
98
98
|
const planFiles = new Set();
|
99
99
|
releaseGroups.forEach((group) => {
|
100
100
|
if (group.resolvedVersionPlans) {
|
@@ -62,6 +62,6 @@ export declare function parseConventionalCommitsMessage(message: string): {
|
|
62
62
|
description: string;
|
63
63
|
breaking: boolean;
|
64
64
|
} | null;
|
65
|
-
export declare function parseGitCommit(commit: RawGitCommit): GitCommit | null;
|
65
|
+
export declare function parseGitCommit(commit: RawGitCommit, isVersionPlanCommit?: boolean): GitCommit | null;
|
66
66
|
export declare function getCommitHash(ref: string): Promise<string>;
|
67
67
|
export declare function getFirstGitCommit(): Promise<string>;
|
@@ -136,7 +136,7 @@ async function gitAdd({ changedFiles, deletedFiles, dryRun, verbose, logFn, cwd,
|
|
136
136
|
ignoredFiles.push(f);
|
137
137
|
// git add will fail if trying to add an untracked file that doesn't exist
|
138
138
|
}
|
139
|
-
else if (changedTrackedFiles.has(f)) {
|
139
|
+
else if (changedTrackedFiles.has(f) || dryRun) {
|
140
140
|
filesToAdd.push(f);
|
141
141
|
}
|
142
142
|
}
|
@@ -281,6 +281,30 @@ function parseConventionalCommitsMessage(message) {
|
|
281
281
|
breaking: Boolean(match.groups.breaking),
|
282
282
|
};
|
283
283
|
}
|
284
|
+
function extractReferencesFromCommitMessage(message, shortHash) {
|
285
|
+
const references = [];
|
286
|
+
for (const m of message.matchAll(PullRequestRE)) {
|
287
|
+
references.push({ type: 'pull-request', value: m[1] });
|
288
|
+
}
|
289
|
+
for (const m of message.matchAll(IssueRE)) {
|
290
|
+
if (!references.some((i) => i.value === m[1])) {
|
291
|
+
references.push({ type: 'issue', value: m[1] });
|
292
|
+
}
|
293
|
+
}
|
294
|
+
references.push({ value: shortHash, type: 'hash' });
|
295
|
+
return references;
|
296
|
+
}
|
297
|
+
function getAllAuthorsForCommit(commit) {
|
298
|
+
const authors = [commit.author];
|
299
|
+
// Additional authors can be specified in the commit body (depending on the VCS provider)
|
300
|
+
for (const match of commit.body.matchAll(CoAuthoredByRegex)) {
|
301
|
+
authors.push({
|
302
|
+
name: (match.groups.name || '').trim(),
|
303
|
+
email: (match.groups.email || '').trim(),
|
304
|
+
});
|
305
|
+
}
|
306
|
+
return authors;
|
307
|
+
}
|
284
308
|
// https://www.conventionalcommits.org/en/v1.0.0/
|
285
309
|
// https://regex101.com/r/FSfNvA/1
|
286
310
|
const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
@@ -289,7 +313,25 @@ const PullRequestRE = /\([ a-z]*(#\d+)\s*\)/gm;
|
|
289
313
|
const IssueRE = /(#\d+)/gm;
|
290
314
|
const ChangedFileRegex = /(A|M|D|R\d*|C\d*)\t([^\t\n]*)\t?(.*)?/gm;
|
291
315
|
const RevertHashRE = /This reverts commit (?<hash>[\da-f]{40})./gm;
|
292
|
-
function parseGitCommit(commit) {
|
316
|
+
function parseGitCommit(commit, isVersionPlanCommit = false) {
|
317
|
+
// For version plans, we do not require conventional commits and therefore cannot extract data based on that format
|
318
|
+
if (isVersionPlanCommit) {
|
319
|
+
return {
|
320
|
+
...commit,
|
321
|
+
description: commit.message,
|
322
|
+
type: '',
|
323
|
+
scope: '',
|
324
|
+
references: extractReferencesFromCommitMessage(commit.message, commit.shortHash),
|
325
|
+
// The commit message is not the source of truth for a breaking (major) change in version plans, so the value is not relevant
|
326
|
+
// TODO(v20): Make the current GitCommit interface more clearly tied to conventional commits
|
327
|
+
isBreaking: false,
|
328
|
+
authors: getAllAuthorsForCommit(commit),
|
329
|
+
// Not applicable to version plans
|
330
|
+
affectedFiles: [],
|
331
|
+
// Not applicable, a version plan cannot have been added in a commit that also reverts another commit
|
332
|
+
revertedHashes: [],
|
333
|
+
};
|
334
|
+
}
|
293
335
|
const parsedMessage = parseConventionalCommitsMessage(commit.message);
|
294
336
|
if (!parsedMessage) {
|
295
337
|
return null;
|
@@ -298,16 +340,7 @@ function parseGitCommit(commit) {
|
|
298
340
|
const isBreaking = parsedMessage.breaking || commit.body.includes('BREAKING CHANGE:');
|
299
341
|
let description = parsedMessage.description;
|
300
342
|
// Extract references from message
|
301
|
-
const references =
|
302
|
-
for (const m of description.matchAll(PullRequestRE)) {
|
303
|
-
references.push({ type: 'pull-request', value: m[1] });
|
304
|
-
}
|
305
|
-
for (const m of description.matchAll(IssueRE)) {
|
306
|
-
if (!references.some((i) => i.value === m[1])) {
|
307
|
-
references.push({ type: 'issue', value: m[1] });
|
308
|
-
}
|
309
|
-
}
|
310
|
-
references.push({ value: commit.shortHash, type: 'hash' });
|
343
|
+
const references = extractReferencesFromCommitMessage(description, commit.shortHash);
|
311
344
|
// Remove references and normalize
|
312
345
|
description = description.replace(PullRequestRE, '').trim();
|
313
346
|
let type = parsedMessage.type;
|
@@ -322,13 +355,7 @@ function parseGitCommit(commit) {
|
|
322
355
|
description = commit.message;
|
323
356
|
}
|
324
357
|
// Find all authors
|
325
|
-
const authors =
|
326
|
-
for (const match of commit.body.matchAll(CoAuthoredByRegex)) {
|
327
|
-
authors.push({
|
328
|
-
name: (match.groups.name || '').trim(),
|
329
|
-
email: (match.groups.email || '').trim(),
|
330
|
-
});
|
331
|
-
}
|
358
|
+
const authors = getAllAuthorsForCommit(commit);
|
332
359
|
// Extract file changes from commit body
|
333
360
|
const affectedFiles = Array.from(commit.body.matchAll(ChangedFileRegex)).reduce((prev, [fullLine, changeType, file1, file2]) =>
|
334
361
|
// file2 only exists for some change types, such as renames
|
@@ -82,7 +82,7 @@ function createAPI(overrideReleaseConfig) {
|
|
82
82
|
}
|
83
83
|
if (!args.specifier) {
|
84
84
|
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
85
|
-
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
85
|
+
await (0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes), args.verbose);
|
86
86
|
}
|
87
87
|
else {
|
88
88
|
if (args.verbose && releaseGroups.some((g) => !!g.versionPlans)) {
|
@@ -3,7 +3,7 @@ interface ExcludeOptions {
|
|
3
3
|
exclude: string[];
|
4
4
|
}
|
5
5
|
export declare const defaultYargsParserConfiguration: Partial<ParserConfigurationOptions>;
|
6
|
-
export declare function withExcludeOption(yargs: Argv): Argv<ExcludeOptions>;
|
6
|
+
export declare function withExcludeOption<T>(yargs: Argv<T>): Argv<T & ExcludeOptions>;
|
7
7
|
export interface RunOptions {
|
8
8
|
exclude: string;
|
9
9
|
parallel: string;
|
@@ -20,6 +20,7 @@ export interface RunOptions {
|
|
20
20
|
batch: boolean;
|
21
21
|
useAgents: boolean;
|
22
22
|
excludeTaskDependencies: boolean;
|
23
|
+
skipSync: boolean;
|
23
24
|
}
|
24
25
|
export declare function withRunOptions<T>(yargs: Argv<T>): Argv<T & RunOptions>;
|
25
26
|
export declare function withTargetAndConfigurationOption(yargs: Argv, demandOption?: boolean): Argv<{
|