nx 19.6.0-beta.2 → 19.6.0-beta.3
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/schemas/nx-schema.json +30 -4
- package/src/command-line/release/changelog.js +9 -9
- package/src/command-line/release/command-object.d.ts +12 -3
- package/src/command-line/release/command-object.js +16 -1
- package/src/command-line/release/config/config.js +4 -2
- package/src/command-line/release/config/filter-release-groups.d.ts +2 -2
- package/src/command-line/release/config/filter-release-groups.js +1 -1
- package/src/command-line/release/config/version-plans.d.ts +1 -1
- package/src/command-line/release/config/version-plans.js +12 -12
- package/src/command-line/release/plan-check.d.ts +4 -0
- package/src/command-line/release/plan-check.js +225 -0
- package/src/command-line/release/plan.js +1 -1
- package/src/command-line/release/release.js +3 -3
- package/src/command-line/release/version.js +1 -1
- package/src/config/nx-json.d.ts +9 -2
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/utils/command-line-utils.js +1 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "19.6.0-beta.
|
3
|
+
"version": "19.6.0-beta.3",
|
4
4
|
"private": false,
|
5
5
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
6
6
|
"repository": {
|
@@ -71,7 +71,7 @@
|
|
71
71
|
"yargs-parser": "21.1.1",
|
72
72
|
"node-machine-id": "1.1.12",
|
73
73
|
"ora": "5.3.0",
|
74
|
-
"@nrwl/tao": "19.6.0-beta.
|
74
|
+
"@nrwl/tao": "19.6.0-beta.3"
|
75
75
|
},
|
76
76
|
"peerDependencies": {
|
77
77
|
"@swc-node/register": "^1.8.0",
|
@@ -86,16 +86,16 @@
|
|
86
86
|
}
|
87
87
|
},
|
88
88
|
"optionalDependencies": {
|
89
|
-
"@nx/nx-darwin-x64": "19.6.0-beta.
|
90
|
-
"@nx/nx-darwin-arm64": "19.6.0-beta.
|
91
|
-
"@nx/nx-linux-x64-gnu": "19.6.0-beta.
|
92
|
-
"@nx/nx-linux-x64-musl": "19.6.0-beta.
|
93
|
-
"@nx/nx-win32-x64-msvc": "19.6.0-beta.
|
94
|
-
"@nx/nx-linux-arm64-gnu": "19.6.0-beta.
|
95
|
-
"@nx/nx-linux-arm64-musl": "19.6.0-beta.
|
96
|
-
"@nx/nx-linux-arm-gnueabihf": "19.6.0-beta.
|
97
|
-
"@nx/nx-win32-arm64-msvc": "19.6.0-beta.
|
98
|
-
"@nx/nx-freebsd-x64": "19.6.0-beta.
|
89
|
+
"@nx/nx-darwin-x64": "19.6.0-beta.3",
|
90
|
+
"@nx/nx-darwin-arm64": "19.6.0-beta.3",
|
91
|
+
"@nx/nx-linux-x64-gnu": "19.6.0-beta.3",
|
92
|
+
"@nx/nx-linux-x64-musl": "19.6.0-beta.3",
|
93
|
+
"@nx/nx-win32-x64-msvc": "19.6.0-beta.3",
|
94
|
+
"@nx/nx-linux-arm64-gnu": "19.6.0-beta.3",
|
95
|
+
"@nx/nx-linux-arm64-musl": "19.6.0-beta.3",
|
96
|
+
"@nx/nx-linux-arm-gnueabihf": "19.6.0-beta.3",
|
97
|
+
"@nx/nx-win32-arm64-msvc": "19.6.0-beta.3",
|
98
|
+
"@nx/nx-freebsd-x64": "19.6.0-beta.3"
|
99
99
|
},
|
100
100
|
"nx-migrations": {
|
101
101
|
"migrations": "./migrations.json",
|
package/schemas/nx-schema.json
CHANGED
@@ -186,8 +186,15 @@
|
|
186
186
|
"type": "string"
|
187
187
|
},
|
188
188
|
"versionPlans": {
|
189
|
-
"
|
190
|
-
|
189
|
+
"oneOf": [
|
190
|
+
{
|
191
|
+
"$ref": "#/definitions/NxReleaseVersionPlansConfiguration"
|
192
|
+
},
|
193
|
+
{
|
194
|
+
"type": "boolean",
|
195
|
+
"description": "Enables using version plans as a specifier source for versioning and to determine changes for changelog generation."
|
196
|
+
}
|
197
|
+
]
|
191
198
|
}
|
192
199
|
},
|
193
200
|
"required": ["projects"]
|
@@ -239,8 +246,15 @@
|
|
239
246
|
"$ref": "#/definitions/NxReleaseVersionConfiguration"
|
240
247
|
},
|
241
248
|
"versionPlans": {
|
242
|
-
"
|
243
|
-
|
249
|
+
"oneOf": [
|
250
|
+
{
|
251
|
+
"$ref": "#/definitions/NxReleaseVersionPlansConfiguration"
|
252
|
+
},
|
253
|
+
{
|
254
|
+
"type": "boolean",
|
255
|
+
"description": "Enables using version plans as a specifier source for versioning and to determine changes for changelog generation."
|
256
|
+
}
|
257
|
+
]
|
244
258
|
},
|
245
259
|
"releaseTagPattern": {
|
246
260
|
"type": "string"
|
@@ -698,6 +712,18 @@
|
|
698
712
|
}
|
699
713
|
}
|
700
714
|
},
|
715
|
+
"NxReleaseVersionPlansConfiguration": {
|
716
|
+
"type": "object",
|
717
|
+
"properties": {
|
718
|
+
"ignorePatternsForPlanCheck": {
|
719
|
+
"type": "array",
|
720
|
+
"items": {
|
721
|
+
"type": "string"
|
722
|
+
},
|
723
|
+
"description": "Changes to files matching any of these optional patterns will be excluded from the affected project logic within the `nx release plan:check` command. This is useful for ignoring files that are not relevant to the versioning process, such as documentation or configuration files."
|
724
|
+
}
|
725
|
+
}
|
726
|
+
},
|
701
727
|
"ChangelogRenderOptions": {
|
702
728
|
"type": "object",
|
703
729
|
"additionalProperties": true
|
@@ -84,7 +84,7 @@ function createAPI(overrideReleaseConfig) {
|
|
84
84
|
process.exit(1);
|
85
85
|
}
|
86
86
|
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
87
|
-
(0, version_plans_1.
|
87
|
+
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
88
88
|
if (args.deleteVersionPlans === undefined) {
|
89
89
|
// default to deleting version plans in this command instead of after versioning
|
90
90
|
args.deleteVersionPlans = true;
|
@@ -140,12 +140,12 @@ function createAPI(overrideReleaseConfig) {
|
|
140
140
|
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
141
141
|
let workspaceChangelogCommits = [];
|
142
142
|
// If there are multiple release groups, we'll just skip the workspace changelog anyway.
|
143
|
-
const versionPlansEnabledForWorkspaceChangelog = releaseGroups[0].
|
143
|
+
const versionPlansEnabledForWorkspaceChangelog = releaseGroups[0].resolvedVersionPlans;
|
144
144
|
if (versionPlansEnabledForWorkspaceChangelog) {
|
145
145
|
if (releaseGroups.length === 1) {
|
146
146
|
const releaseGroup = releaseGroups[0];
|
147
147
|
if (releaseGroup.projectsRelationship === 'fixed') {
|
148
|
-
const versionPlans = releaseGroup.
|
148
|
+
const versionPlans = releaseGroup.resolvedVersionPlans;
|
149
149
|
workspaceChangelogChanges = versionPlans
|
150
150
|
.flatMap((vp) => {
|
151
151
|
const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
|
@@ -296,8 +296,8 @@ function createAPI(overrideReleaseConfig) {
|
|
296
296
|
let changes = null;
|
297
297
|
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
298
298
|
let commits;
|
299
|
-
if (releaseGroup.
|
300
|
-
changes = releaseGroup.
|
299
|
+
if (releaseGroup.resolvedVersionPlans) {
|
300
|
+
changes = releaseGroup.resolvedVersionPlans
|
301
301
|
.map((vp) => {
|
302
302
|
const bumpForProject = vp.projectVersionBumps[project.name];
|
303
303
|
if (!bumpForProject) {
|
@@ -396,8 +396,8 @@ function createAPI(overrideReleaseConfig) {
|
|
396
396
|
let changes = [];
|
397
397
|
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
398
398
|
let commits = [];
|
399
|
-
if (releaseGroup.
|
400
|
-
changes = releaseGroup.
|
399
|
+
if (releaseGroup.resolvedVersionPlans) {
|
400
|
+
changes = releaseGroup.resolvedVersionPlans
|
401
401
|
.flatMap((vp) => {
|
402
402
|
const releaseType = versionPlanSemverReleaseTypeToChangelogType(vp.groupVersionBump);
|
403
403
|
const changes = !vp.triggeredByProjects
|
@@ -585,8 +585,8 @@ async function applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTa
|
|
585
585
|
if (args.deleteVersionPlans && !args.dryRun) {
|
586
586
|
const planFiles = new Set();
|
587
587
|
releaseGroups.forEach((group) => {
|
588
|
-
if (group.
|
589
|
-
group.
|
588
|
+
if (group.resolvedVersionPlans) {
|
589
|
+
group.resolvedVersionPlans.forEach((plan) => {
|
590
590
|
(0, fs_extra_1.removeSync)(plan.absolutePath);
|
591
591
|
planFiles.add(plan.relativePath);
|
592
592
|
});
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import { CommandModule } from 'yargs';
|
2
2
|
import { OutputStyle, RunManyOptions } from '../yargs-utils/shared-options';
|
3
3
|
import { VersionData } from './utils/shared';
|
4
|
-
export interface
|
4
|
+
export interface BaseNxReleaseArgs {
|
5
|
+
verbose?: boolean;
|
6
|
+
printConfig?: boolean | 'debug';
|
7
|
+
}
|
8
|
+
export interface NxReleaseArgs extends BaseNxReleaseArgs {
|
5
9
|
groups?: string[];
|
6
10
|
projects?: string[];
|
7
11
|
dryRun?: boolean;
|
8
|
-
verbose?: boolean;
|
9
|
-
printConfig?: boolean | 'debug';
|
10
12
|
}
|
11
13
|
interface GitCommitAndTagOptions {
|
12
14
|
stageChanges?: boolean;
|
@@ -43,6 +45,13 @@ export type PlanOptions = NxReleaseArgs & {
|
|
43
45
|
bump?: string;
|
44
46
|
message?: string;
|
45
47
|
};
|
48
|
+
export type PlanCheckOptions = BaseNxReleaseArgs & {
|
49
|
+
base?: string;
|
50
|
+
head?: string;
|
51
|
+
files?: string;
|
52
|
+
uncommitted?: boolean;
|
53
|
+
untracked?: boolean;
|
54
|
+
};
|
46
55
|
export type ReleaseOptions = NxReleaseArgs & FirstReleaseArgs & {
|
47
56
|
yes?: boolean;
|
48
57
|
skipPublish?: boolean;
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.yargsReleaseCommand = void 0;
|
4
4
|
const yargs_1 = require("yargs");
|
5
5
|
const nx_json_1 = require("../../config/nx-json");
|
6
|
+
const command_line_utils_1 = require("../../utils/command-line-utils");
|
6
7
|
const logger_1 = require("../../utils/logger");
|
7
8
|
const shared_options_1 = require("../yargs-utils/shared-options");
|
8
|
-
const command_line_utils_1 = require("../../utils/command-line-utils");
|
9
9
|
exports.yargsReleaseCommand = {
|
10
10
|
command: 'release',
|
11
11
|
describe: 'Orchestrate versioning and publishing of applications and libraries',
|
@@ -15,6 +15,7 @@ exports.yargsReleaseCommand = {
|
|
15
15
|
.command(changelogCommand)
|
16
16
|
.command(publishCommand)
|
17
17
|
.command(planCommand)
|
18
|
+
.command(planCheckCommand)
|
18
19
|
.demandCommand()
|
19
20
|
// Error on typos/mistyped CLI args, there is no reason to support arbitrary unknown args for these commands
|
20
21
|
.strictOptions()
|
@@ -206,6 +207,7 @@ const publishCommand = {
|
|
206
207
|
const planCommand = {
|
207
208
|
command: 'plan [bump]',
|
208
209
|
aliases: ['pl'],
|
210
|
+
// TODO: Remove this when docs are added
|
209
211
|
// Create a plan to pick a new version and generate a changelog entry.
|
210
212
|
// Hidden for now until the feature is more stable
|
211
213
|
describe: false,
|
@@ -237,6 +239,19 @@ const planCommand = {
|
|
237
239
|
process.exit(result);
|
238
240
|
},
|
239
241
|
};
|
242
|
+
const planCheckCommand = {
|
243
|
+
command: 'plan:check',
|
244
|
+
// TODO: Remove this when docs are added
|
245
|
+
// Create a plan to pick a new version and generate a changelog entry.
|
246
|
+
// Hidden for now until the feature is more stable
|
247
|
+
describe: false,
|
248
|
+
builder: (yargs) => (0, shared_options_1.withAffectedOptions)(yargs),
|
249
|
+
handler: async (args) => {
|
250
|
+
const release = await Promise.resolve().then(() => require('./plan-check'));
|
251
|
+
const result = await release.releasePlanCheckCLIHandler(args);
|
252
|
+
process.exit(result);
|
253
|
+
},
|
254
|
+
};
|
240
255
|
function coerceParallelOption(args) {
|
241
256
|
return {
|
242
257
|
...args,
|
@@ -144,7 +144,8 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
144
144
|
? defaultIndependentReleaseTagPattern
|
145
145
|
: defaultFixedReleaseTagPattern),
|
146
146
|
conventionalCommits: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG,
|
147
|
-
versionPlans:
|
147
|
+
versionPlans: (userConfig.versionPlans ||
|
148
|
+
false),
|
148
149
|
};
|
149
150
|
const groupProjectsRelationship = userConfig.projectsRelationship || WORKSPACE_DEFAULTS.projectsRelationship;
|
150
151
|
const GROUP_DEFAULTS = {
|
@@ -200,7 +201,8 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
200
201
|
git: userConfig.git,
|
201
202
|
},
|
202
203
|
], normalizeTrueToEmptyObject(userConfig.changelog));
|
203
|
-
const rootVersionPlansConfig = userConfig.versionPlans ??
|
204
|
+
const rootVersionPlansConfig = (userConfig.versionPlans ??
|
205
|
+
WORKSPACE_DEFAULTS.versionPlans);
|
204
206
|
const rootConventionalCommitsConfig = deepMergeDefaults([WORKSPACE_DEFAULTS.conventionalCommits], fillUnspecifiedConventionalCommitsProperties(normalizeConventionalCommitsConfig(userConfig.conventionalCommits)));
|
205
207
|
// these options are not supported at the group level, only the root/command level
|
206
208
|
const rootVersionWithoutGlobalOptions = { ...rootVersionConfig };
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import { ProjectGraph } from '../../../config/project-graph';
|
2
2
|
import { NxReleaseConfig } from './config';
|
3
3
|
import { GroupVersionPlan, ProjectsVersionPlan } from './version-plans';
|
4
|
-
export type ReleaseGroupWithName =
|
4
|
+
export type ReleaseGroupWithName = NxReleaseConfig['groups'][string] & {
|
5
5
|
name: string;
|
6
|
-
|
6
|
+
resolvedVersionPlans: (ProjectsVersionPlan | GroupVersionPlan)[] | false;
|
7
7
|
};
|
8
8
|
export declare function filterReleaseGroups(projectGraph: ProjectGraph, nxReleaseConfig: NxReleaseConfig, projectsFilter?: string[], groupsFilter?: string[]): {
|
9
9
|
error: null | {
|
@@ -9,7 +9,7 @@ function filterReleaseGroups(projectGraph, nxReleaseConfig, projectsFilter, grou
|
|
9
9
|
return {
|
10
10
|
...group,
|
11
11
|
name,
|
12
|
-
|
12
|
+
resolvedVersionPlans: group.versionPlans ? [] : false,
|
13
13
|
};
|
14
14
|
});
|
15
15
|
const filteredProjectToReleaseGroup = new Map();
|
@@ -25,5 +25,5 @@ export interface ProjectsVersionPlan extends VersionPlan {
|
|
25
25
|
projectVersionBumps: Record<string, ReleaseType>;
|
26
26
|
}
|
27
27
|
export declare function readRawVersionPlans(): Promise<RawVersionPlan[]>;
|
28
|
-
export declare function
|
28
|
+
export declare function setResolvedVersionPlansOnGroups(rawVersionPlans: RawVersionPlan[], releaseGroups: ReleaseGroupWithName[], allProjectNamesInWorkspace: string[]): ReleaseGroupWithName[];
|
29
29
|
export declare function getVersionPlansAbsolutePath(): string;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.readRawVersionPlans = readRawVersionPlans;
|
4
|
-
exports.
|
4
|
+
exports.setResolvedVersionPlansOnGroups = setResolvedVersionPlansOnGroups;
|
5
5
|
exports.getVersionPlansAbsolutePath = getVersionPlansAbsolutePath;
|
6
6
|
const fs_1 = require("fs");
|
7
7
|
const fs_extra_1 = require("fs-extra");
|
@@ -35,7 +35,7 @@ async function readRawVersionPlans() {
|
|
35
35
|
}
|
36
36
|
return versionPlans;
|
37
37
|
}
|
38
|
-
function
|
38
|
+
function setResolvedVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNamesInWorkspace) {
|
39
39
|
const groupsByName = releaseGroups.reduce((acc, group) => acc.set(group.name, group), new Map());
|
40
40
|
const isDefaultGroup = isDefault(releaseGroups);
|
41
41
|
for (const rawVersionPlan of rawVersionPlans) {
|
@@ -45,7 +45,7 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
45
45
|
for (const [key, value] of Object.entries(rawVersionPlan.content)) {
|
46
46
|
if (groupsByName.has(key)) {
|
47
47
|
const group = groupsByName.get(key);
|
48
|
-
if (!group.
|
48
|
+
if (!group.resolvedVersionPlans) {
|
49
49
|
if (isDefaultGroup) {
|
50
50
|
throw new Error(`Found a version bump in '${rawVersionPlan.fileName}' but version plans are not enabled.`);
|
51
51
|
}
|
@@ -69,7 +69,7 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
69
69
|
throw new Error(`Found a version bump for group '${key}' in '${rawVersionPlan.fileName}' with an invalid release type. Please specify one of ${semver_1.RELEASE_TYPES.join(', ')}.`);
|
70
70
|
}
|
71
71
|
}
|
72
|
-
const existingPlan = (group.
|
72
|
+
const existingPlan = (group.resolvedVersionPlans.find((plan) => plan.fileName === rawVersionPlan.fileName));
|
73
73
|
if (existingPlan) {
|
74
74
|
if (existingPlan.groupVersionBump !== value) {
|
75
75
|
if (isDefaultGroup) {
|
@@ -81,7 +81,7 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
81
81
|
}
|
82
82
|
}
|
83
83
|
else {
|
84
|
-
group.
|
84
|
+
group.resolvedVersionPlans.push({
|
85
85
|
absolutePath: rawVersionPlan.absolutePath,
|
86
86
|
relativePath: rawVersionPlan.relativePath,
|
87
87
|
fileName: rawVersionPlan.fileName,
|
@@ -104,7 +104,7 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
104
104
|
throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' but the project is not in any configured release groups.`);
|
105
105
|
}
|
106
106
|
}
|
107
|
-
if (!groupForProject.
|
107
|
+
if (!groupForProject.resolvedVersionPlans) {
|
108
108
|
if (isDefaultGroup) {
|
109
109
|
throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' but version plans are not enabled.`);
|
110
110
|
}
|
@@ -116,12 +116,12 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
116
116
|
throw new Error(`Found a version bump for project '${key}' in '${rawVersionPlan.fileName}' with an invalid release type. Please specify one of ${semver_1.RELEASE_TYPES.join(', ')}.`);
|
117
117
|
}
|
118
118
|
if (groupForProject.projectsRelationship === 'independent') {
|
119
|
-
const existingPlan = (groupForProject.
|
119
|
+
const existingPlan = (groupForProject.resolvedVersionPlans.find((plan) => plan.fileName === rawVersionPlan.fileName));
|
120
120
|
if (existingPlan) {
|
121
121
|
existingPlan.projectVersionBumps[key] = value;
|
122
122
|
}
|
123
123
|
else {
|
124
|
-
groupForProject.
|
124
|
+
groupForProject.resolvedVersionPlans.push({
|
125
125
|
absolutePath: rawVersionPlan.absolutePath,
|
126
126
|
relativePath: rawVersionPlan.relativePath,
|
127
127
|
fileName: rawVersionPlan.fileName,
|
@@ -134,7 +134,7 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
134
134
|
}
|
135
135
|
}
|
136
136
|
else {
|
137
|
-
const existingPlan = (groupForProject.
|
137
|
+
const existingPlan = (groupForProject.resolvedVersionPlans.find((plan) => plan.fileName === rawVersionPlan.fileName));
|
138
138
|
// This can occur if the same fixed release group has multiple entries for different projects within
|
139
139
|
// the same version plan file. This will be the case when users are using the default release group.
|
140
140
|
if (existingPlan) {
|
@@ -151,7 +151,7 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
151
151
|
}
|
152
152
|
}
|
153
153
|
else {
|
154
|
-
groupForProject.
|
154
|
+
groupForProject.resolvedVersionPlans.push({
|
155
155
|
absolutePath: rawVersionPlan.absolutePath,
|
156
156
|
relativePath: rawVersionPlan.relativePath,
|
157
157
|
fileName: rawVersionPlan.fileName,
|
@@ -169,8 +169,8 @@ function setVersionPlansOnGroups(rawVersionPlans, releaseGroups, allProjectNames
|
|
169
169
|
}
|
170
170
|
// Order the plans from newest to oldest
|
171
171
|
releaseGroups.forEach((group) => {
|
172
|
-
if (group.
|
173
|
-
group.
|
172
|
+
if (group.resolvedVersionPlans) {
|
173
|
+
group.resolvedVersionPlans.sort((a, b) => b.createdOnMs - a.createdOnMs);
|
174
174
|
}
|
175
175
|
});
|
176
176
|
return releaseGroups;
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import { NxReleaseConfiguration } from '../../config/nx-json';
|
2
|
+
import { PlanCheckOptions, PlanOptions } from './command-object';
|
3
|
+
export declare const releasePlanCheckCLIHandler: (args: PlanCheckOptions) => Promise<number>;
|
4
|
+
export declare function createAPI(overrideReleaseConfig: NxReleaseConfiguration): (args: PlanOptions) => Promise<number>;
|
@@ -0,0 +1,225 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.releasePlanCheckCLIHandler = void 0;
|
4
|
+
exports.createAPI = createAPI;
|
5
|
+
const nx_json_1 = require("../../config/nx-json");
|
6
|
+
const workspace_projects_1 = require("../../project-graph/affected/locators/workspace-projects");
|
7
|
+
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
8
|
+
const file_utils_1 = require("../../project-graph/file-utils");
|
9
|
+
const project_graph_1 = require("../../project-graph/project-graph");
|
10
|
+
const all_file_data_1 = require("../../utils/all-file-data");
|
11
|
+
const command_line_utils_1 = require("../../utils/command-line-utils");
|
12
|
+
const ignore_1 = require("../../utils/ignore");
|
13
|
+
const output_1 = require("../../utils/output");
|
14
|
+
const params_1 = require("../../utils/params");
|
15
|
+
const config_1 = require("./config/config");
|
16
|
+
const deep_merge_json_1 = require("./config/deep-merge-json");
|
17
|
+
const filter_release_groups_1 = require("./config/filter-release-groups");
|
18
|
+
const version_plans_1 = require("./config/version-plans");
|
19
|
+
const print_config_1 = require("./utils/print-config");
|
20
|
+
const releasePlanCheckCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => createAPI({})(args));
|
21
|
+
exports.releasePlanCheckCLIHandler = releasePlanCheckCLIHandler;
|
22
|
+
function createAPI(overrideReleaseConfig) {
|
23
|
+
return async function releasePlanCheck(args) {
|
24
|
+
const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
|
25
|
+
const nxJson = (0, nx_json_1.readNxJson)();
|
26
|
+
const userProvidedReleaseConfig = (0, deep_merge_json_1.deepMergeJson)(nxJson.release ?? {}, overrideReleaseConfig ?? {});
|
27
|
+
if (args.verbose) {
|
28
|
+
process.env.NX_VERBOSE_LOGGING = 'true';
|
29
|
+
}
|
30
|
+
// Apply default configuration to any optional user configuration
|
31
|
+
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig);
|
32
|
+
if (configError) {
|
33
|
+
return await (0, config_1.handleNxReleaseConfigError)(configError);
|
34
|
+
}
|
35
|
+
// --print-config exits directly as it is not designed to be combined with any other programmatic operations
|
36
|
+
if (args.printConfig) {
|
37
|
+
return (0, print_config_1.printConfigAndExit)({
|
38
|
+
userProvidedReleaseConfig,
|
39
|
+
nxReleaseConfig,
|
40
|
+
isDebug: args.printConfig === 'debug',
|
41
|
+
});
|
42
|
+
}
|
43
|
+
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
44
|
+
if (filterError) {
|
45
|
+
output_1.output.error(filterError);
|
46
|
+
process.exit(1);
|
47
|
+
}
|
48
|
+
// If no release groups have version plans enabled, provide an explicit error
|
49
|
+
if (!releaseGroups.some((group) => group.versionPlans)) {
|
50
|
+
output_1.output.error({
|
51
|
+
title: 'Version plans are not enabled',
|
52
|
+
bodyLines: [
|
53
|
+
'Please ensure at least one release group has version plans enabled in your Nx release configuration if you want to use this command.',
|
54
|
+
// TODO: Add docs link here once it is available
|
55
|
+
],
|
56
|
+
});
|
57
|
+
return 1;
|
58
|
+
}
|
59
|
+
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
60
|
+
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
61
|
+
// Resolve the final values for base, head etc to use when resolving the changes to consider
|
62
|
+
const { nxArgs } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'affected', {
|
63
|
+
printWarnings: args.verbose,
|
64
|
+
}, nxJson);
|
65
|
+
const changedFiles = (0, command_line_utils_1.parseFiles)(nxArgs).files;
|
66
|
+
if (nxArgs.verbose) {
|
67
|
+
if (changedFiles.length) {
|
68
|
+
output_1.output.log({
|
69
|
+
title: `Changed files based on resolved "base" (${nxArgs.base}) and "head" (${nxArgs.head ?? 'HEAD'})`,
|
70
|
+
bodyLines: changedFiles.map((file) => ` - ${file}`),
|
71
|
+
});
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
output_1.output.warn({
|
75
|
+
title: 'No changed files found based on resolved "base" and "head"',
|
76
|
+
});
|
77
|
+
}
|
78
|
+
}
|
79
|
+
const resolvedAllFileData = await (0, all_file_data_1.allFileData)();
|
80
|
+
/**
|
81
|
+
* Create a minimal subset of touched projects based on the configured ignore patterns, we only need
|
82
|
+
* to recompute when the ignorePatternsForPlanCheck differs between release groups.
|
83
|
+
*/
|
84
|
+
const serializedIgnorePatternsToTouchedProjects = new Map();
|
85
|
+
const NOTE_ABOUT_VERBOSE_LOGGING = 'Run with --verbose to see the full list of changed files used for the touched projects logic.';
|
86
|
+
let hasErrors = false;
|
87
|
+
for (const releaseGroup of releaseGroups) {
|
88
|
+
// The current release group doesn't leverage version plans
|
89
|
+
if (!releaseGroup.versionPlans) {
|
90
|
+
continue;
|
91
|
+
}
|
92
|
+
const resolvedVersionPlans = releaseGroup.resolvedVersionPlans || [];
|
93
|
+
// Check upfront if the release group as a whole is featured in any version plan files
|
94
|
+
const matchingVersionPlanFiles = resolvedVersionPlans.filter((plan) => 'groupVersionBump' in plan);
|
95
|
+
if (matchingVersionPlanFiles.length) {
|
96
|
+
output_1.output.log({
|
97
|
+
title: `${releaseGroup.name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
98
|
+
? `There are`
|
99
|
+
: `Release group "${releaseGroup.name}" has`} pending bumps in version plan(s)`,
|
100
|
+
bodyLines: [
|
101
|
+
...matchingVersionPlanFiles.map((plan) => ` - "${plan.groupVersionBump}" in ${plan.fileName}`),
|
102
|
+
],
|
103
|
+
});
|
104
|
+
continue;
|
105
|
+
}
|
106
|
+
// Exclude patterns from .nxignore, .gitignore and explicit version plan config
|
107
|
+
let serializedIgnorePatterns = '[]';
|
108
|
+
const ignore = (0, ignore_1.getIgnoreObject)();
|
109
|
+
if (typeof releaseGroup.versionPlans !== 'boolean' &&
|
110
|
+
Array.isArray(releaseGroup.versionPlans.ignorePatternsForPlanCheck) &&
|
111
|
+
releaseGroup.versionPlans.ignorePatternsForPlanCheck.length) {
|
112
|
+
output_1.output.note({
|
113
|
+
title: `Applying configured ignore patterns to changed files${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
114
|
+
? ` for release group "${releaseGroup.name}"`
|
115
|
+
: ''}`,
|
116
|
+
bodyLines: [
|
117
|
+
...releaseGroup.versionPlans.ignorePatternsForPlanCheck.map((pattern) => ` - ${pattern}`),
|
118
|
+
],
|
119
|
+
});
|
120
|
+
ignore.add(releaseGroup.versionPlans.ignorePatternsForPlanCheck);
|
121
|
+
serializedIgnorePatterns = JSON.stringify(releaseGroup.versionPlans.ignorePatternsForPlanCheck);
|
122
|
+
}
|
123
|
+
let touchedProjects = {};
|
124
|
+
if (serializedIgnorePatternsToTouchedProjects.has(serializedIgnorePatterns)) {
|
125
|
+
touchedProjects = serializedIgnorePatternsToTouchedProjects.get(serializedIgnorePatterns);
|
126
|
+
}
|
127
|
+
else {
|
128
|
+
// We only care about directly touched projects, not implicitly affected ones etc
|
129
|
+
const touchedProjectsArr = await (0, workspace_projects_1.getTouchedProjects)((0, file_utils_1.calculateFileChanges)(changedFiles, resolvedAllFileData, nxArgs, undefined, ignore), projectGraph.nodes);
|
130
|
+
touchedProjects = touchedProjectsArr.reduce((acc, project) => ({ ...acc, [project]: true }), {});
|
131
|
+
serializedIgnorePatternsToTouchedProjects.set(serializedIgnorePatterns, touchedProjects);
|
132
|
+
}
|
133
|
+
const touchedProjectsUnderReleaseGroup = releaseGroup.projects.filter((project) => touchedProjects[project]);
|
134
|
+
if (touchedProjectsUnderReleaseGroup.length) {
|
135
|
+
output_1.output.log({
|
136
|
+
title: `Touched projects based on changed files${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
137
|
+
? ` under release group "${releaseGroup.name}"`
|
138
|
+
: ''}`,
|
139
|
+
bodyLines: [
|
140
|
+
...touchedProjectsUnderReleaseGroup.map((project) => ` - ${project}`),
|
141
|
+
'',
|
142
|
+
'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.',
|
143
|
+
],
|
144
|
+
});
|
145
|
+
}
|
146
|
+
else {
|
147
|
+
output_1.output.log({
|
148
|
+
title: `No touched projects found based on changed files${typeof releaseGroup.versionPlans !== 'boolean' &&
|
149
|
+
Array.isArray(releaseGroup.versionPlans.ignorePatternsForPlanCheck) &&
|
150
|
+
releaseGroup.versionPlans.ignorePatternsForPlanCheck.length
|
151
|
+
? ' combined with configured ignore patterns'
|
152
|
+
: ''}${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
153
|
+
? ` under release group "${releaseGroup.name}"`
|
154
|
+
: ''}`,
|
155
|
+
});
|
156
|
+
}
|
157
|
+
const projectsInResolvedVersionPlans = resolvedVersionPlans.reduce((acc, plan) => {
|
158
|
+
if ('projectVersionBumps' in plan) {
|
159
|
+
for (const project in plan.projectVersionBumps) {
|
160
|
+
acc[project] = acc[project] || [];
|
161
|
+
acc[project].push({
|
162
|
+
bump: plan.projectVersionBumps[project],
|
163
|
+
fileName: plan.fileName,
|
164
|
+
});
|
165
|
+
}
|
166
|
+
}
|
167
|
+
return acc;
|
168
|
+
}, {});
|
169
|
+
// Ensure each touched project under this release group features in at least one version plan file
|
170
|
+
let touchedProjectsNotFoundInVersionPlans = [];
|
171
|
+
for (const touchedProject of touchedProjectsUnderReleaseGroup) {
|
172
|
+
if (!resolvedVersionPlans.length) {
|
173
|
+
touchedProjectsNotFoundInVersionPlans.push(touchedProject);
|
174
|
+
continue;
|
175
|
+
}
|
176
|
+
const matchingVersionPlanFileEntries = projectsInResolvedVersionPlans[touchedProject];
|
177
|
+
if (!matchingVersionPlanFileEntries?.length) {
|
178
|
+
touchedProjectsNotFoundInVersionPlans.push(touchedProject);
|
179
|
+
continue;
|
180
|
+
}
|
181
|
+
}
|
182
|
+
// Log any resolved pending bumps, regardless of whether the projects were directly touched or not
|
183
|
+
for (const [projectName, entries] of Object.entries(projectsInResolvedVersionPlans)) {
|
184
|
+
output_1.output.log({
|
185
|
+
title: `Project "${projectName}" has pending bumps in version plan(s)`,
|
186
|
+
bodyLines: [
|
187
|
+
...entries.map(({ bump, fileName }) => ` - "${bump}" in ${fileName}`),
|
188
|
+
],
|
189
|
+
});
|
190
|
+
}
|
191
|
+
if (touchedProjectsNotFoundInVersionPlans.length) {
|
192
|
+
const bodyLines = [
|
193
|
+
`The following touched projects${releaseGroup.name !== config_1.IMPLICIT_DEFAULT_RELEASE_GROUP
|
194
|
+
? ` under release group "${releaseGroup.name}"`
|
195
|
+
: ''} do not feature in any version plan files:`,
|
196
|
+
...touchedProjectsNotFoundInVersionPlans.map((project) => ` - ${project}`),
|
197
|
+
'',
|
198
|
+
'Please use `nx release plan` to generate missing version plans, or adjust your "versionPlans.ignorePatternsForPlanCheck" config stop certain files from affecting the projects for the purposes of this command.',
|
199
|
+
];
|
200
|
+
if (!nxArgs.verbose) {
|
201
|
+
bodyLines.push('', NOTE_ABOUT_VERBOSE_LOGGING);
|
202
|
+
}
|
203
|
+
output_1.output.error({
|
204
|
+
title: 'Touched projects missing version plans',
|
205
|
+
bodyLines,
|
206
|
+
});
|
207
|
+
// At least one project in one release group has an issue
|
208
|
+
hasErrors = true;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
// Do not print success message if any projects are missing version plans
|
212
|
+
if (hasErrors) {
|
213
|
+
return 1;
|
214
|
+
}
|
215
|
+
const bodyLines = [];
|
216
|
+
if (!nxArgs.verbose) {
|
217
|
+
bodyLines.push(NOTE_ABOUT_VERBOSE_LOGGING);
|
218
|
+
}
|
219
|
+
output_1.output.success({
|
220
|
+
title: 'All touched projects have, or do not require, version plans.',
|
221
|
+
bodyLines,
|
222
|
+
});
|
223
|
+
return 0;
|
224
|
+
};
|
225
|
+
}
|
@@ -31,7 +31,7 @@ function createAPI(overrideReleaseConfig) {
|
|
31
31
|
process.env.NX_VERBOSE_LOGGING = 'true';
|
32
32
|
}
|
33
33
|
// Apply default configuration to any optional user configuration
|
34
|
-
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph),
|
34
|
+
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig);
|
35
35
|
if (configError) {
|
36
36
|
return await (0, config_1.handleNxReleaseConfigError)(configError);
|
37
37
|
}
|
@@ -88,17 +88,17 @@ function createAPI(overrideReleaseConfig) {
|
|
88
88
|
process.exit(1);
|
89
89
|
}
|
90
90
|
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
91
|
-
(0, version_plans_1.
|
91
|
+
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
92
92
|
const planFiles = new Set();
|
93
93
|
releaseGroups.forEach((group) => {
|
94
|
-
if (group.
|
94
|
+
if (group.resolvedVersionPlans) {
|
95
95
|
if (group.name === config_1.IMPLICIT_DEFAULT_RELEASE_GROUP) {
|
96
96
|
output_1.output.logSingleLine(`Removing version plan files`);
|
97
97
|
}
|
98
98
|
else {
|
99
99
|
output_1.output.logSingleLine(`Removing version plan files for group ${group.name}`);
|
100
100
|
}
|
101
|
-
group.
|
101
|
+
group.resolvedVersionPlans.forEach((plan) => {
|
102
102
|
if (!args.dryRun) {
|
103
103
|
(0, fs_extra_1.removeSync)(plan.absolutePath);
|
104
104
|
if (args.verbose) {
|
@@ -84,7 +84,7 @@ function createAPI(overrideReleaseConfig) {
|
|
84
84
|
process.exit(1);
|
85
85
|
}
|
86
86
|
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
87
|
-
(0, version_plans_1.
|
87
|
+
(0, version_plans_1.setResolvedVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
88
88
|
if (args.deleteVersionPlans === undefined) {
|
89
89
|
// default to not delete version plans after versioning as they may be needed for changelog generation
|
90
90
|
args.deleteVersionPlans = false;
|
package/src/config/nx-json.d.ts
CHANGED
@@ -145,6 +145,13 @@ export interface NxReleaseConventionalCommitsConfiguration {
|
|
145
145
|
} | boolean;
|
146
146
|
} | boolean>;
|
147
147
|
}
|
148
|
+
export interface NxReleaseVersionPlansConfiguration {
|
149
|
+
/**
|
150
|
+
* Changes to files matching any of these optional patterns will be excluded from the affected project logic within the `nx release plan:check`
|
151
|
+
* command. This is useful for ignoring files that are not relevant to the versioning process, such as documentation or configuration files.
|
152
|
+
*/
|
153
|
+
ignorePatternsForPlanCheck?: string[];
|
154
|
+
}
|
148
155
|
export interface NxReleaseConfiguration {
|
149
156
|
/**
|
150
157
|
* Shorthand for amending the projects which will be included in the implicit default release group (all projects by default).
|
@@ -193,7 +200,7 @@ export interface NxReleaseConfiguration {
|
|
193
200
|
* Enables using version plans as a specifier source for versioning and
|
194
201
|
* to determine changes for changelog generation.
|
195
202
|
*/
|
196
|
-
versionPlans?: boolean;
|
203
|
+
versionPlans?: NxReleaseVersionPlansConfiguration | boolean;
|
197
204
|
}>;
|
198
205
|
/**
|
199
206
|
* Configures the default value for all groups that don't explicitly state their own projectsRelationship.
|
@@ -264,7 +271,7 @@ export interface NxReleaseConfiguration {
|
|
264
271
|
* Enables using version plans as a specifier source for versioning and
|
265
272
|
* to determine changes for changelog generation.
|
266
273
|
*/
|
267
|
-
versionPlans?: boolean;
|
274
|
+
versionPlans?: NxReleaseVersionPlansConfiguration | boolean;
|
268
275
|
}
|
269
276
|
export interface NxSyncConfiguration {
|
270
277
|
/**
|
Binary file
|
@@ -70,7 +70,7 @@ function splitArgsIntoNxArgsAndOverrides(args, mode, options = { printWarnings:
|
|
70
70
|
],
|
71
71
|
});
|
72
72
|
}
|
73
|
-
// Allow setting base and head via environment variables (lower priority
|
73
|
+
// Allow setting base and head via environment variables (lower priority than direct command arguments)
|
74
74
|
if (!nxArgs.base && process.env.NX_BASE) {
|
75
75
|
nxArgs.base = process.env.NX_BASE;
|
76
76
|
if (options.printWarnings) {
|