nx 19.7.0-beta.3 → 19.7.0-beta.5
Sign up to get free protection for your applications and to get access to all the features.
- 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 +5 -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/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/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/core/graph/main.js +1 -1
- package/src/daemon/server/sync-generators.d.ts +4 -0
- package/src/daemon/server/sync-generators.js +172 -52
- 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 +17 -50
- package/src/nx-cloud/generators/connect-to-nx-cloud/schema.json +4 -0
- 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 +15 -1
- package/src/tasks-runner/run-command.js +4 -1
- 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 +2 -2
- package/src/utils/squash.d.ts +0 -1
- package/src/utils/squash.js +0 -12
@@ -8,7 +8,7 @@ const logger_1 = require("../../utils/logger");
|
|
8
8
|
const shared_options_1 = require("../yargs-utils/shared-options");
|
9
9
|
exports.yargsReleaseCommand = {
|
10
10
|
command: 'release',
|
11
|
-
describe: 'Orchestrate versioning and publishing of applications and libraries',
|
11
|
+
describe: 'Orchestrate versioning and publishing of applications and libraries.',
|
12
12
|
builder: (yargs) => (0, shared_options_1.withVerbose)(yargs)
|
13
13
|
.command(releaseCommand)
|
14
14
|
.command(versionCommand)
|
@@ -29,10 +29,10 @@ exports.yargsReleaseCommand = {
|
|
29
29
|
type: 'string',
|
30
30
|
alias: 'p',
|
31
31
|
coerce: shared_options_1.parseCSV,
|
32
|
-
describe: 'Projects to run. (comma/space delimited project names and/or patterns)',
|
32
|
+
describe: 'Projects to run. (comma/space delimited project names and/or patterns).',
|
33
33
|
})
|
34
34
|
.option('dry-run', {
|
35
|
-
describe: 'Preview the changes without updating files/creating releases',
|
35
|
+
describe: 'Preview the changes without updating files/creating releases.',
|
36
36
|
alias: 'd',
|
37
37
|
type: 'boolean',
|
38
38
|
default: false,
|
@@ -40,7 +40,7 @@ exports.yargsReleaseCommand = {
|
|
40
40
|
// NOTE: The camel case format is required for the coerce() function to be called correctly. It still supports --print-config casing.
|
41
41
|
.option('printConfig', {
|
42
42
|
type: 'string',
|
43
|
-
describe: 'Print the resolved nx release configuration that would be used for the current command and then exit',
|
43
|
+
describe: 'Print the resolved nx release configuration that would be used for the current command and then exit.',
|
44
44
|
coerce: (val) => {
|
45
45
|
if (val === '') {
|
46
46
|
return true;
|
@@ -72,7 +72,7 @@ exports.yargsReleaseCommand = {
|
|
72
72
|
};
|
73
73
|
const releaseCommand = {
|
74
74
|
command: '$0 [specifier]',
|
75
|
-
describe: 'Create a version and release for the workspace, generate a changelog, and optionally publish the packages',
|
75
|
+
describe: 'Create a version and release for the workspace, generate a changelog, and optionally publish the packages.',
|
76
76
|
builder: (yargs) => withFirstReleaseOptions(yargs)
|
77
77
|
.positional('specifier', {
|
78
78
|
type: 'string',
|
@@ -81,11 +81,11 @@ const releaseCommand = {
|
|
81
81
|
.option('yes', {
|
82
82
|
type: 'boolean',
|
83
83
|
alias: 'y',
|
84
|
-
description: 'Automatically answer yes to the confirmation prompt for publishing',
|
84
|
+
description: 'Automatically answer yes to the confirmation prompt for publishing.',
|
85
85
|
})
|
86
86
|
.option('skip-publish', {
|
87
87
|
type: 'boolean',
|
88
|
-
description: 'Skip publishing by automatically answering no to the confirmation prompt for publishing',
|
88
|
+
description: 'Skip publishing by automatically answering no to the confirmation prompt for publishing.',
|
89
89
|
})
|
90
90
|
.check((argv) => {
|
91
91
|
if (argv.yes !== undefined && argv.skipPublish !== undefined) {
|
@@ -105,7 +105,7 @@ const releaseCommand = {
|
|
105
105
|
const versionCommand = {
|
106
106
|
command: 'version [specifier]',
|
107
107
|
aliases: ['v'],
|
108
|
-
describe: 'Create a version and release for one or more applications and libraries',
|
108
|
+
describe: 'Create a version and release for one or more applications and libraries.',
|
109
109
|
builder: (yargs) => withFirstReleaseOptions(withGitCommitAndGitTagOptions(yargs
|
110
110
|
.positional('specifier', {
|
111
111
|
type: 'string',
|
@@ -113,7 +113,7 @@ const versionCommand = {
|
|
113
113
|
})
|
114
114
|
.option('preid', {
|
115
115
|
type: 'string',
|
116
|
-
describe: 'The optional prerelease identifier to apply to the version. This will only be applied in the case that the specifier argument has been set to `prerelease` OR when conventional commits are enabled, in which case it will modify the resolved specifier from conventional commits to be its prerelease equivalent. E.g. minor -> preminor',
|
116
|
+
describe: 'The optional prerelease identifier to apply to the version. This will only be applied in the case that the specifier argument has been set to `prerelease` OR when conventional commits are enabled, in which case it will modify the resolved specifier from conventional commits to be its prerelease equivalent. E.g. minor -> preminor.',
|
117
117
|
default: '',
|
118
118
|
})
|
119
119
|
.option('stage-changes', {
|
@@ -132,32 +132,32 @@ const versionCommand = {
|
|
132
132
|
const changelogCommand = {
|
133
133
|
command: 'changelog [version]',
|
134
134
|
aliases: ['c'],
|
135
|
-
describe: 'Generate a changelog for one or more projects, and optionally push to Github',
|
135
|
+
describe: 'Generate a changelog for one or more projects, and optionally push to Github.',
|
136
136
|
builder: (yargs) => withFirstReleaseOptions(withGitCommitAndGitTagOptions(yargs
|
137
137
|
// Disable default meaning of yargs version for this command
|
138
138
|
.version(false)
|
139
139
|
.positional('version', {
|
140
140
|
type: 'string',
|
141
|
-
description: 'The version to create a Github release and changelog for',
|
141
|
+
description: 'The version to create a Github release and changelog for.',
|
142
142
|
})
|
143
143
|
.option('from', {
|
144
144
|
type: 'string',
|
145
|
-
description: 'The git reference to use as the start of the changelog. If not set it will attempt to resolve the latest tag and use that',
|
145
|
+
description: 'The git reference to use as the start of the changelog. If not set it will attempt to resolve the latest tag and use that.',
|
146
146
|
})
|
147
147
|
.option('to', {
|
148
148
|
type: 'string',
|
149
|
-
description: 'The git reference to use as the end of the changelog',
|
149
|
+
description: 'The git reference to use as the end of the changelog.',
|
150
150
|
default: 'HEAD',
|
151
151
|
})
|
152
152
|
.option('interactive', {
|
153
153
|
alias: 'i',
|
154
154
|
type: 'string',
|
155
|
-
description: 'Interactively modify changelog markdown contents in your code editor before applying the changes. You can set it to be interactive for all changelogs, or only the workspace level, or only the project level',
|
155
|
+
description: 'Interactively modify changelog markdown contents in your code editor before applying the changes. You can set it to be interactive for all changelogs, or only the workspace level, or only the project level.',
|
156
156
|
choices: ['all', 'workspace', 'projects'],
|
157
157
|
})
|
158
158
|
.option('git-remote', {
|
159
159
|
type: 'string',
|
160
|
-
description: 'Alternate git remote in the form {user}/{repo} on which to create the Github release (useful for testing)',
|
160
|
+
description: 'Alternate git remote in the form {user}/{repo} on which to create the Github release (useful for testing).',
|
161
161
|
default: 'origin',
|
162
162
|
})
|
163
163
|
.check((argv) => {
|
@@ -178,19 +178,24 @@ const changelogCommand = {
|
|
178
178
|
const publishCommand = {
|
179
179
|
command: 'publish',
|
180
180
|
aliases: ['p'],
|
181
|
-
describe: 'Publish a versioned project to a registry',
|
181
|
+
describe: 'Publish a versioned project to a registry.',
|
182
182
|
builder: (yargs) => withFirstReleaseOptions((0, shared_options_1.withRunManyOptions)((0, shared_options_1.withOutputStyleOption)(yargs))
|
183
183
|
.option('registry', {
|
184
184
|
type: 'string',
|
185
|
-
description: 'The registry to publish to',
|
185
|
+
description: 'The registry to publish to.',
|
186
186
|
})
|
187
187
|
.option('tag', {
|
188
188
|
type: 'string',
|
189
|
-
description: 'The distribution tag to apply to the published package',
|
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',
|
193
|
-
description: 'A one-time password for publishing to a registry that requires 2FA',
|
198
|
+
description: 'A one-time password for publishing to a registry that requires 2FA.',
|
194
199
|
})),
|
195
200
|
handler: async (args) => {
|
196
201
|
const status = await (await Promise.resolve().then(() => require('./publish'))).releasePublishCLIHandler(coerceParallelOption((0, shared_options_1.withOverrides)(args, 2)));
|
@@ -203,11 +208,8 @@ const publishCommand = {
|
|
203
208
|
const planCommand = {
|
204
209
|
command: 'plan [bump]',
|
205
210
|
aliases: ['pl'],
|
206
|
-
|
207
|
-
|
208
|
-
// Hidden for now until the feature is more stable
|
209
|
-
describe: false,
|
210
|
-
builder: (yargs) => yargs
|
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.',
|
212
|
+
builder: (yargs) => (0, shared_options_1.withAffectedOptions)(yargs)
|
211
213
|
.positional('bump', {
|
212
214
|
type: 'string',
|
213
215
|
describe: 'Semver keyword to use for the selected release group.',
|
@@ -224,7 +226,12 @@ const planCommand = {
|
|
224
226
|
.option('message', {
|
225
227
|
type: 'string',
|
226
228
|
alias: 'm',
|
227
|
-
describe: 'Custom message to use for the changelog entry',
|
229
|
+
describe: 'Custom message to use for the changelog entry.',
|
230
|
+
})
|
231
|
+
.option('onlyTouched', {
|
232
|
+
type: 'boolean',
|
233
|
+
describe: 'Only include projects that have been affected by the current changes.',
|
234
|
+
default: true,
|
228
235
|
}),
|
229
236
|
handler: async (args) => {
|
230
237
|
const release = await Promise.resolve().then(() => require('./plan'));
|
@@ -237,10 +244,7 @@ const planCommand = {
|
|
237
244
|
};
|
238
245
|
const planCheckCommand = {
|
239
246
|
command: 'plan:check',
|
240
|
-
|
241
|
-
// Create a plan to pick a new version and generate a changelog entry.
|
242
|
-
// Hidden for now until the feature is more stable
|
243
|
-
describe: false,
|
247
|
+
describe: 'Ensure that all touched projects have an applicable version plan created for them.',
|
244
248
|
builder: (yargs) => (0, shared_options_1.withAffectedOptions)(yargs),
|
245
249
|
handler: async (args) => {
|
246
250
|
const release = await Promise.resolve().then(() => require('./plan-check'));
|
@@ -257,7 +261,7 @@ function coerceParallelOption(args) {
|
|
257
261
|
function withGitCommitAndGitTagOptions(yargs) {
|
258
262
|
return yargs
|
259
263
|
.option('git-commit', {
|
260
|
-
describe: 'Whether or not to automatically commit the changes made by this command',
|
264
|
+
describe: 'Whether or not to automatically commit the changes made by this command.',
|
261
265
|
type: 'boolean',
|
262
266
|
})
|
263
267
|
.option('git-commit-message', {
|
@@ -265,11 +269,11 @@ function withGitCommitAndGitTagOptions(yargs) {
|
|
265
269
|
type: 'string',
|
266
270
|
})
|
267
271
|
.option('git-commit-args', {
|
268
|
-
describe: 'Additional arguments (added after the --message argument, which may or may not be customized with --git-commit-message) to pass to the `git commit` command invoked behind the scenes',
|
272
|
+
describe: 'Additional arguments (added after the --message argument, which may or may not be customized with --git-commit-message) to pass to the `git commit` command invoked behind the scenes.',
|
269
273
|
type: 'string',
|
270
274
|
})
|
271
275
|
.option('git-tag', {
|
272
|
-
describe: 'Whether or not to automatically tag the changes made by this command',
|
276
|
+
describe: 'Whether or not to automatically tag the changes made by this command.',
|
273
277
|
type: 'boolean',
|
274
278
|
})
|
275
279
|
.option('git-tag-message', {
|
@@ -277,7 +281,7 @@ function withGitCommitAndGitTagOptions(yargs) {
|
|
277
281
|
type: 'string',
|
278
282
|
})
|
279
283
|
.option('git-tag-args', {
|
280
|
-
describe: 'Additional arguments to pass to the `git tag` command invoked behind the scenes',
|
284
|
+
describe: 'Additional arguments to pass to the `git tag` command invoked behind the scenes.',
|
281
285
|
type: 'string',
|
282
286
|
})
|
283
287
|
.option('stage-changes', {
|
@@ -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
|
+
}
|
@@ -3,19 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.releasePlanCheckCLIHandler = void 0;
|
4
4
|
exports.createAPI = createAPI;
|
5
5
|
const nx_json_1 = require("../../config/nx-json");
|
6
|
-
const workspace_projects_1 = require("../../project-graph/affected/locators/workspace-projects");
|
7
6
|
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
8
|
-
const file_utils_1 = require("../../project-graph/file-utils");
|
9
7
|
const project_graph_1 = require("../../project-graph/project-graph");
|
10
8
|
const all_file_data_1 = require("../../utils/all-file-data");
|
11
9
|
const command_line_utils_1 = require("../../utils/command-line-utils");
|
12
|
-
const ignore_1 = require("../../utils/ignore");
|
13
10
|
const output_1 = require("../../utils/output");
|
14
11
|
const params_1 = require("../../utils/params");
|
15
12
|
const config_1 = require("./config/config");
|
16
13
|
const deep_merge_json_1 = require("./config/deep-merge-json");
|
17
14
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
18
15
|
const version_plans_1 = require("./config/version-plans");
|
16
|
+
const get_touched_projects_for_group_1 = require("./utils/get-touched-projects-for-group");
|
19
17
|
const print_config_1 = require("./utils/print-config");
|
20
18
|
const releasePlanCheckCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => createAPI({})(args));
|
21
19
|
exports.releasePlanCheckCLIHandler = releasePlanCheckCLIHandler;
|
@@ -37,7 +35,8 @@ function createAPI(overrideReleaseConfig) {
|
|
37
35
|
isDebug: args.printConfig === 'debug',
|
38
36
|
});
|
39
37
|
}
|
40
|
-
|
38
|
+
// No filtering is applied here, as we want to consider all release groups for plan:check
|
39
|
+
const { error: filterError, releaseGroups } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig);
|
41
40
|
if (filterError) {
|
42
41
|
output_1.output.error(filterError);
|
43
42
|
process.exit(1);
|
@@ -54,7 +53,7 @@ function createAPI(overrideReleaseConfig) {
|
|
54
53
|
return 1;
|
55
54
|
}
|
56
55
|
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
57
|
-
(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);
|
58
57
|
// Resolve the final values for base, head etc to use when resolving the changes to consider
|
59
58
|
const { nxArgs } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'affected', {
|
60
59
|
printWarnings: args.verbose,
|
@@ -74,11 +73,7 @@ function createAPI(overrideReleaseConfig) {
|
|
74
73
|
}
|
75
74
|
}
|
76
75
|
const resolvedAllFileData = await (0, all_file_data_1.allFileData)();
|
77
|
-
|
78
|
-
* Create a minimal subset of touched projects based on the configured ignore patterns, we only need
|
79
|
-
* to recompute when the ignorePatternsForPlanCheck differs between release groups.
|
80
|
-
*/
|
81
|
-
const serializedIgnorePatternsToTouchedProjects = new Map();
|
76
|
+
const getTouchedProjectsForGroup = (0, get_touched_projects_for_group_1.createGetTouchedProjectsForGroup)(nxArgs, projectGraph, changedFiles, resolvedAllFileData);
|
82
77
|
const NOTE_ABOUT_VERBOSE_LOGGING = 'Run with --verbose to see the full list of changed files used for the touched projects logic.';
|
83
78
|
let hasErrors = false;
|
84
79
|
for (const releaseGroup of releaseGroups) {
|
@@ -100,57 +95,9 @@ function createAPI(overrideReleaseConfig) {
|
|
100
95
|
});
|
101
96
|
continue;
|
102
97
|
}
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
if (typeof releaseGroup.versionPlans !== 'boolean' &&
|
107
|
-
Array.isArray(releaseGroup.versionPlans.ignorePatternsForPlanCheck) &&
|
108
|
-
releaseGroup.versionPlans.ignorePatternsForPlanCheck.length) {
|
109
|
-
output_1.output.note({
|
110
|
-
title: `Applying configured ignore patterns to changed files${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
111
|
-
? ` for release group "${releaseGroup.name}"`
|
112
|
-
: ''}`,
|
113
|
-
bodyLines: [
|
114
|
-
...releaseGroup.versionPlans.ignorePatternsForPlanCheck.map((pattern) => ` - ${pattern}`),
|
115
|
-
],
|
116
|
-
});
|
117
|
-
ignore.add(releaseGroup.versionPlans.ignorePatternsForPlanCheck);
|
118
|
-
serializedIgnorePatterns = JSON.stringify(releaseGroup.versionPlans.ignorePatternsForPlanCheck);
|
119
|
-
}
|
120
|
-
let touchedProjects = {};
|
121
|
-
if (serializedIgnorePatternsToTouchedProjects.has(serializedIgnorePatterns)) {
|
122
|
-
touchedProjects = serializedIgnorePatternsToTouchedProjects.get(serializedIgnorePatterns);
|
123
|
-
}
|
124
|
-
else {
|
125
|
-
// We only care about directly touched projects, not implicitly affected ones etc
|
126
|
-
const touchedProjectsArr = await (0, workspace_projects_1.getTouchedProjects)((0, file_utils_1.calculateFileChanges)(changedFiles, resolvedAllFileData, nxArgs, undefined, ignore), projectGraph.nodes);
|
127
|
-
touchedProjects = touchedProjectsArr.reduce((acc, project) => ({ ...acc, [project]: true }), {});
|
128
|
-
serializedIgnorePatternsToTouchedProjects.set(serializedIgnorePatterns, touchedProjects);
|
129
|
-
}
|
130
|
-
const touchedProjectsUnderReleaseGroup = releaseGroup.projects.filter((project) => touchedProjects[project]);
|
131
|
-
if (touchedProjectsUnderReleaseGroup.length) {
|
132
|
-
output_1.output.log({
|
133
|
-
title: `Touched projects based on changed files${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
134
|
-
? ` under release group "${releaseGroup.name}"`
|
135
|
-
: ''}`,
|
136
|
-
bodyLines: [
|
137
|
-
...touchedProjectsUnderReleaseGroup.map((project) => ` - ${project}`),
|
138
|
-
'',
|
139
|
-
'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.',
|
140
|
-
],
|
141
|
-
});
|
142
|
-
}
|
143
|
-
else {
|
144
|
-
output_1.output.log({
|
145
|
-
title: `No touched projects found based on changed files${typeof releaseGroup.versionPlans !== 'boolean' &&
|
146
|
-
Array.isArray(releaseGroup.versionPlans.ignorePatternsForPlanCheck) &&
|
147
|
-
releaseGroup.versionPlans.ignorePatternsForPlanCheck.length
|
148
|
-
? ' combined with configured ignore patterns'
|
149
|
-
: ''}${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
150
|
-
? ` under release group "${releaseGroup.name}"`
|
151
|
-
: ''}`,
|
152
|
-
});
|
153
|
-
}
|
98
|
+
const touchedProjectsUnderReleaseGroup = await getTouchedProjectsForGroup(releaseGroup,
|
99
|
+
// We do not take any --projects or --groups filtering into account for plan:check
|
100
|
+
releaseGroup.projects, false);
|
154
101
|
const projectsInResolvedVersionPlans = resolvedVersionPlans.reduce((acc, plan) => {
|
155
102
|
if ('projectVersionBumps' in plan) {
|
156
103
|
for (const project in plan.projectVersionBumps) {
|
@@ -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)([
|