nx 19.7.0-beta.2 → 19.7.0-beta.4
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/schemas/nx-schema.json +12 -0
- package/src/command-line/add/command-object.js +2 -2
- package/src/command-line/affected/command-object.js +1 -1
- package/src/command-line/connect/command-object.js +11 -4
- package/src/command-line/connect/connect-to-nx-cloud.d.ts +3 -1
- package/src/command-line/connect/connect-to-nx-cloud.js +7 -4
- package/src/command-line/daemon/command-object.js +1 -1
- package/src/command-line/deprecated/command-objects.js +2 -2
- package/src/command-line/exec/command-object.js +1 -1
- package/src/command-line/format/command-object.js +4 -4
- package/src/command-line/generate/command-object.js +4 -4
- package/src/command-line/graph/command-object.js +6 -6
- package/src/command-line/import/command-object.js +9 -5
- package/src/command-line/import/import.d.ts +4 -0
- package/src/command-line/import/import.js +147 -12
- package/src/command-line/import/utils/prepare-source-repo.d.ts +1 -1
- package/src/command-line/import/utils/prepare-source-repo.js +31 -85
- package/src/command-line/list/command-object.js +1 -1
- package/src/command-line/login/command-object.js +1 -1
- package/src/command-line/logout/command-object.js +1 -1
- package/src/command-line/migrate/command-object.js +9 -9
- package/src/command-line/new/command-object.js +2 -2
- package/src/command-line/release/changelog.js +53 -12
- package/src/command-line/release/command-object.d.ts +2 -0
- package/src/command-line/release/command-object.js +37 -33
- 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/index.d.ts +6 -4
- package/src/command-line/release/plan-check.js +8 -61
- package/src/command-line/release/plan.js +131 -37
- package/src/command-line/release/publish.js +3 -0
- package/src/command-line/release/release.js +1 -1
- package/src/command-line/release/utils/get-touched-projects-for-group.d.ts +7 -0
- package/src/command-line/release/utils/get-touched-projects-for-group.js +78 -0
- 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/report/command-object.js +1 -1
- package/src/command-line/reset/command-object.js +1 -1
- package/src/command-line/run/command-object.js +1 -1
- package/src/command-line/run-many/command-object.js +1 -1
- package/src/command-line/show/command-object.js +10 -10
- package/src/command-line/sync/sync.js +12 -1
- package/src/command-line/watch/command-object.js +1 -1
- package/src/command-line/yargs-utils/shared-options.d.ts +2 -1
- package/src/command-line/yargs-utils/shared-options.js +26 -29
- package/src/config/nx-json.d.ts +5 -1
- package/src/core/graph/main.js +1 -1
- package/src/daemon/server/sync-generators.d.ts +4 -0
- package/src/daemon/server/sync-generators.js +183 -55
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.d.ts +2 -1
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +25 -23
- package/src/nx-cloud/generators/connect-to-nx-cloud/schema.json +4 -0
- package/src/nx-cloud/update-manager.d.ts +1 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +8 -1
- package/src/project-graph/plugins/isolation/plugin-pool.js +1 -1
- package/src/tasks-runner/cache.d.ts +2 -0
- package/src/tasks-runner/cache.js +17 -3
- package/src/tasks-runner/run-command.js +5 -11
- package/src/tasks-runner/task-orchestrator.js +1 -10
- package/src/utils/command-line-utils.d.ts +1 -0
- package/src/utils/git-utils.d.ts +7 -10
- package/src/utils/git-utils.js +61 -44
- package/src/utils/sync-generators.d.ts +8 -5
- package/src/utils/sync-generators.js +27 -5
- package/src/utils/squash.d.ts +0 -1
- package/src/utils/squash.js +0 -12
@@ -10,6 +10,8 @@ const tmp_1 = require("tmp");
|
|
10
10
|
const nx_json_1 = require("../../config/nx-json");
|
11
11
|
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
12
12
|
const project_graph_1 = require("../../project-graph/project-graph");
|
13
|
+
const all_file_data_1 = require("../../utils/all-file-data");
|
14
|
+
const command_line_utils_1 = require("../../utils/command-line-utils");
|
13
15
|
const output_1 = require("../../utils/output");
|
14
16
|
const params_1 = require("../../utils/params");
|
15
17
|
const config_1 = require("./config/config");
|
@@ -17,6 +19,7 @@ const deep_merge_json_1 = require("./config/deep-merge-json");
|
|
17
19
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
18
20
|
const version_plans_1 = require("./config/version-plans");
|
19
21
|
const generate_version_plan_content_1 = require("./utils/generate-version-plan-content");
|
22
|
+
const get_touched_projects_for_group_1 = require("./utils/get-touched-projects-for-group");
|
20
23
|
const launch_editor_1 = require("./utils/launch-editor");
|
21
24
|
const print_changes_1 = require("./utils/print-changes");
|
22
25
|
const print_config_1 = require("./utils/print-config");
|
@@ -45,64 +48,155 @@ function createAPI(overrideReleaseConfig) {
|
|
45
48
|
output_1.output.error(filterError);
|
46
49
|
process.exit(1);
|
47
50
|
}
|
51
|
+
// If no release groups have version plans enabled, it doesn't make sense to use the plan command only to set yourself up for an error at release time
|
52
|
+
if (!releaseGroups.some((group) => group.versionPlans === true)) {
|
53
|
+
if (releaseGroups.length === 1) {
|
54
|
+
output_1.output.warn({
|
55
|
+
title: `Version plans are not enabled in your release configuration`,
|
56
|
+
bodyLines: [
|
57
|
+
'To enable version plans, set `"versionPlans": true` at the top level of your `"release"` configuration',
|
58
|
+
],
|
59
|
+
});
|
60
|
+
return 0;
|
61
|
+
}
|
62
|
+
output_1.output.warn({
|
63
|
+
title: 'No release groups have version plans enabled',
|
64
|
+
bodyLines: [
|
65
|
+
'To enable version plans, set `"versionPlans": true` at the top level of your `"release"` configuration to apply it to all groups, otherwise set it at the release group level',
|
66
|
+
],
|
67
|
+
});
|
68
|
+
return 0;
|
69
|
+
}
|
70
|
+
// Resolve the final values for base, head etc to use when resolving the changes to consider
|
71
|
+
const { nxArgs } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'affected', {
|
72
|
+
printWarnings: args.verbose,
|
73
|
+
}, nxJson);
|
48
74
|
const versionPlanBumps = {};
|
49
75
|
const setBumpIfNotNone = (projectOrGroup, version) => {
|
50
76
|
if (version !== 'none') {
|
51
77
|
versionPlanBumps[projectOrGroup] = version;
|
52
78
|
}
|
53
79
|
};
|
54
|
-
if
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
80
|
+
// Changed files are only relevant if considering touched projects
|
81
|
+
let changedFiles = [];
|
82
|
+
let getProjectsToVersionForGroup;
|
83
|
+
if (args.onlyTouched) {
|
84
|
+
changedFiles = (0, command_line_utils_1.parseFiles)(nxArgs).files;
|
85
|
+
if (nxArgs.verbose) {
|
86
|
+
if (changedFiles.length) {
|
87
|
+
output_1.output.log({
|
88
|
+
title: `Changed files based on resolved "base" (${nxArgs.base}) and "head" (${nxArgs.head ?? 'HEAD'})`,
|
89
|
+
bodyLines: changedFiles.map((file) => ` - ${file}`),
|
90
|
+
});
|
91
|
+
}
|
92
|
+
else {
|
93
|
+
output_1.output.warn({
|
94
|
+
title: 'No changed files found based on resolved "base" and "head"',
|
95
|
+
});
|
60
96
|
}
|
61
97
|
}
|
62
|
-
|
63
|
-
|
64
|
-
setBumpIfNotNone(group.name, args.bump ||
|
65
|
-
(await promptForVersion(`How do you want to bump the versions of all projects?`)));
|
66
|
-
}
|
98
|
+
const resolvedAllFileData = await (0, all_file_data_1.allFileData)();
|
99
|
+
getProjectsToVersionForGroup = (0, get_touched_projects_for_group_1.createGetTouchedProjectsForGroup)(nxArgs, projectGraph, changedFiles, resolvedAllFileData);
|
67
100
|
}
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
101
|
+
if (args.projects?.length) {
|
102
|
+
/**
|
103
|
+
* Run plan for all remaining release groups and filtered projects within them
|
104
|
+
*/
|
105
|
+
for (const releaseGroup of releaseGroups) {
|
106
|
+
const releaseGroupName = releaseGroup.name;
|
107
|
+
const releaseGroupProjectNames = Array.from(releaseGroupToFilteredProjects.get(releaseGroup));
|
108
|
+
let applicableProjects = releaseGroupProjectNames;
|
109
|
+
if (args.onlyTouched &&
|
110
|
+
typeof getProjectsToVersionForGroup === 'function') {
|
111
|
+
applicableProjects = await getProjectsToVersionForGroup(releaseGroup, releaseGroupProjectNames, true);
|
112
|
+
}
|
113
|
+
if (!applicableProjects.length) {
|
114
|
+
continue;
|
115
|
+
}
|
116
|
+
if (releaseGroup.projectsRelationship === 'independent') {
|
117
|
+
for (const project of applicableProjects) {
|
72
118
|
setBumpIfNotNone(project, args.bump ||
|
73
|
-
(await promptForVersion(`How do you want to bump the version of the project "${project}"
|
119
|
+
(await promptForVersion(`How do you want to bump the version of the project "${project}"${releaseGroupName === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
120
|
+
? ''
|
121
|
+
: ` within group "${releaseGroupName}"`}?`)));
|
74
122
|
}
|
75
123
|
}
|
76
124
|
else {
|
77
|
-
setBumpIfNotNone(
|
78
|
-
(await promptForVersion(`How do you want to bump the versions of
|
125
|
+
setBumpIfNotNone(releaseGroupName, args.bump ||
|
126
|
+
(await promptForVersion(`How do you want to bump the versions of ${releaseGroupName === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
127
|
+
? 'all projects'
|
128
|
+
: `the projects in the group "${releaseGroupName}"`}?`)));
|
79
129
|
}
|
80
130
|
}
|
81
|
-
|
82
|
-
|
83
|
-
output_1.output.warn({
|
84
|
-
title: 'No version bumps were selected so no version plan file was created.',
|
85
|
-
});
|
131
|
+
// Create a version plan file if applicable
|
132
|
+
await createVersionPlanFileForBumps(args, versionPlanBumps);
|
86
133
|
return 0;
|
87
134
|
}
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
const
|
92
|
-
|
93
|
-
|
94
|
-
(
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
(
|
99
|
-
|
100
|
-
|
101
|
-
|
135
|
+
/**
|
136
|
+
* Run plan for all remaining release groups
|
137
|
+
*/
|
138
|
+
for (const releaseGroup of releaseGroups) {
|
139
|
+
const releaseGroupName = releaseGroup.name;
|
140
|
+
let applicableProjects = releaseGroup.projects;
|
141
|
+
if (args.onlyTouched &&
|
142
|
+
typeof getProjectsToVersionForGroup === 'function') {
|
143
|
+
applicableProjects = await getProjectsToVersionForGroup(releaseGroup, releaseGroup.projects, false);
|
144
|
+
}
|
145
|
+
if (!applicableProjects.length) {
|
146
|
+
continue;
|
147
|
+
}
|
148
|
+
if (releaseGroup.projectsRelationship === 'independent') {
|
149
|
+
for (const project of applicableProjects) {
|
150
|
+
setBumpIfNotNone(project, args.bump ||
|
151
|
+
(await promptForVersion(`How do you want to bump the version of the project "${project}"${releaseGroupName === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
152
|
+
? ''
|
153
|
+
: ` within group "${releaseGroupName}"`}?`)));
|
154
|
+
}
|
155
|
+
}
|
156
|
+
else {
|
157
|
+
setBumpIfNotNone(releaseGroupName, args.bump ||
|
158
|
+
(await promptForVersion(`How do you want to bump the versions of ${releaseGroupName === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
159
|
+
? 'all projects'
|
160
|
+
: `the projects in the group "${releaseGroupName}"`}?`)));
|
161
|
+
}
|
102
162
|
}
|
163
|
+
// Create a version plan file if applicable
|
164
|
+
await createVersionPlanFileForBumps(args, versionPlanBumps);
|
103
165
|
return 0;
|
104
166
|
};
|
105
167
|
}
|
168
|
+
async function createVersionPlanFileForBumps(args, versionPlanBumps) {
|
169
|
+
if (!Object.keys(versionPlanBumps).length) {
|
170
|
+
let bodyLines = [];
|
171
|
+
if (args.onlyTouched) {
|
172
|
+
bodyLines = [
|
173
|
+
'This might be because no projects have been changed, or projects you expected to release have not been touched',
|
174
|
+
'To include all projects, not just those that have been changed, pass --only-touched=false',
|
175
|
+
'Alternatively, you can specify alternate --base and --head refs to include only changes from certain commits',
|
176
|
+
];
|
177
|
+
}
|
178
|
+
output_1.output.warn({
|
179
|
+
title: 'No version bumps were selected so no version plan file was created.',
|
180
|
+
bodyLines,
|
181
|
+
});
|
182
|
+
return 0;
|
183
|
+
}
|
184
|
+
const versionPlanName = `version-plan-${new Date().getTime()}`;
|
185
|
+
const versionPlanMessage = args.message || (await promptForMessage(versionPlanName));
|
186
|
+
const versionPlanFileContent = (0, generate_version_plan_content_1.generateVersionPlanContent)(versionPlanBumps, versionPlanMessage);
|
187
|
+
const versionPlanFileName = `${versionPlanName}.md`;
|
188
|
+
if (args.dryRun) {
|
189
|
+
output_1.output.logSingleLine(`Would create version plan file "${versionPlanFileName}", but --dry-run was set.`);
|
190
|
+
(0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
|
191
|
+
}
|
192
|
+
else {
|
193
|
+
output_1.output.logSingleLine(`Creating version plan file "${versionPlanFileName}"`);
|
194
|
+
(0, print_changes_1.printDiff)('', versionPlanFileContent, 1);
|
195
|
+
const versionPlansAbsolutePath = (0, version_plans_1.getVersionPlansAbsolutePath)();
|
196
|
+
await (0, fs_extra_1.ensureDir)(versionPlansAbsolutePath);
|
197
|
+
await (0, fs_extra_1.writeFile)((0, node_path_1.join)(versionPlansAbsolutePath, versionPlanFileName), versionPlanFileContent);
|
198
|
+
}
|
199
|
+
}
|
106
200
|
async function promptForVersion(message) {
|
107
201
|
try {
|
108
202
|
const reply = await (0, enquirer_1.prompt)([
|
@@ -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) {
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import { FileData, ProjectGraph } from '../../../config/project-graph';
|
2
|
+
import { NxArgs } from '../../../utils/command-line-utils';
|
3
|
+
import { ReleaseGroupWithName } from '../config/filter-release-groups';
|
4
|
+
/**
|
5
|
+
* Create a function that returns the touched projects for a given release group. Only relevant when version plans are enabled.
|
6
|
+
*/
|
7
|
+
export declare function createGetTouchedProjectsForGroup(nxArgs: NxArgs, projectGraph: ProjectGraph, changedFiles: string[], fileData: FileData[]): (releaseGroup: ReleaseGroupWithName, releaseGroupFilteredProjectNames: string[], hasProjectsFilter: boolean) => Promise<string[]>;
|
@@ -0,0 +1,78 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.createGetTouchedProjectsForGroup = createGetTouchedProjectsForGroup;
|
4
|
+
const workspace_projects_1 = require("../../../project-graph/affected/locators/workspace-projects");
|
5
|
+
const file_utils_1 = require("../../../project-graph/file-utils");
|
6
|
+
const ignore_1 = require("../../../utils/ignore");
|
7
|
+
const output_1 = require("../../../utils/output");
|
8
|
+
const config_1 = require("../config/config");
|
9
|
+
/**
|
10
|
+
* Create a function that returns the touched projects for a given release group. Only relevant when version plans are enabled.
|
11
|
+
*/
|
12
|
+
function createGetTouchedProjectsForGroup(nxArgs, projectGraph, changedFiles, fileData) {
|
13
|
+
/**
|
14
|
+
* Create a minimal subset of touched projects based on the configured ignore patterns, we only need
|
15
|
+
* to recompute when the ignorePatternsForPlanCheck differs between release groups.
|
16
|
+
*/
|
17
|
+
const serializedIgnorePatternsToTouchedProjects = new Map();
|
18
|
+
return async function getTouchedProjectsForGroup(releaseGroup,
|
19
|
+
// We don't access releaseGroups.projects directly, because we need to take the --projects filter into account
|
20
|
+
releaseGroupFilteredProjectNames, hasProjectsFilter) {
|
21
|
+
// The current release group doesn't leverage version plans
|
22
|
+
if (!releaseGroup.versionPlans) {
|
23
|
+
return [];
|
24
|
+
}
|
25
|
+
// Exclude patterns from .nxignore, .gitignore and explicit version plan config
|
26
|
+
let serializedIgnorePatterns = '[]';
|
27
|
+
const ignore = (0, ignore_1.getIgnoreObject)();
|
28
|
+
if (typeof releaseGroup.versionPlans !== 'boolean' &&
|
29
|
+
Array.isArray(releaseGroup.versionPlans.ignorePatternsForPlanCheck) &&
|
30
|
+
releaseGroup.versionPlans.ignorePatternsForPlanCheck.length) {
|
31
|
+
output_1.output.note({
|
32
|
+
title: `Applying configured ignore patterns to changed files${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
33
|
+
? ` for release group "${releaseGroup.name}"`
|
34
|
+
: ''}`,
|
35
|
+
bodyLines: [
|
36
|
+
...releaseGroup.versionPlans.ignorePatternsForPlanCheck.map((pattern) => ` - ${pattern}`),
|
37
|
+
],
|
38
|
+
});
|
39
|
+
ignore.add(releaseGroup.versionPlans.ignorePatternsForPlanCheck);
|
40
|
+
serializedIgnorePatterns = JSON.stringify(releaseGroup.versionPlans.ignorePatternsForPlanCheck);
|
41
|
+
}
|
42
|
+
let touchedProjects = {};
|
43
|
+
if (serializedIgnorePatternsToTouchedProjects.has(serializedIgnorePatterns)) {
|
44
|
+
touchedProjects = serializedIgnorePatternsToTouchedProjects.get(serializedIgnorePatterns);
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
// We only care about directly touched projects, not implicitly affected ones etc
|
48
|
+
const touchedProjectsArr = await (0, workspace_projects_1.getTouchedProjects)((0, file_utils_1.calculateFileChanges)(changedFiles, fileData, nxArgs, undefined, ignore), projectGraph.nodes);
|
49
|
+
touchedProjects = touchedProjectsArr.reduce((acc, project) => ({ ...acc, [project]: true }), {});
|
50
|
+
serializedIgnorePatternsToTouchedProjects.set(serializedIgnorePatterns, touchedProjects);
|
51
|
+
}
|
52
|
+
const touchedProjectsUnderReleaseGroup = releaseGroupFilteredProjectNames.filter((project) => touchedProjects[project]);
|
53
|
+
if (touchedProjectsUnderReleaseGroup.length) {
|
54
|
+
output_1.output.log({
|
55
|
+
title: `Touched projects${hasProjectsFilter ? ` (after --projects filter applied)` : ''} based on changed files${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
56
|
+
? ` under release group "${releaseGroup.name}"`
|
57
|
+
: ''}`,
|
58
|
+
bodyLines: [
|
59
|
+
...touchedProjectsUnderReleaseGroup.map((project) => ` - ${project}`),
|
60
|
+
'',
|
61
|
+
'NOTE: You can adjust your "versionPlans.ignorePatternsForPlanCheck" config to stop certain files from resulting in projects being classed as touched for the purposes of this command.',
|
62
|
+
],
|
63
|
+
});
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
output_1.output.log({
|
67
|
+
title: `No touched projects${hasProjectsFilter ? ` (after --projects filter applied)` : ''} found based on changed files${typeof releaseGroup.versionPlans !== 'boolean' &&
|
68
|
+
Array.isArray(releaseGroup.versionPlans.ignorePatternsForPlanCheck) &&
|
69
|
+
releaseGroup.versionPlans.ignorePatternsForPlanCheck.length
|
70
|
+
? ' combined with configured ignore patterns'
|
71
|
+
: ''}${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
72
|
+
? ` under release group "${releaseGroup.name}"`
|
73
|
+
: ''}`,
|
74
|
+
});
|
75
|
+
}
|
76
|
+
return touchedProjectsUnderReleaseGroup;
|
77
|
+
};
|
78
|
+
}
|
@@ -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 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.yargsReportCommand = void 0;
|
4
4
|
exports.yargsReportCommand = {
|
5
5
|
command: 'report',
|
6
|
-
describe: 'Reports useful version numbers to copy into the Nx issue template',
|
6
|
+
describe: 'Reports useful version numbers to copy into the Nx issue template.',
|
7
7
|
handler: async () => {
|
8
8
|
await (await Promise.resolve().then(() => require('./report'))).reportHandler();
|
9
9
|
process.exit(0);
|
@@ -19,7 +19,7 @@ exports.yargsResetCommand = {
|
|
19
19
|
type: 'boolean',
|
20
20
|
})
|
21
21
|
.option('onlyWorkspaceData', {
|
22
|
-
description: 'Clears the workspace data directory. Used by Nx to store cached data about the current workspace (e.g. partial results, incremental data, etc)',
|
22
|
+
description: 'Clears the workspace data directory. Used by Nx to store cached data about the current workspace (e.g. partial results, incremental data, etc).',
|
23
23
|
type: 'boolean',
|
24
24
|
}),
|
25
25
|
handler: async (argv) => (await Promise.resolve().then(() => require('./reset'))).resetHandler(argv),
|
@@ -27,7 +27,7 @@ exports.yargsRunCommand = {
|
|
27
27
|
exports.yargsNxInfixCommand = {
|
28
28
|
...exports.yargsRunCommand,
|
29
29
|
command: '$0 <target> [project] [_..]',
|
30
|
-
describe: 'Run a target for a project',
|
30
|
+
describe: 'Run a target for a project.',
|
31
31
|
handler: async (args) => {
|
32
32
|
const exitCode = await (0, params_1.handleErrors)(args.verbose ?? process.env.NX_VERBOSE_LOGGING === 'true', async () => {
|
33
33
|
// Yargs parses <target> as 'undefined' if running just 'nx'
|
@@ -6,7 +6,7 @@ const shared_options_1 = require("../yargs-utils/shared-options");
|
|
6
6
|
const params_1 = require("../../utils/params");
|
7
7
|
exports.yargsRunManyCommand = {
|
8
8
|
command: 'run-many',
|
9
|
-
describe: 'Run target for multiple listed projects',
|
9
|
+
describe: 'Run target for multiple listed projects.',
|
10
10
|
builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)((0, shared_options_1.withRunManyOptions)((0, shared_options_1.withOutputStyleOption)((0, shared_options_1.withTargetAndConfigurationOption)((0, shared_options_1.withBatch)(yargs)))), 'run-many'),
|
11
11
|
handler: async (args) => {
|
12
12
|
const exitCode = await (0, params_1.handleErrors)(args.verbose ?? process.env.NX_VERBOSE_LOGGING === 'true', async () => {
|
@@ -6,14 +6,14 @@ const shared_options_1 = require("../yargs-utils/shared-options");
|
|
6
6
|
const params_1 = require("../../utils/params");
|
7
7
|
exports.yargsShowCommand = {
|
8
8
|
command: 'show',
|
9
|
-
describe: 'Show information about the workspace (e.g., list of projects)',
|
9
|
+
describe: 'Show information about the workspace (e.g., list of projects).',
|
10
10
|
builder: (yargs) => yargs
|
11
11
|
.command(showProjectsCommand)
|
12
12
|
.command(showProjectCommand)
|
13
13
|
.demandCommand()
|
14
14
|
.option('json', {
|
15
15
|
type: 'boolean',
|
16
|
-
description: 'Output JSON',
|
16
|
+
description: 'Output JSON.',
|
17
17
|
})
|
18
18
|
.example('$0 show projects', 'Show a list of all projects in the workspace')
|
19
19
|
.example('$0 show projects --with-target serve', 'Show a list of all projects in the workspace that have a "serve" target')
|
@@ -25,11 +25,11 @@ exports.yargsShowCommand = {
|
|
25
25
|
};
|
26
26
|
const showProjectsCommand = {
|
27
27
|
command: 'projects',
|
28
|
-
describe: 'Show a list of projects in the workspace',
|
28
|
+
describe: 'Show a list of projects in the workspace.',
|
29
29
|
builder: (yargs) => (0, shared_options_1.withVerbose)((0, shared_options_1.withAffectedOptions)(yargs))
|
30
30
|
.option('affected', {
|
31
31
|
type: 'boolean',
|
32
|
-
description: 'Show only affected projects',
|
32
|
+
description: 'Show only affected projects.',
|
33
33
|
})
|
34
34
|
.option('projects', {
|
35
35
|
type: 'string',
|
@@ -40,17 +40,17 @@ const showProjectsCommand = {
|
|
40
40
|
.option('withTarget', {
|
41
41
|
type: 'string',
|
42
42
|
alias: ['t'],
|
43
|
-
description: 'Show only projects that have a specific target',
|
43
|
+
description: 'Show only projects that have a specific target.',
|
44
44
|
coerce: shared_options_1.parseCSV,
|
45
45
|
})
|
46
46
|
.option('type', {
|
47
47
|
type: 'string',
|
48
|
-
description: 'Select only projects of the given type',
|
48
|
+
description: 'Select only projects of the given type.',
|
49
49
|
choices: ['app', 'lib', 'e2e'],
|
50
50
|
})
|
51
51
|
.option('sep', {
|
52
52
|
type: 'string',
|
53
|
-
description: 'Outputs projects with the specified seperator',
|
53
|
+
description: 'Outputs projects with the specified seperator.',
|
54
54
|
})
|
55
55
|
.implies('untracked', 'affected')
|
56
56
|
.implies('uncommitted', 'affected')
|
@@ -79,15 +79,15 @@ const showProjectCommand = {
|
|
79
79
|
.positional('projectName', {
|
80
80
|
type: 'string',
|
81
81
|
alias: 'p',
|
82
|
-
description: 'Which project should be viewed
|
82
|
+
description: 'Which project should be viewed?.',
|
83
83
|
})
|
84
84
|
.option('web', {
|
85
85
|
type: 'boolean',
|
86
|
-
description: 'Show project details in the browser. (default when interactive)',
|
86
|
+
description: 'Show project details in the browser. (default when interactive).',
|
87
87
|
})
|
88
88
|
.option('open', {
|
89
89
|
type: 'boolean',
|
90
|
-
description: 'Set to false to prevent the browser from opening when using --web',
|
90
|
+
description: 'Set to false to prevent the browser from opening when using --web.',
|
91
91
|
implies: 'web',
|
92
92
|
})
|
93
93
|
.check((argv) => {
|
@@ -2,6 +2,7 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.syncHandler = syncHandler;
|
4
4
|
const ora = require("ora");
|
5
|
+
const nx_json_1 = require("../../config/nx-json");
|
5
6
|
const project_graph_1 = require("../../project-graph/project-graph");
|
6
7
|
const output_1 = require("../../utils/output");
|
7
8
|
const params_1 = require("../../utils/params");
|
@@ -10,7 +11,17 @@ const chalk = require("chalk");
|
|
10
11
|
function syncHandler(options) {
|
11
12
|
return (0, params_1.handleErrors)(options.verbose, async () => {
|
12
13
|
const projectGraph = await (0, project_graph_1.createProjectGraphAsync)();
|
13
|
-
const
|
14
|
+
const nxJson = (0, nx_json_1.readNxJson)();
|
15
|
+
const syncGenerators = await (0, sync_generators_1.collectAllRegisteredSyncGenerators)(projectGraph, nxJson);
|
16
|
+
if (!syncGenerators.length) {
|
17
|
+
output_1.output.success({
|
18
|
+
title: options.check
|
19
|
+
? 'The workspace is up to date'
|
20
|
+
: 'The workspace is already up to date',
|
21
|
+
bodyLines: ['There are no sync generators to run.'],
|
22
|
+
});
|
23
|
+
return 0;
|
24
|
+
}
|
14
25
|
const results = await (0, sync_generators_1.getSyncGeneratorChanges)(syncGenerators);
|
15
26
|
if (!results.length) {
|
16
27
|
output_1.output.success({
|
@@ -5,7 +5,7 @@ const documentation_1 = require("../yargs-utils/documentation");
|
|
5
5
|
const shared_options_1 = require("../yargs-utils/shared-options");
|
6
6
|
exports.yargsWatchCommand = {
|
7
7
|
command: 'watch',
|
8
|
-
describe: 'Watch for changes within projects, and execute commands',
|
8
|
+
describe: 'Watch for changes within projects, and execute commands.',
|
9
9
|
builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)(withWatchOptions(yargs), 'watch'),
|
10
10
|
handler: async (args) => {
|
11
11
|
await Promise.resolve().then(() => require('./watch')).then((m) => m.watch(args));
|
@@ -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<{
|