nx 19.2.0-canary.20240604-0594deb → 19.2.0-rc.0
Sign up to get free protection for your applications and to get access to all the features.
- package/migrations.json +6 -0
- package/package.json +13 -12
- package/release/changelog-renderer/index.d.ts +6 -3
- package/release/changelog-renderer/index.js +53 -50
- package/schemas/nx-schema.json +8 -0
- package/src/command-line/add/add.d.ts +1 -1
- package/src/command-line/add/command-object.js +3 -1
- package/src/command-line/affected/command-object.js +10 -5
- package/src/command-line/deprecated/command-objects.js +12 -6
- package/src/command-line/examples.js +18 -0
- package/src/command-line/generate/generate.d.ts +1 -1
- package/src/command-line/migrate/migrate.d.ts +1 -1
- package/src/command-line/new/new.d.ts +1 -1
- package/src/command-line/release/changelog.d.ts +17 -1
- package/src/command-line/release/changelog.js +305 -76
- package/src/command-line/release/command-object.d.ts +14 -5
- package/src/command-line/release/command-object.js +52 -24
- package/src/command-line/release/config/config.js +38 -6
- package/src/command-line/release/config/filter-release-groups.d.ts +3 -1
- package/src/command-line/release/config/filter-release-groups.js +1 -0
- package/src/command-line/release/config/version-plans.d.ts +24 -0
- package/src/command-line/release/config/version-plans.js +184 -0
- package/src/command-line/release/plan.d.ts +3 -0
- package/src/command-line/release/plan.js +184 -0
- package/src/command-line/release/publish.d.ts +1 -1
- package/src/command-line/release/release.d.ts +1 -1
- package/src/command-line/release/release.js +40 -0
- package/src/command-line/release/utils/git.d.ts +10 -2
- package/src/command-line/release/utils/git.js +45 -10
- package/src/command-line/release/utils/shared.d.ts +12 -2
- package/src/command-line/release/utils/shared.js +3 -2
- package/src/command-line/release/version.d.ts +3 -2
- package/src/command-line/release/version.js +43 -5
- package/src/command-line/repair/repair.d.ts +1 -1
- package/src/command-line/reset/command-object.d.ts +6 -1
- package/src/command-line/reset/command-object.js +15 -2
- package/src/command-line/reset/reset.d.ts +2 -1
- package/src/command-line/reset/reset.js +98 -16
- package/src/command-line/run/command-object.js +6 -3
- package/src/command-line/run/run.d.ts +2 -2
- package/src/command-line/run-many/command-object.js +6 -3
- package/src/command-line/show/command-object.js +6 -6
- package/src/config/misc-interfaces.d.ts +15 -3
- package/src/config/nx-json.d.ts +11 -0
- package/src/daemon/tmp-dir.js +1 -1
- package/src/devkit-exports.d.ts +1 -1
- package/src/migrations/update-19-2-0/move-workspace-data-directory.d.ts +4 -0
- package/src/migrations/update-19-2-0/move-workspace-data-directory.js +34 -0
- package/src/plugins/js/index.js +2 -2
- package/src/plugins/js/project-graph/affected/lock-file-changes.js +11 -0
- package/src/plugins/js/project-graph/affected/npm-packages.js +12 -0
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +3 -11
- package/src/plugins/js/utils/config.js +4 -0
- package/src/plugins/js/utils/register.d.ts +4 -3
- package/src/plugins/js/utils/register.js +47 -4
- package/src/project-graph/affected/affected-project-graph.js +6 -6
- package/src/project-graph/nx-deps-cache.js +6 -6
- package/src/project-graph/plugins/loader.js +1 -1
- package/src/tasks-runner/task-env.js +12 -0
- package/src/utils/cache-directory.d.ts +1 -1
- package/src/utils/cache-directory.js +13 -6
- package/src/utils/get-package-name-from-import-path.d.ts +1 -0
- package/src/utils/get-package-name-from-import-path.js +18 -0
- package/src/utils/package-json.d.ts +1 -0
- package/src/utils/package-manager.js +42 -9
- package/src/utils/params.d.ts +1 -1
- package/src/utils/params.js +5 -1
@@ -0,0 +1,184 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.releasePlan = exports.releasePlanCLIHandler = void 0;
|
4
|
+
const enquirer_1 = require("enquirer");
|
5
|
+
const fs_extra_1 = require("fs-extra");
|
6
|
+
const path_1 = require("path");
|
7
|
+
const semver_1 = require("semver");
|
8
|
+
const nx_json_1 = require("../../config/nx-json");
|
9
|
+
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
10
|
+
const project_graph_1 = require("../../project-graph/project-graph");
|
11
|
+
const output_1 = require("../../utils/output");
|
12
|
+
const params_1 = require("../../utils/params");
|
13
|
+
const config_1 = require("./config/config");
|
14
|
+
const filter_release_groups_1 = require("./config/filter-release-groups");
|
15
|
+
const version_plans_1 = require("./config/version-plans");
|
16
|
+
const git_1 = require("./utils/git");
|
17
|
+
const print_changes_1 = require("./utils/print-changes");
|
18
|
+
const releasePlanCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => releasePlan(args));
|
19
|
+
exports.releasePlanCLIHandler = releasePlanCLIHandler;
|
20
|
+
async function releasePlan(args) {
|
21
|
+
const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
|
22
|
+
const nxJson = (0, nx_json_1.readNxJson)();
|
23
|
+
if (args.verbose) {
|
24
|
+
process.env.NX_VERBOSE_LOGGING = 'true';
|
25
|
+
}
|
26
|
+
// Apply default configuration to any optional user configuration
|
27
|
+
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), nxJson.release);
|
28
|
+
if (configError) {
|
29
|
+
return await (0, config_1.handleNxReleaseConfigError)(configError);
|
30
|
+
}
|
31
|
+
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
32
|
+
if (filterError) {
|
33
|
+
output_1.output.error(filterError);
|
34
|
+
process.exit(1);
|
35
|
+
}
|
36
|
+
const versionPlanBumps = {};
|
37
|
+
const setBumpIfNotNone = (projectOrGroup, version) => {
|
38
|
+
if (version !== 'none') {
|
39
|
+
versionPlanBumps[projectOrGroup] = version;
|
40
|
+
}
|
41
|
+
};
|
42
|
+
if (args.message) {
|
43
|
+
const message = (0, git_1.parseConventionalCommitsMessage)(args.message);
|
44
|
+
if (!message) {
|
45
|
+
output_1.output.error({
|
46
|
+
title: 'Changelog message is not in conventional commits format.',
|
47
|
+
bodyLines: [
|
48
|
+
'Please ensure your message is in the form of:',
|
49
|
+
' type(optional scope): description',
|
50
|
+
'',
|
51
|
+
'For example:',
|
52
|
+
' feat(pkg-b): add new feature',
|
53
|
+
' fix(pkg-a): correct a bug',
|
54
|
+
' chore: update build process',
|
55
|
+
' fix(core)!: breaking change in core package',
|
56
|
+
],
|
57
|
+
});
|
58
|
+
process.exit(1);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
if (releaseGroups[0].name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP) {
|
62
|
+
const group = releaseGroups[0];
|
63
|
+
if (group.projectsRelationship === 'independent') {
|
64
|
+
for (const project of group.projects) {
|
65
|
+
setBumpIfNotNone(project, args.bump ||
|
66
|
+
(await promptForVersion(`How do you want to bump the version of the project "${project}"?`)));
|
67
|
+
}
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
// TODO: use project names instead of the implicit default release group name? (though this might be confusing, as users might think they can just delete one of the project bumps to change the behavior to independent versioning)
|
71
|
+
setBumpIfNotNone(group.name, args.bump ||
|
72
|
+
(await promptForVersion(`How do you want to bump the versions of all projects?`)));
|
73
|
+
}
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
for (const group of releaseGroups) {
|
77
|
+
if (group.projectsRelationship === 'independent') {
|
78
|
+
for (const project of releaseGroupToFilteredProjects.get(group)) {
|
79
|
+
setBumpIfNotNone(project, args.bump ||
|
80
|
+
(await promptForVersion(`How do you want to bump the version of the project "${project}" within group "${group.name}"?`)));
|
81
|
+
}
|
82
|
+
}
|
83
|
+
else {
|
84
|
+
setBumpIfNotNone(group.name, args.bump ||
|
85
|
+
(await promptForVersion(`How do you want to bump the versions of the projects in the group "${group.name}"?`)));
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
if (!Object.keys(versionPlanBumps).length) {
|
90
|
+
output_1.output.warn({
|
91
|
+
title: 'No version bumps were selected so no version plan file was created.',
|
92
|
+
});
|
93
|
+
return 0;
|
94
|
+
}
|
95
|
+
const versionPlanMessage = args.message || (await promptForMessage());
|
96
|
+
const versionPlanFileContent = getVersionPlanFileContent(versionPlanBumps, versionPlanMessage);
|
97
|
+
const versionPlanFileName = `version-plan-${new Date().getTime()}.md`;
|
98
|
+
if (args.dryRun) {
|
99
|
+
output_1.output.logSingleLine(`Would create version plan file "${versionPlanFileName}", but --dry-run was set.`);
|
100
|
+
(0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
|
101
|
+
}
|
102
|
+
else {
|
103
|
+
output_1.output.logSingleLine(`Creating version plan file "${versionPlanFileName}"`);
|
104
|
+
(0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
|
105
|
+
const versionPlansAbsolutePath = (0, version_plans_1.getVersionPlansAbsolutePath)();
|
106
|
+
await (0, fs_extra_1.ensureDir)(versionPlansAbsolutePath);
|
107
|
+
await (0, fs_extra_1.writeFile)((0, path_1.join)(versionPlansAbsolutePath, versionPlanFileName), versionPlanFileContent);
|
108
|
+
}
|
109
|
+
return 0;
|
110
|
+
}
|
111
|
+
exports.releasePlan = releasePlan;
|
112
|
+
async function promptForVersion(message) {
|
113
|
+
try {
|
114
|
+
const reply = await (0, enquirer_1.prompt)([
|
115
|
+
{
|
116
|
+
name: 'version',
|
117
|
+
message,
|
118
|
+
type: 'select',
|
119
|
+
choices: [...semver_1.RELEASE_TYPES, 'none'],
|
120
|
+
},
|
121
|
+
]);
|
122
|
+
return reply.version;
|
123
|
+
}
|
124
|
+
catch (e) {
|
125
|
+
output_1.output.log({
|
126
|
+
title: 'Cancelled version plan creation.',
|
127
|
+
});
|
128
|
+
process.exit(0);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
async function promptForMessage() {
|
132
|
+
let message;
|
133
|
+
do {
|
134
|
+
message = await _promptForMessage();
|
135
|
+
} while (!message);
|
136
|
+
return message;
|
137
|
+
}
|
138
|
+
// TODO: support non-conventional commits messages (will require significant changelog renderer changes)
|
139
|
+
async function _promptForMessage() {
|
140
|
+
try {
|
141
|
+
const reply = await (0, enquirer_1.prompt)([
|
142
|
+
{
|
143
|
+
name: 'message',
|
144
|
+
message: 'What changelog message would you like associated with this change?',
|
145
|
+
type: 'input',
|
146
|
+
},
|
147
|
+
]);
|
148
|
+
const conventionalCommitsMessage = (0, git_1.parseConventionalCommitsMessage)(reply.message);
|
149
|
+
if (!conventionalCommitsMessage) {
|
150
|
+
output_1.output.warn({
|
151
|
+
title: 'Changelog message is not in conventional commits format.',
|
152
|
+
bodyLines: [
|
153
|
+
'Please ensure your message is in the form of:',
|
154
|
+
' type(optional scope): description',
|
155
|
+
'',
|
156
|
+
'For example:',
|
157
|
+
' feat(pkg-b): add new feature',
|
158
|
+
' fix(pkg-a): correct a bug',
|
159
|
+
' chore: update build process',
|
160
|
+
' fix(core)!: breaking change in core package',
|
161
|
+
],
|
162
|
+
});
|
163
|
+
return null;
|
164
|
+
}
|
165
|
+
return reply.message;
|
166
|
+
}
|
167
|
+
catch (e) {
|
168
|
+
output_1.output.log({
|
169
|
+
title: 'Cancelled version plan creation.',
|
170
|
+
});
|
171
|
+
process.exit(0);
|
172
|
+
}
|
173
|
+
}
|
174
|
+
function getVersionPlanFileContent(bumps, message) {
|
175
|
+
return `---
|
176
|
+
${Object.entries(bumps)
|
177
|
+
.filter(([_, version]) => version !== 'none')
|
178
|
+
.map(([projectOrGroup, version]) => `${projectOrGroup}: ${version}`)
|
179
|
+
.join('\n')}
|
180
|
+
---
|
181
|
+
|
182
|
+
${message}
|
183
|
+
`;
|
184
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { PublishOptions } from './command-object';
|
2
|
-
export declare const releasePublishCLIHandler: (args: PublishOptions) => Promise<
|
2
|
+
export declare const releasePublishCLIHandler: (args: PublishOptions) => Promise<number>;
|
3
3
|
/**
|
4
4
|
* NOTE: This function is also exported for programmatic usage and forms part of the public API
|
5
5
|
* of Nx. We intentionally do not wrap the implementation with handleErrors because users need
|
@@ -1,4 +1,4 @@
|
|
1
1
|
import { ReleaseOptions, VersionOptions } from './command-object';
|
2
2
|
import { NxReleaseVersionResult } from './version';
|
3
|
-
export declare const releaseCLIHandler: (args: VersionOptions) => Promise<
|
3
|
+
export declare const releaseCLIHandler: (args: VersionOptions) => Promise<number>;
|
4
4
|
export declare function release(args: ReleaseOptions): Promise<NxReleaseVersionResult | number>;
|
@@ -2,6 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.release = exports.releaseCLIHandler = void 0;
|
4
4
|
const enquirer_1 = require("enquirer");
|
5
|
+
const fs_extra_1 = require("fs-extra");
|
5
6
|
const nx_json_1 = require("../../config/nx-json");
|
6
7
|
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
7
8
|
const project_graph_1 = require("../../project-graph/project-graph");
|
@@ -10,6 +11,7 @@ const params_1 = require("../../utils/params");
|
|
10
11
|
const changelog_1 = require("./changelog");
|
11
12
|
const config_1 = require("./config/config");
|
12
13
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
14
|
+
const version_plans_1 = require("./config/version-plans");
|
13
15
|
const publish_1 = require("./publish");
|
14
16
|
const git_1 = require("./utils/git");
|
15
17
|
const github_1 = require("./utils/github");
|
@@ -52,6 +54,7 @@ async function release(args) {
|
|
52
54
|
stageChanges: shouldStage,
|
53
55
|
gitCommit: false,
|
54
56
|
gitTag: false,
|
57
|
+
deleteVersionPlans: false,
|
55
58
|
});
|
56
59
|
const changelogResult = await (0, changelog_1.releaseChangelog)({
|
57
60
|
...args,
|
@@ -61,12 +64,49 @@ async function release(args) {
|
|
61
64
|
gitCommit: false,
|
62
65
|
gitTag: false,
|
63
66
|
createRelease: false,
|
67
|
+
deleteVersionPlans: false,
|
64
68
|
});
|
65
69
|
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
66
70
|
if (filterError) {
|
67
71
|
output_1.output.error(filterError);
|
68
72
|
process.exit(1);
|
69
73
|
}
|
74
|
+
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
75
|
+
(0, version_plans_1.setVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
76
|
+
const planFiles = new Set();
|
77
|
+
releaseGroups.forEach((group) => {
|
78
|
+
if (group.versionPlans) {
|
79
|
+
if (group.name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP) {
|
80
|
+
output_1.output.logSingleLine(`Removing version plan files`);
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
output_1.output.logSingleLine(`Removing version plan files for group ${group.name}`);
|
84
|
+
}
|
85
|
+
group.versionPlans.forEach((plan) => {
|
86
|
+
if (!args.dryRun) {
|
87
|
+
(0, fs_extra_1.removeSync)(plan.absolutePath);
|
88
|
+
if (args.verbose) {
|
89
|
+
console.log(`Removing ${plan.relativePath}`);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
else {
|
93
|
+
if (args.verbose) {
|
94
|
+
console.log(`Would remove ${plan.relativePath}, but --dry-run was set`);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
planFiles.add(plan.relativePath);
|
98
|
+
});
|
99
|
+
}
|
100
|
+
});
|
101
|
+
const deletedFiles = Array.from(planFiles);
|
102
|
+
if (deletedFiles.length > 0) {
|
103
|
+
await (0, git_1.gitAdd)({
|
104
|
+
changedFiles: [],
|
105
|
+
deletedFiles,
|
106
|
+
dryRun: args.dryRun,
|
107
|
+
verbose: args.verbose,
|
108
|
+
});
|
109
|
+
}
|
70
110
|
if (shouldCommit) {
|
71
111
|
output_1.output.logSingleLine(`Committing changes with git`);
|
72
112
|
const commitMessage = nxReleaseConfig.git.commitMessage;
|
@@ -27,8 +27,10 @@ export declare function getLatestGitTagForPattern(releaseTagPattern: string, add
|
|
27
27
|
extractedVersion: string;
|
28
28
|
} | null>;
|
29
29
|
export declare function getGitDiff(from: string | undefined, to?: string): Promise<RawGitCommit[]>;
|
30
|
-
export declare function
|
31
|
-
|
30
|
+
export declare function getChangedTrackedFiles(): Promise<Set<string>>;
|
31
|
+
export declare function gitAdd({ changedFiles, deletedFiles, dryRun, verbose, logFn, }: {
|
32
|
+
changedFiles?: string[];
|
33
|
+
deletedFiles?: string[];
|
32
34
|
dryRun?: boolean;
|
33
35
|
verbose?: boolean;
|
34
36
|
logFn?: (...messages: string[]) => void;
|
@@ -54,6 +56,12 @@ export declare function gitPush({ gitRemote, dryRun, verbose, }: {
|
|
54
56
|
verbose?: boolean;
|
55
57
|
}): Promise<void>;
|
56
58
|
export declare function parseCommits(commits: RawGitCommit[]): GitCommit[];
|
59
|
+
export declare function parseConventionalCommitsMessage(message: string): {
|
60
|
+
type: string;
|
61
|
+
scope: string;
|
62
|
+
description: string;
|
63
|
+
breaking: boolean;
|
64
|
+
} | null;
|
57
65
|
export declare function parseGitCommit(commit: RawGitCommit): GitCommit | null;
|
58
66
|
export declare function getCommitHash(ref: string): Promise<string>;
|
59
67
|
export declare function getFirstGitCommit(): Promise<string>;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.getFirstGitCommit = exports.getCommitHash = exports.parseGitCommit = exports.parseCommits = exports.gitPush = exports.gitTag = exports.gitCommit = exports.gitAdd = exports.getGitDiff = exports.getLatestGitTagForPattern = void 0;
|
3
|
+
exports.getFirstGitCommit = exports.getCommitHash = exports.parseGitCommit = exports.parseConventionalCommitsMessage = exports.parseCommits = exports.gitPush = exports.gitTag = exports.gitCommit = exports.gitAdd = exports.getChangedTrackedFiles = exports.getGitDiff = exports.getLatestGitTagForPattern = void 0;
|
4
4
|
/**
|
5
5
|
* Special thanks to changelogen for the original inspiration for many of these utilities:
|
6
6
|
* https://github.com/unjs/changelogen
|
@@ -97,11 +97,17 @@ async function getGitDiff(from, to = 'HEAD') {
|
|
97
97
|
});
|
98
98
|
}
|
99
99
|
exports.getGitDiff = getGitDiff;
|
100
|
-
async function
|
100
|
+
async function getChangedTrackedFiles() {
|
101
|
+
const result = await (0, exec_command_1.execCommand)('git', ['status', '--porcelain']);
|
102
|
+
const lines = result.split('\n').filter((l) => l.trim().length > 0);
|
103
|
+
return new Set(lines.map((l) => l.substring(3)));
|
104
|
+
}
|
105
|
+
exports.getChangedTrackedFiles = getChangedTrackedFiles;
|
106
|
+
async function gitAdd({ changedFiles, deletedFiles, dryRun, verbose, logFn, }) {
|
101
107
|
logFn = logFn || console.log;
|
102
108
|
let ignoredFiles = [];
|
103
109
|
let filesToAdd = [];
|
104
|
-
for (const f of changedFiles) {
|
110
|
+
for (const f of changedFiles ?? []) {
|
105
111
|
const isFileIgnored = await isIgnored(f);
|
106
112
|
if (isFileIgnored) {
|
107
113
|
ignoredFiles.push(f);
|
@@ -110,12 +116,28 @@ async function gitAdd({ changedFiles, dryRun, verbose, logFn, }) {
|
|
110
116
|
filesToAdd.push(f);
|
111
117
|
}
|
112
118
|
}
|
119
|
+
if (deletedFiles?.length > 0) {
|
120
|
+
const changedTrackedFiles = await getChangedTrackedFiles();
|
121
|
+
for (const f of deletedFiles ?? []) {
|
122
|
+
const isFileIgnored = await isIgnored(f);
|
123
|
+
if (isFileIgnored) {
|
124
|
+
ignoredFiles.push(f);
|
125
|
+
// git add will fail if trying to add an untracked file that doesn't exist
|
126
|
+
}
|
127
|
+
else if (changedTrackedFiles.has(f)) {
|
128
|
+
filesToAdd.push(f);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
113
132
|
if (verbose && ignoredFiles.length) {
|
114
133
|
logFn(`Will not add the following files because they are ignored by git:`);
|
115
134
|
ignoredFiles.forEach((f) => logFn(f));
|
116
135
|
}
|
117
136
|
if (!filesToAdd.length) {
|
118
|
-
|
137
|
+
if (!dryRun) {
|
138
|
+
logFn('\nNo files to stage. Skipping git add.');
|
139
|
+
}
|
140
|
+
// if this is a dry run, it's possible that there would have been actual files to add, so it's deceptive to say "No files to stage".
|
119
141
|
return;
|
120
142
|
}
|
121
143
|
const commandArgs = ['add', ...filesToAdd];
|
@@ -236,6 +258,19 @@ function parseCommits(commits) {
|
|
236
258
|
return commits.map((commit) => parseGitCommit(commit)).filter(Boolean);
|
237
259
|
}
|
238
260
|
exports.parseCommits = parseCommits;
|
261
|
+
function parseConventionalCommitsMessage(message) {
|
262
|
+
const match = message.match(ConventionalCommitRegex);
|
263
|
+
if (!match) {
|
264
|
+
return null;
|
265
|
+
}
|
266
|
+
return {
|
267
|
+
type: match.groups.type || '',
|
268
|
+
scope: match.groups.scope || '',
|
269
|
+
description: match.groups.description || '',
|
270
|
+
breaking: Boolean(match.groups.breaking),
|
271
|
+
};
|
272
|
+
}
|
273
|
+
exports.parseConventionalCommitsMessage = parseConventionalCommitsMessage;
|
239
274
|
// https://www.conventionalcommits.org/en/v1.0.0/
|
240
275
|
// https://regex101.com/r/FSfNvA/1
|
241
276
|
const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
|
@@ -245,13 +280,13 @@ const IssueRE = /(#\d+)/gm;
|
|
245
280
|
const ChangedFileRegex = /(A|M|D|R\d*|C\d*)\t([^\t\n]*)\t?(.*)?/gm;
|
246
281
|
const RevertHashRE = /This reverts commit (?<hash>[\da-f]{40})./gm;
|
247
282
|
function parseGitCommit(commit) {
|
248
|
-
const
|
249
|
-
if (!
|
283
|
+
const parsedMessage = parseConventionalCommitsMessage(commit.message);
|
284
|
+
if (!parsedMessage) {
|
250
285
|
return null;
|
251
286
|
}
|
252
|
-
const scope =
|
253
|
-
const isBreaking =
|
254
|
-
let description =
|
287
|
+
const scope = parsedMessage.scope;
|
288
|
+
const isBreaking = parsedMessage.breaking || commit.body.includes('BREAKING CHANGE:');
|
289
|
+
let description = parsedMessage.description;
|
255
290
|
// Extract references from message
|
256
291
|
const references = [];
|
257
292
|
for (const m of description.matchAll(PullRequestRE)) {
|
@@ -265,7 +300,7 @@ function parseGitCommit(commit) {
|
|
265
300
|
references.push({ value: commit.shortHash, type: 'hash' });
|
266
301
|
// Remove references and normalize
|
267
302
|
description = description.replace(PullRequestRE, '').trim();
|
268
|
-
let type =
|
303
|
+
let type = parsedMessage.type;
|
269
304
|
// Extract any reverted hashes, if applicable
|
270
305
|
const revertedHashes = [];
|
271
306
|
const matchedHashes = commit.body.matchAll(RevertHashRE);
|
@@ -9,7 +9,10 @@ export type ReleaseVersionGeneratorResult = {
|
|
9
9
|
dryRun?: boolean;
|
10
10
|
verbose?: boolean;
|
11
11
|
generatorOptions?: Record<string, unknown>;
|
12
|
-
}) => Promise<string[]
|
12
|
+
}) => Promise<string[] | {
|
13
|
+
changedFiles: string[];
|
14
|
+
deletedFiles: string[];
|
15
|
+
}>;
|
13
16
|
};
|
14
17
|
export type VersionData = Record<string, {
|
15
18
|
/**
|
@@ -36,7 +39,14 @@ export declare class ReleaseVersion {
|
|
36
39
|
projectName?: string;
|
37
40
|
});
|
38
41
|
}
|
39
|
-
export declare function commitChanges(changedFiles
|
42
|
+
export declare function commitChanges({ changedFiles, deletedFiles, isDryRun, isVerbose, gitCommitMessages, gitCommitArgs, }: {
|
43
|
+
changedFiles?: string[];
|
44
|
+
deletedFiles?: string[];
|
45
|
+
isDryRun?: boolean;
|
46
|
+
isVerbose?: boolean;
|
47
|
+
gitCommitMessages?: string[];
|
48
|
+
gitCommitArgs?: string;
|
49
|
+
}): Promise<void>;
|
40
50
|
export declare function createCommitMessageValues(releaseGroups: ReleaseGroupWithName[], releaseGroupToFilteredProjects: Map<ReleaseGroupWithName, Set<string>>, versionData: VersionData, commitMessage: string): string[];
|
41
51
|
export declare function createGitTagValues(releaseGroups: ReleaseGroupWithName[], releaseGroupToFilteredProjects: Map<ReleaseGroupWithName, Set<string>>, versionData: VersionData): string[];
|
42
52
|
export declare function handleDuplicateGitTags(gitTagValues: string[]): void;
|
@@ -26,13 +26,14 @@ class ReleaseVersion {
|
|
26
26
|
}
|
27
27
|
}
|
28
28
|
exports.ReleaseVersion = ReleaseVersion;
|
29
|
-
async function commitChanges(changedFiles, isDryRun, isVerbose, gitCommitMessages, gitCommitArgs) {
|
30
|
-
if (!changedFiles
|
29
|
+
async function commitChanges({ changedFiles, deletedFiles, isDryRun, isVerbose, gitCommitMessages, gitCommitArgs, }) {
|
30
|
+
if (!changedFiles?.length && !deletedFiles?.length) {
|
31
31
|
throw new Error('Error: No changed files to commit');
|
32
32
|
}
|
33
33
|
output_1.output.logSingleLine(`Committing changes with git`);
|
34
34
|
await (0, git_1.gitAdd)({
|
35
35
|
changedFiles,
|
36
|
+
deletedFiles,
|
36
37
|
dryRun: isDryRun,
|
37
38
|
verbose: isVerbose,
|
38
39
|
});
|
@@ -11,7 +11,7 @@ export interface ReleaseVersionGeneratorSchema {
|
|
11
11
|
releaseGroup: ReleaseGroupWithName;
|
12
12
|
projectGraph: ProjectGraph;
|
13
13
|
specifier?: string;
|
14
|
-
specifierSource?: 'prompt' | 'conventional-commits';
|
14
|
+
specifierSource?: 'prompt' | 'conventional-commits' | 'version-plans';
|
15
15
|
preid?: string;
|
16
16
|
packageRoot?: string;
|
17
17
|
currentVersionResolver?: 'registry' | 'disk' | 'git-tag';
|
@@ -23,6 +23,7 @@ export interface ReleaseVersionGeneratorSchema {
|
|
23
23
|
installArgs?: string;
|
24
24
|
installIgnoreScripts?: boolean;
|
25
25
|
conventionalCommitsConfig?: NxReleaseConfig['conventionalCommits'];
|
26
|
+
deleteVersionPlans?: boolean;
|
26
27
|
/**
|
27
28
|
* 'auto' allows users to opt into dependents being updated (a patch version bump) when a dependency is versioned.
|
28
29
|
* This is only applicable to independently released projects.
|
@@ -43,7 +44,7 @@ export interface NxReleaseVersionResult {
|
|
43
44
|
workspaceVersion: (string | null) | undefined;
|
44
45
|
projectsVersionData: VersionData;
|
45
46
|
}
|
46
|
-
export declare const releaseVersionCLIHandler: (args: VersionOptions) => Promise<
|
47
|
+
export declare const releaseVersionCLIHandler: (args: VersionOptions) => Promise<number>;
|
47
48
|
/**
|
48
49
|
* NOTE: This function is also exported for programmatic usage and forms part of the public API
|
49
50
|
* of Nx. We intentionally do not wrap the implementation with handleErrors because users need
|
@@ -17,6 +17,7 @@ const generate_1 = require("../generate/generate");
|
|
17
17
|
const generator_utils_1 = require("../generate/generator-utils");
|
18
18
|
const config_1 = require("./config/config");
|
19
19
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
20
|
+
const version_plans_1 = require("./config/version-plans");
|
20
21
|
const batch_projects_by_generator_config_1 = require("./utils/batch-projects-by-generator-config");
|
21
22
|
const git_1 = require("./utils/git");
|
22
23
|
const print_changes_1 = require("./utils/print-changes");
|
@@ -69,6 +70,12 @@ async function releaseVersion(args) {
|
|
69
70
|
output_1.output.error(filterError);
|
70
71
|
process.exit(1);
|
71
72
|
}
|
73
|
+
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
74
|
+
(0, version_plans_1.setVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
75
|
+
if (args.deleteVersionPlans === undefined) {
|
76
|
+
// default to not delete version plans after versioning as they may be needed for changelog generation
|
77
|
+
args.deleteVersionPlans = false;
|
78
|
+
}
|
72
79
|
runPreVersionCommand(nxReleaseConfig.version.preVersionCommand, {
|
73
80
|
dryRun: args.dryRun,
|
74
81
|
verbose: args.verbose,
|
@@ -82,6 +89,7 @@ async function releaseVersion(args) {
|
|
82
89
|
* and need to get staged and committed as part of the existing commit, if applicable.
|
83
90
|
*/
|
84
91
|
const additionalChangedFiles = new Set();
|
92
|
+
const additionalDeletedFiles = new Set();
|
85
93
|
if (args.projects?.length) {
|
86
94
|
/**
|
87
95
|
* Run versioning for all remaining release groups and filtered projects within them
|
@@ -104,7 +112,7 @@ async function releaseVersion(args) {
|
|
104
112
|
const generatorCallback = await runVersionOnProjects(projectGraph, nxJson, args, tree, generatorData, args.generatorOptionsOverrides, projectNames, releaseGroup, versionData, nxReleaseConfig.conventionalCommits);
|
105
113
|
// Capture the callback so that we can run it after flushing the changes to disk
|
106
114
|
generatorCallbacks.push(async () => {
|
107
|
-
const
|
115
|
+
const result = await generatorCallback(tree, {
|
108
116
|
dryRun: !!args.dryRun,
|
109
117
|
verbose: !!args.verbose,
|
110
118
|
generatorOptions: {
|
@@ -112,7 +120,9 @@ async function releaseVersion(args) {
|
|
112
120
|
...args.generatorOptionsOverrides,
|
113
121
|
},
|
114
122
|
});
|
123
|
+
const { changedFiles, deletedFiles } = parseGeneratorCallbackResult(result);
|
115
124
|
changedFiles.forEach((f) => additionalChangedFiles.add(f));
|
125
|
+
deletedFiles.forEach((f) => additionalDeletedFiles.add(f));
|
116
126
|
});
|
117
127
|
}
|
118
128
|
}
|
@@ -138,7 +148,14 @@ async function releaseVersion(args) {
|
|
138
148
|
};
|
139
149
|
}
|
140
150
|
if (args.gitCommit ?? nxReleaseConfig.version.git.commit) {
|
141
|
-
await (0, shared_1.commitChanges)(
|
151
|
+
await (0, shared_1.commitChanges)({
|
152
|
+
changedFiles,
|
153
|
+
deletedFiles: Array.from(additionalDeletedFiles),
|
154
|
+
isDryRun: !!args.dryRun,
|
155
|
+
isVerbose: !!args.verbose,
|
156
|
+
gitCommitMessages: (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, commitMessage),
|
157
|
+
gitCommitArgs: args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs,
|
158
|
+
});
|
142
159
|
}
|
143
160
|
else if (args.stageChanges ?? nxReleaseConfig.version.git.stageChanges) {
|
144
161
|
output_1.output.logSingleLine(`Staging changed files with git`);
|
@@ -186,7 +203,7 @@ async function releaseVersion(args) {
|
|
186
203
|
const generatorCallback = await runVersionOnProjects(projectGraph, nxJson, args, tree, generatorData, args.generatorOptionsOverrides, projectNames, releaseGroup, versionData, nxReleaseConfig.conventionalCommits);
|
187
204
|
// Capture the callback so that we can run it after flushing the changes to disk
|
188
205
|
generatorCallbacks.push(async () => {
|
189
|
-
const
|
206
|
+
const result = await generatorCallback(tree, {
|
190
207
|
dryRun: !!args.dryRun,
|
191
208
|
verbose: !!args.verbose,
|
192
209
|
generatorOptions: {
|
@@ -194,7 +211,9 @@ async function releaseVersion(args) {
|
|
194
211
|
...args.generatorOptionsOverrides,
|
195
212
|
},
|
196
213
|
});
|
214
|
+
const { changedFiles, deletedFiles } = parseGeneratorCallbackResult(result);
|
197
215
|
changedFiles.forEach((f) => additionalChangedFiles.add(f));
|
216
|
+
deletedFiles.forEach((f) => additionalDeletedFiles.add(f));
|
198
217
|
});
|
199
218
|
}
|
200
219
|
}
|
@@ -228,7 +247,14 @@ async function releaseVersion(args) {
|
|
228
247
|
};
|
229
248
|
}
|
230
249
|
if (args.gitCommit ?? nxReleaseConfig.version.git.commit) {
|
231
|
-
await (0, shared_1.commitChanges)(
|
250
|
+
await (0, shared_1.commitChanges)({
|
251
|
+
changedFiles,
|
252
|
+
deletedFiles: Array.from(additionalDeletedFiles),
|
253
|
+
isDryRun: !!args.dryRun,
|
254
|
+
isVerbose: !!args.verbose,
|
255
|
+
gitCommitMessages: (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, commitMessage),
|
256
|
+
gitCommitArgs: args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs,
|
257
|
+
});
|
232
258
|
}
|
233
259
|
else if (args.stageChanges ?? nxReleaseConfig.version.git.stageChanges) {
|
234
260
|
output_1.output.logSingleLine(`Staging changed files with git`);
|
@@ -279,6 +305,7 @@ async function runVersionOnProjects(projectGraph, nxJson, args, tree, generatorD
|
|
279
305
|
releaseGroup,
|
280
306
|
firstRelease: args.firstRelease ?? false,
|
281
307
|
conventionalCommitsConfig,
|
308
|
+
deleteVersionPlans: args.deleteVersionPlans,
|
282
309
|
};
|
283
310
|
// Apply generator defaults from schema.json file etc
|
284
311
|
const combinedOpts = await (0, params_1.combineOptionsForGenerator)(generatorOptions, generatorData.collectionName, generatorData.normalizedGeneratorName, (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph), nxJson, generatorData.schema, false, null, (0, node_path_1.relative)(process.cwd(), workspace_root_1.workspaceRoot), args.verbose);
|
@@ -306,7 +333,7 @@ function printAndFlushChanges(tree, isDryRun) {
|
|
306
333
|
const currentContentsOnDisk = (0, node_fs_1.readFileSync)((0, path_1.joinPathFragments)(tree.root, f.path)).toString();
|
307
334
|
(0, print_changes_1.printDiff)(currentContentsOnDisk, f.content?.toString() || '');
|
308
335
|
}
|
309
|
-
else if (f.type === 'DELETE') {
|
336
|
+
else if (f.type === 'DELETE' && !f.path.includes('.nx')) {
|
310
337
|
throw new Error('Unexpected DELETE change, please report this as an issue');
|
311
338
|
}
|
312
339
|
});
|
@@ -395,3 +422,14 @@ function runPreVersionCommand(preVersionCommand, { dryRun, verbose }) {
|
|
395
422
|
process.exit(1);
|
396
423
|
}
|
397
424
|
}
|
425
|
+
function parseGeneratorCallbackResult(result) {
|
426
|
+
if (Array.isArray(result)) {
|
427
|
+
return {
|
428
|
+
changedFiles: result,
|
429
|
+
deletedFiles: [],
|
430
|
+
};
|
431
|
+
}
|
432
|
+
else {
|
433
|
+
return result;
|
434
|
+
}
|
435
|
+
}
|
@@ -1,2 +1,7 @@
|
|
1
1
|
import { CommandModule } from 'yargs';
|
2
|
-
export
|
2
|
+
export type ResetCommandOptions = {
|
3
|
+
onlyCache?: boolean;
|
4
|
+
onlyDaemon?: boolean;
|
5
|
+
onlyWorkspaceData?: boolean;
|
6
|
+
};
|
7
|
+
export declare const yargsResetCommand: CommandModule<Record<string, unknown>, ResetCommandOptions>;
|
@@ -3,7 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.yargsResetCommand = void 0;
|
4
4
|
exports.yargsResetCommand = {
|
5
5
|
command: 'reset',
|
6
|
-
describe: 'Clears
|
6
|
+
describe: 'Clears cached Nx artifacts and metadata about the workspace and shuts down the Nx Daemon.',
|
7
7
|
aliases: ['clear-cache'],
|
8
|
-
|
8
|
+
builder: (yargs) => yargs
|
9
|
+
.option('onlyCache', {
|
10
|
+
description: 'Clears the Nx cache directory. This will remove all local cache entries for tasks, but will not affect the remote cache.',
|
11
|
+
type: 'boolean',
|
12
|
+
})
|
13
|
+
.option('onlyDaemon', {
|
14
|
+
description: 'Stops the Nx Daemon, it will be restarted fresh when the next Nx command is run.',
|
15
|
+
type: 'boolean',
|
16
|
+
})
|
17
|
+
.option('onlyWorkspaceData', {
|
18
|
+
description: 'Clears the workspace data directory. Used by Nx to store cached data about the current workspace (e.g. partial results, incremental data, etc)',
|
19
|
+
type: 'boolean',
|
20
|
+
}),
|
21
|
+
handler: async (argv) => (await Promise.resolve().then(() => require('./reset'))).resetHandler(argv),
|
9
22
|
};
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
import { ResetCommandOptions } from './command-object';
|
2
|
+
export declare function resetHandler(args: ResetCommandOptions): Promise<void>;
|