nx 21.3.0-rc.0 → 21.3.1
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/bin/nx.js +19 -2
- package/package.json +11 -11
- package/schemas/nx-schema.json +18 -0
- package/src/command-line/init/implementation/add-nx-to-monorepo.d.ts +1 -1
- package/src/command-line/init/implementation/add-nx-to-monorepo.js +2 -2
- package/src/command-line/init/implementation/add-nx-to-npm-repo.d.ts +1 -1
- package/src/command-line/init/implementation/add-nx-to-npm-repo.js +2 -2
- package/src/command-line/init/implementation/utils.js +1 -5
- package/src/command-line/init/init-v2.js +44 -22
- package/src/command-line/release/changelog.js +47 -3
- package/src/command-line/release/config/config.js +14 -1
- package/src/command-line/release/utils/git.d.ts +35 -4
- package/src/command-line/release/utils/git.js +71 -11
- package/src/command-line/release/utils/shared.d.ts +1 -0
- package/src/command-line/release/utils/shared.js +1 -0
- package/src/command-line/release/version/release-group-processor.js +6 -1
- package/src/config/nx-json.d.ts +40 -0
- package/src/core/graph/main.js +1 -1
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +3 -7
- package/src/utils/ab-testing.d.ts +3 -3
- package/src/utils/ab-testing.js +3 -3
package/bin/nx.js
CHANGED
@@ -64,14 +64,14 @@ async function main() {
|
|
64
64
|
if (!workspace) {
|
65
65
|
handleNoWorkspace(GLOBAL_NX_VERSION);
|
66
66
|
}
|
67
|
-
if (!localNx) {
|
67
|
+
if (!localNx && !isNxCloudCommand(process.argv[2])) {
|
68
68
|
handleMissingLocalInstallation(workspace ? workspace.dir : null);
|
69
69
|
}
|
70
70
|
// this file is already in the local workspace
|
71
71
|
if (isLocalInstall) {
|
72
72
|
await (0, init_local_1.initLocal)(workspace);
|
73
73
|
}
|
74
|
-
else {
|
74
|
+
else if (localNx) {
|
75
75
|
// Nx is being run from globally installed CLI - hand off to the local
|
76
76
|
warnIfUsingOutdatedGlobalInstall(GLOBAL_NX_VERSION, LOCAL_NX_VERSION);
|
77
77
|
if (localNx.includes('.nx')) {
|
@@ -82,6 +82,11 @@ async function main() {
|
|
82
82
|
require(localNx);
|
83
83
|
}
|
84
84
|
}
|
85
|
+
else if (isNxCloudCommand(process.argv[2])) {
|
86
|
+
// nx-cloud commands can run without local Nx installation
|
87
|
+
process.env.NX_DAEMON = 'false';
|
88
|
+
require('nx/src/command-line/nx-commands').commandsObject.argv;
|
89
|
+
}
|
85
90
|
}
|
86
91
|
}
|
87
92
|
function handleNoWorkspace(globalNxVersion) {
|
@@ -132,6 +137,18 @@ function resolveNx(workspace) {
|
|
132
137
|
paths: [workspace ? workspace.dir : globalsRoot],
|
133
138
|
});
|
134
139
|
}
|
140
|
+
function isNxCloudCommand(command) {
|
141
|
+
const nxCloudCommands = [
|
142
|
+
'start-ci-run',
|
143
|
+
'login',
|
144
|
+
'logout',
|
145
|
+
'connect',
|
146
|
+
'view-logs',
|
147
|
+
'fix-ci',
|
148
|
+
'record',
|
149
|
+
];
|
150
|
+
return nxCloudCommands.includes(command);
|
151
|
+
}
|
135
152
|
function handleMissingLocalInstallation(detectedWorkspaceRoot) {
|
136
153
|
output_1.output.error({
|
137
154
|
title: detectedWorkspaceRoot
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "21.3.
|
3
|
+
"version": "21.3.1",
|
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": {
|
@@ -83,16 +83,16 @@
|
|
83
83
|
}
|
84
84
|
},
|
85
85
|
"optionalDependencies": {
|
86
|
-
"@nx/nx-darwin-arm64": "21.3.
|
87
|
-
"@nx/nx-darwin-x64": "21.3.
|
88
|
-
"@nx/nx-freebsd-x64": "21.3.
|
89
|
-
"@nx/nx-linux-arm-gnueabihf": "21.3.
|
90
|
-
"@nx/nx-linux-arm64-gnu": "21.3.
|
91
|
-
"@nx/nx-linux-arm64-musl": "21.3.
|
92
|
-
"@nx/nx-linux-x64-gnu": "21.3.
|
93
|
-
"@nx/nx-linux-x64-musl": "21.3.
|
94
|
-
"@nx/nx-win32-arm64-msvc": "21.3.
|
95
|
-
"@nx/nx-win32-x64-msvc": "21.3.
|
86
|
+
"@nx/nx-darwin-arm64": "21.3.1",
|
87
|
+
"@nx/nx-darwin-x64": "21.3.1",
|
88
|
+
"@nx/nx-freebsd-x64": "21.3.1",
|
89
|
+
"@nx/nx-linux-arm-gnueabihf": "21.3.1",
|
90
|
+
"@nx/nx-linux-arm64-gnu": "21.3.1",
|
91
|
+
"@nx/nx-linux-arm64-musl": "21.3.1",
|
92
|
+
"@nx/nx-linux-x64-gnu": "21.3.1",
|
93
|
+
"@nx/nx-linux-x64-musl": "21.3.1",
|
94
|
+
"@nx/nx-win32-arm64-msvc": "21.3.1",
|
95
|
+
"@nx/nx-win32-x64-msvc": "21.3.1"
|
96
96
|
},
|
97
97
|
"nx-migrations": {
|
98
98
|
"migrations": "./migrations.json",
|
package/schemas/nx-schema.json
CHANGED
@@ -207,6 +207,13 @@
|
|
207
207
|
],
|
208
208
|
"description": "By default, we will try and resolve the latest match for the releaseTagPattern from the current branch, falling back to all branches if no match is found on the current branch. Setting this to true will cause us to ALWAYS check all branches for the latest match. Setting it to false will cause us to ONLY check the current branch for the latest match. Setting it to an array of strings will cause us to check all branches WHEN the current branch is one of the strings in the array. Glob patterns are supported."
|
209
209
|
},
|
210
|
+
"releaseTagPatternRequireSemver": {
|
211
|
+
"type": "boolean",
|
212
|
+
"description": "Whether to require semver to be used for the release tag pattern. If set to false, the release tag pattern will not be checked for semver compliance."
|
213
|
+
},
|
214
|
+
"releaseTagPatternStrictPreid": {
|
215
|
+
"$ref": "#/definitions/NxReleaseReleaseTagPatternStrictPreidConfiguration"
|
216
|
+
},
|
210
217
|
"versionPlans": {
|
211
218
|
"oneOf": [
|
212
219
|
{
|
@@ -295,6 +302,13 @@
|
|
295
302
|
}
|
296
303
|
],
|
297
304
|
"description": "By default, we will try and resolve the latest match for the releaseTagPattern from the current branch, falling back to all branches if no match is found on the current branch. Setting this to true will cause us to ALWAYS check all branches for the latest match. Setting it to false will cause us to ONLY check the current branch for the latest match. Setting it to an array of strings will cause us to check all branches WHEN the current branch is one of the strings in the array. Glob patterns are supported."
|
305
|
+
},
|
306
|
+
"releaseTagPatternRequireSemver": {
|
307
|
+
"type": "boolean",
|
308
|
+
"description": "Whether to require semver to be used for the release tag pattern. If set to false, the release tag pattern will not be checked for semver compliance."
|
309
|
+
},
|
310
|
+
"releaseTagPatternStrictPreid": {
|
311
|
+
"$ref": "#/definitions/NxReleaseReleaseTagPatternStrictPreidConfiguration"
|
298
312
|
}
|
299
313
|
}
|
300
314
|
},
|
@@ -925,6 +939,10 @@
|
|
925
939
|
}
|
926
940
|
}
|
927
941
|
},
|
942
|
+
"NxReleaseReleaseTagPatternStrictPreidConfiguration": {
|
943
|
+
"type": "boolean",
|
944
|
+
"description": "When set to true and multiple tags match your configured \"releaseTagPattern\", the git tag matching logic will strictly prefer the tag which contain a semver preid which matches the one given to the nx release invocation.\n\nFor example, let's say your \"releaseTagPattern\" is \"{projectName}@{version}\" and you have the following tags for project \"my-lib\", which uses semver:\n- my-lib@1.2.4-beta.1\n- my-lib@1.2.4-alpha.1\n- my-lib@1.2.3\n\nIf \"releaseTagPatternStrictPreid\" is set to true and you run:\n- `nx release --preid beta`, the git tag \"my-lib@1.2.4-beta.1\" will be resolved.\n- `nx release --preid alpha`, the git tag \"my-lib@1.2.4-alpha.1\" will be resolved.\n- `nx release` (no preid), the git tag \"my-lib@1.2.3\" will be resolved.\n\nIf \"releaseTagPatternStrictPreid\" is set to false, the git tag \"my-lib@1.2.4-beta.1\" will always be resolved as the latest tag that matches the pattern, regardless of any preid which gets passed to nx release.\n\nNOTE: This feature was added in a minor version and is therefore set to false by default, but this may change in a future major version."
|
945
|
+
},
|
928
946
|
"ChangelogRenderOptions": {
|
929
947
|
"type": "object",
|
930
948
|
"additionalProperties": true
|
@@ -2,5 +2,5 @@ import { InitArgs } from '../init-v1';
|
|
2
2
|
type Options = Pick<InitArgs, 'nxCloud' | 'interactive' | 'cacheable'> & {
|
3
3
|
legacy?: boolean;
|
4
4
|
};
|
5
|
-
export declare function addNxToMonorepo(options: Options): Promise<void>;
|
5
|
+
export declare function addNxToMonorepo(options: Options, guided?: boolean): Promise<void>;
|
6
6
|
export {};
|
@@ -9,7 +9,7 @@ const fileutils_1 = require("../../../utils/fileutils");
|
|
9
9
|
const output_1 = require("../../../utils/output");
|
10
10
|
const utils_1 = require("./utils");
|
11
11
|
const connect_to_nx_cloud_1 = require("../../nx-cloud/connect/connect-to-nx-cloud");
|
12
|
-
async function addNxToMonorepo(options) {
|
12
|
+
async function addNxToMonorepo(options, guided = true) {
|
13
13
|
const repoRoot = process.cwd();
|
14
14
|
output_1.output.log({ title: '🐳 Nx initialization' });
|
15
15
|
const packageJsonFiles = allProjectPackageJsonFiles(repoRoot);
|
@@ -18,7 +18,7 @@ async function addNxToMonorepo(options) {
|
|
18
18
|
let cacheableOperations;
|
19
19
|
let scriptOutputs = {};
|
20
20
|
let useNxCloud;
|
21
|
-
if (options.interactive && scripts.length > 0) {
|
21
|
+
if (options.interactive && scripts.length > 0 && guided) {
|
22
22
|
output_1.output.log({
|
23
23
|
title: '🧑🔧 Please answer the following questions about the scripts found in your workspace in order to generate task runner configuration',
|
24
24
|
});
|
@@ -2,5 +2,5 @@ import { InitArgs } from '../init-v1';
|
|
2
2
|
type Options = Pick<InitArgs, 'nxCloud' | 'interactive' | 'cacheable'> & {
|
3
3
|
legacy?: boolean;
|
4
4
|
};
|
5
|
-
export declare function addNxToNpmRepo(options: Options): Promise<void>;
|
5
|
+
export declare function addNxToNpmRepo(options: Options, guided?: boolean): Promise<void>;
|
6
6
|
export {};
|
@@ -8,7 +8,7 @@ const output_1 = require("../../../utils/output");
|
|
8
8
|
const package_manager_1 = require("../../../utils/package-manager");
|
9
9
|
const utils_1 = require("./utils");
|
10
10
|
const connect_to_nx_cloud_1 = require("../../nx-cloud/connect/connect-to-nx-cloud");
|
11
|
-
async function addNxToNpmRepo(options) {
|
11
|
+
async function addNxToNpmRepo(options, guided = true) {
|
12
12
|
const repoRoot = process.cwd();
|
13
13
|
output_1.output.log({ title: '🐳 Nx initialization' });
|
14
14
|
let cacheableOperations;
|
@@ -16,7 +16,7 @@ async function addNxToNpmRepo(options) {
|
|
16
16
|
let useNxCloud;
|
17
17
|
const packageJson = (0, fileutils_1.readJsonFile)('package.json');
|
18
18
|
const scripts = Object.keys(packageJson.scripts ?? {}).filter((s) => !s.startsWith('pre') && !s.startsWith('post'));
|
19
|
-
if (options.interactive && scripts.length > 0) {
|
19
|
+
if (options.interactive && scripts.length > 0 && guided) {
|
20
20
|
output_1.output.log({
|
21
21
|
title: '🧑🔧 Please answer the following questions about the scripts found in your package.json in order to generate task runner configuration',
|
22
22
|
});
|
@@ -24,7 +24,6 @@ const connect_to_nx_cloud_1 = require("../../../nx-cloud/generators/connect-to-n
|
|
24
24
|
const url_shorten_1 = require("../../../nx-cloud/utilities/url-shorten");
|
25
25
|
const connect_to_nx_cloud_2 = require("../../nx-cloud/connect/connect-to-nx-cloud");
|
26
26
|
const deduce_default_base_1 = require("./deduce-default-base");
|
27
|
-
const child_process_2 = require("../../../utils/child-process");
|
28
27
|
function createNxJsonFile(repoRoot, topologicalTargets, cacheableOperations, scriptOutputs) {
|
29
28
|
const nxJsonPath = (0, path_2.joinPathFragments)(repoRoot, 'nx.json');
|
30
29
|
let nxJson = {};
|
@@ -263,13 +262,10 @@ function markPackageJsonAsNxProject(packageJsonPath) {
|
|
263
262
|
(0, fileutils_1.writeJsonFile)(packageJsonPath, json);
|
264
263
|
}
|
265
264
|
function printFinalMessage({ learnMoreLink, appendLines, }) {
|
266
|
-
const pmc = (0, package_manager_1.getPackageManagerCommand)();
|
267
265
|
output_1.output.success({
|
268
266
|
title: '🎉 Done!',
|
269
267
|
bodyLines: [
|
270
|
-
`-
|
271
|
-
`- Run "${(0, child_process_2.getRunNxBaseCommand)(pmc)} graph" to see the graph of projects and tasks in your workspace. https://nx.dev/core-features/explore-graph`,
|
272
|
-
learnMoreLink ? `- Learn more at ${learnMoreLink}.` : undefined,
|
268
|
+
`- Learn more about what to do next at ${learnMoreLink ?? 'https://nx.dev/getting-started/adding-to-existing'}`,
|
273
269
|
...(appendLines ?? []),
|
274
270
|
].filter(Boolean),
|
275
271
|
});
|
@@ -34,7 +34,7 @@ async function initHandler(options) {
|
|
34
34
|
integrated: !!options.integrated,
|
35
35
|
});
|
36
36
|
(0, utils_1.printFinalMessage)({
|
37
|
-
learnMoreLink: 'https://nx.dev/
|
37
|
+
learnMoreLink: 'https://nx.dev/technologies/angular/migration/angular',
|
38
38
|
});
|
39
39
|
return;
|
40
40
|
}
|
@@ -45,6 +45,21 @@ async function initHandler(options) {
|
|
45
45
|
const _isTurborepo = (0, fs_1.existsSync)('turbo.json');
|
46
46
|
const _isMonorepo = _isNonJs ? false : (0, utils_1.isMonorepo)(packageJson);
|
47
47
|
const _isCRA = _isNonJs ? false : (0, utils_1.isCRA)(packageJson);
|
48
|
+
let guided = true;
|
49
|
+
if (options.interactive && !(_isTurborepo || _isCRA || _isNonJs)) {
|
50
|
+
const setupType = await (0, enquirer_1.prompt)([
|
51
|
+
{
|
52
|
+
type: 'select',
|
53
|
+
name: 'setupPreference',
|
54
|
+
message: 'Would you like a minimum or guided setup?',
|
55
|
+
choices: [
|
56
|
+
{ name: 'Minimum', value: 'min' },
|
57
|
+
{ name: 'Guided', value: 'guided' },
|
58
|
+
],
|
59
|
+
},
|
60
|
+
]).then((r) => r.setupPreference);
|
61
|
+
guided = setupType === 'guided';
|
62
|
+
}
|
48
63
|
/**
|
49
64
|
* Turborepo users must have set up individual scripts already, and we keep the transition as minimal as possible.
|
50
65
|
* We log a message during the conversion process in addNxToTurborepo about how they can learn more about the power
|
@@ -75,7 +90,7 @@ async function initHandler(options) {
|
|
75
90
|
await (0, add_nx_to_monorepo_1.addNxToMonorepo)({
|
76
91
|
interactive: options.interactive,
|
77
92
|
nxCloud: false,
|
78
|
-
});
|
93
|
+
}, guided);
|
79
94
|
}
|
80
95
|
else if (_isNonJs) {
|
81
96
|
(0, add_nx_scripts_1.generateDotNxSetup)(version);
|
@@ -85,41 +100,48 @@ async function initHandler(options) {
|
|
85
100
|
await (0, add_nx_to_npm_repo_1.addNxToNpmRepo)({
|
86
101
|
interactive: options.interactive,
|
87
102
|
nxCloud: false,
|
88
|
-
});
|
103
|
+
}, guided);
|
89
104
|
}
|
90
|
-
const useNxCloud = options.nxCloud ??
|
91
|
-
(options.interactive ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)() : false);
|
92
105
|
const repoRoot = process.cwd();
|
93
106
|
(0, utils_1.createNxJsonFile)(repoRoot, [], [], {});
|
94
107
|
(0, utils_1.updateGitIgnore)(repoRoot);
|
95
108
|
const nxJson = (0, nx_json_1.readNxJson)(repoRoot);
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
109
|
+
if (guided) {
|
110
|
+
output_1.output.log({ title: '🧐 Checking dependencies' });
|
111
|
+
let plugins;
|
112
|
+
let updatePackageScripts;
|
113
|
+
if (_isCRA) {
|
114
|
+
plugins = ['@nx/vite'];
|
115
|
+
updatePackageScripts = true;
|
116
|
+
}
|
117
|
+
else {
|
118
|
+
const { plugins: _plugins, updatePackageScripts: _updatePackageScripts } = await detectPlugins(nxJson, options.interactive);
|
119
|
+
plugins = _plugins;
|
120
|
+
updatePackageScripts = _updatePackageScripts;
|
121
|
+
}
|
122
|
+
output_1.output.log({ title: '📦 Installing Nx' });
|
123
|
+
(0, configure_plugins_1.installPluginPackages)(repoRoot, pmc, plugins);
|
124
|
+
await (0, configure_plugins_1.configurePlugins)(plugins, updatePackageScripts, pmc, repoRoot, options.verbose);
|
102
125
|
}
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
126
|
+
let useNxCloud = options.nxCloud;
|
127
|
+
if (useNxCloud === undefined) {
|
128
|
+
output_1.output.log({ title: '🛠️ Setting up Self-Healing CI and Remote Caching' });
|
129
|
+
useNxCloud = options.interactive
|
130
|
+
? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)()
|
131
|
+
: false;
|
107
132
|
}
|
108
|
-
output_1.output.log({ title: '📦 Installing Nx' });
|
109
|
-
(0, configure_plugins_1.installPluginPackages)(repoRoot, pmc, plugins);
|
110
|
-
await (0, configure_plugins_1.configurePlugins)(plugins, updatePackageScripts, pmc, repoRoot, options.verbose);
|
111
133
|
if (useNxCloud) {
|
112
|
-
output_1.output.log({ title: '🛠️ Setting up Nx Cloud' });
|
113
134
|
await (0, utils_1.initCloud)('nx-init');
|
114
135
|
}
|
115
136
|
(0, utils_1.printFinalMessage)({
|
137
|
+
learnMoreLink: _isMonorepo
|
138
|
+
? 'https://nx.dev/recipes/adopting-nx/adding-to-monorepo'
|
139
|
+
: 'https://nx.dev/getting-started/adding-to-existing',
|
116
140
|
appendLines: _isMonorepo
|
117
141
|
? [
|
118
142
|
`- Learn how Nx helps manage your TypeScript monorepo at https://nx.dev/features/maintain-ts-monorepos.`,
|
119
143
|
]
|
120
|
-
: [
|
121
|
-
`- Learn how Nx works with any type of project at https://nx.dev/recipes/adopting-nx/adding-to-existing-project.`,
|
122
|
-
],
|
144
|
+
: [],
|
123
145
|
});
|
124
146
|
}
|
125
147
|
const npmPackageToPluginMap = {
|
@@ -5,6 +5,7 @@ exports.createAPI = createAPI;
|
|
5
5
|
const chalk = require("chalk");
|
6
6
|
const enquirer_1 = require("enquirer");
|
7
7
|
const node_fs_1 = require("node:fs");
|
8
|
+
const semver_1 = require("semver");
|
8
9
|
const tmp_1 = require("tmp");
|
9
10
|
const nx_json_1 = require("../../config/nx-json");
|
10
11
|
const tree_1 = require("../../generators/tree");
|
@@ -120,6 +121,16 @@ function createAPI(overrideReleaseConfig) {
|
|
120
121
|
const to = args.to || 'HEAD';
|
121
122
|
const toSHA = await (0, git_1.getCommitHash)(to);
|
122
123
|
const headSHA = to === 'HEAD' ? toSHA : await (0, git_1.getCommitHash)('HEAD');
|
124
|
+
/**
|
125
|
+
* Extract the preid from the workspace version and the project versions
|
126
|
+
*/
|
127
|
+
const workspacePreid = workspaceChangelogVersion
|
128
|
+
? extractPreid(workspaceChangelogVersion)
|
129
|
+
: undefined;
|
130
|
+
const projectsPreid = Object.fromEntries(Object.entries(projectsVersionData).map(([projectName, v]) => [
|
131
|
+
projectName,
|
132
|
+
v.newVersion ? extractPreid(v.newVersion) : undefined,
|
133
|
+
]));
|
123
134
|
/**
|
124
135
|
* Protect the user against attempting to create a new commit when recreating an old release changelog,
|
125
136
|
* this seems like it would always be unintentional.
|
@@ -191,7 +202,13 @@ function createAPI(overrideReleaseConfig) {
|
|
191
202
|
}
|
192
203
|
else {
|
193
204
|
let workspaceChangelogFromRef = args.from ||
|
194
|
-
(await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern, {},
|
205
|
+
(await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern, {}, {
|
206
|
+
checkAllBranchesWhen: nxReleaseConfig.releaseTagPatternCheckAllBranchesWhen,
|
207
|
+
preid: workspacePreid ??
|
208
|
+
projectsPreid?.[Object.keys(projectsPreid)[0]],
|
209
|
+
releaseTagPatternRequireSemver: nxReleaseConfig.releaseTagPatternRequireSemver,
|
210
|
+
releaseTagPatternStrictPreid: nxReleaseConfig.releaseTagPatternStrictPreid,
|
211
|
+
}))?.tag;
|
195
212
|
if (!workspaceChangelogFromRef) {
|
196
213
|
if (useAutomaticFromRef) {
|
197
214
|
workspaceChangelogFromRef = await (0, git_1.getFirstGitCommit)();
|
@@ -326,7 +343,12 @@ function createAPI(overrideReleaseConfig) {
|
|
326
343
|
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {
|
327
344
|
projectName: project.name,
|
328
345
|
releaseGroupName: releaseGroup.name,
|
329
|
-
},
|
346
|
+
}, {
|
347
|
+
checkAllBranchesWhen: releaseGroup.releaseTagPatternCheckAllBranchesWhen,
|
348
|
+
preid: projectsPreid[project.name],
|
349
|
+
releaseTagPatternRequireSemver: releaseGroup.releaseTagPatternRequireSemver,
|
350
|
+
releaseTagPatternStrictPreid: releaseGroup.releaseTagPatternStrictPreid,
|
351
|
+
}))?.tag;
|
330
352
|
if (!fromRef && useAutomaticFromRef) {
|
331
353
|
const firstCommit = await (0, git_1.getFirstGitCommit)();
|
332
354
|
commits = await filterProjectCommits({
|
@@ -436,7 +458,13 @@ function createAPI(overrideReleaseConfig) {
|
|
436
458
|
}
|
437
459
|
else {
|
438
460
|
let fromRef = args.from ||
|
439
|
-
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {},
|
461
|
+
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {}, {
|
462
|
+
checkAllBranchesWhen: releaseGroup.releaseTagPatternCheckAllBranchesWhen,
|
463
|
+
preid: workspacePreid ??
|
464
|
+
projectsPreid?.[Object.keys(projectsPreid)[0]],
|
465
|
+
releaseTagPatternRequireSemver: releaseGroup.releaseTagPatternRequireSemver,
|
466
|
+
releaseTagPatternStrictPreid: releaseGroup.releaseTagPatternStrictPreid,
|
467
|
+
}))?.tag;
|
440
468
|
if (!fromRef) {
|
441
469
|
if (useAutomaticFromRef) {
|
442
470
|
fromRef = await (0, git_1.getFirstGitCommit)();
|
@@ -967,3 +995,19 @@ function versionPlanSemverReleaseTypeToChangelogType(bump) {
|
|
967
995
|
throw new Error(`Invalid semver bump type: ${bump}`);
|
968
996
|
}
|
969
997
|
}
|
998
|
+
function extractPreid(version) {
|
999
|
+
if (!(0, shared_1.isPrerelease)(version)) {
|
1000
|
+
return undefined;
|
1001
|
+
}
|
1002
|
+
const preid = (0, semver_1.prerelease)(version)?.[0];
|
1003
|
+
if (typeof preid === 'string') {
|
1004
|
+
if (preid.trim() === '') {
|
1005
|
+
return undefined;
|
1006
|
+
}
|
1007
|
+
return preid;
|
1008
|
+
}
|
1009
|
+
if (typeof preid === 'number') {
|
1010
|
+
return preid.toString();
|
1011
|
+
}
|
1012
|
+
return undefined;
|
1013
|
+
}
|
@@ -114,11 +114,15 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
114
114
|
};
|
115
115
|
const defaultFixedReleaseTagPattern = 'v{version}';
|
116
116
|
/**
|
117
|
-
* TODO(
|
117
|
+
* TODO(v22): in v22, make it so that this pattern is used by default when any custom groups are used
|
118
118
|
*/
|
119
119
|
const defaultFixedGroupReleaseTagPattern = '{releaseGroupName}-v{version}';
|
120
120
|
const defaultIndependentReleaseTagPattern = '{projectName}@{version}';
|
121
121
|
const defaultReleaseTagPatternRequireSemver = true;
|
122
|
+
/**
|
123
|
+
* TODO(v22): in v22, set this to true by default
|
124
|
+
*/
|
125
|
+
const defaultReleaseTagPatternStrictPreid = false;
|
122
126
|
const workspaceProjectsRelationship = userConfig.projectsRelationship || 'fixed';
|
123
127
|
const defaultGeneratorOptions = {};
|
124
128
|
if (userConfig.version?.conventionalCommits) {
|
@@ -203,6 +207,8 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
203
207
|
releaseTagPatternCheckAllBranchesWhen: userConfig.releaseTagPatternCheckAllBranchesWhen ?? undefined,
|
204
208
|
releaseTagPatternRequireSemver: userConfig.releaseTagPatternRequireSemver ??
|
205
209
|
defaultReleaseTagPatternRequireSemver,
|
210
|
+
releaseTagPatternStrictPreid: userConfig.releaseTagPatternStrictPreid ??
|
211
|
+
defaultReleaseTagPatternStrictPreid,
|
206
212
|
conventionalCommits: conventional_commits_1.DEFAULT_CONVENTIONAL_COMMITS_CONFIG,
|
207
213
|
versionPlans: (userConfig.versionPlans ||
|
208
214
|
false),
|
@@ -210,6 +216,8 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
210
216
|
const groupProjectsRelationship = userConfig.projectsRelationship || WORKSPACE_DEFAULTS.projectsRelationship;
|
211
217
|
const groupReleaseTagPatternRequireSemver = userConfig.releaseTagPatternRequireSemver ??
|
212
218
|
WORKSPACE_DEFAULTS.releaseTagPatternRequireSemver;
|
219
|
+
const groupReleaseTagPatternStrictPreid = userConfig.releaseTagPatternStrictPreid ??
|
220
|
+
defaultReleaseTagPatternStrictPreid;
|
213
221
|
const GROUP_DEFAULTS = {
|
214
222
|
projectsRelationship: groupProjectsRelationship,
|
215
223
|
version: USE_LEGACY_VERSIONING
|
@@ -244,6 +252,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
244
252
|
: WORKSPACE_DEFAULTS.releaseTagPattern,
|
245
253
|
releaseTagPatternCheckAllBranchesWhen: userConfig.releaseTagPatternCheckAllBranchesWhen ?? undefined,
|
246
254
|
releaseTagPatternRequireSemver: groupReleaseTagPatternRequireSemver,
|
255
|
+
releaseTagPatternStrictPreid: groupReleaseTagPatternStrictPreid,
|
247
256
|
versionPlans: false,
|
248
257
|
};
|
249
258
|
/**
|
@@ -429,6 +438,9 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
429
438
|
releaseTagPatternRequireSemver: releaseGroup.releaseTagPatternRequireSemver ??
|
430
439
|
userConfig.releaseTagPatternRequireSemver ??
|
431
440
|
defaultReleaseTagPatternRequireSemver,
|
441
|
+
releaseTagPatternStrictPreid: releaseGroup.releaseTagPatternStrictPreid ??
|
442
|
+
userConfig.releaseTagPatternStrictPreid ??
|
443
|
+
defaultReleaseTagPatternStrictPreid,
|
432
444
|
versionPlans: releaseGroup.versionPlans ?? rootVersionPlansConfig,
|
433
445
|
};
|
434
446
|
const finalReleaseGroup = deepMergeDefaults([groupDefaults], {
|
@@ -503,6 +515,7 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
503
515
|
releaseTagPattern: WORKSPACE_DEFAULTS.releaseTagPattern,
|
504
516
|
releaseTagPatternCheckAllBranchesWhen: WORKSPACE_DEFAULTS.releaseTagPatternCheckAllBranchesWhen,
|
505
517
|
releaseTagPatternRequireSemver: WORKSPACE_DEFAULTS.releaseTagPatternRequireSemver,
|
518
|
+
releaseTagPatternStrictPreid: WORKSPACE_DEFAULTS.releaseTagPatternStrictPreid,
|
506
519
|
git: rootGitConfig,
|
507
520
|
version: rootVersionConfig,
|
508
521
|
changelog: rootChangelogConfig,
|
@@ -12,6 +12,10 @@ export interface Reference {
|
|
12
12
|
type: 'hash' | 'issue' | 'pull-request';
|
13
13
|
value: string;
|
14
14
|
}
|
15
|
+
export interface GitTagAndVersion {
|
16
|
+
tag: string;
|
17
|
+
extractedVersion: string;
|
18
|
+
}
|
15
19
|
export interface GitCommit extends RawGitCommit {
|
16
20
|
description: string;
|
17
21
|
type: string;
|
@@ -22,10 +26,37 @@ export interface GitCommit extends RawGitCommit {
|
|
22
26
|
affectedFiles: string[];
|
23
27
|
revertedHashes: string[];
|
24
28
|
}
|
25
|
-
export
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
export interface GetLatestGitTagForPatternOptions {
|
30
|
+
checkAllBranchesWhen?: boolean | string[];
|
31
|
+
preid?: string;
|
32
|
+
releaseTagPatternRequireSemver: boolean;
|
33
|
+
releaseTagPatternStrictPreid: boolean;
|
34
|
+
}
|
35
|
+
/**
|
36
|
+
* Extract the tag and version from a tag string
|
37
|
+
*
|
38
|
+
* @param tag - The tag string to extract the tag and version from
|
39
|
+
* @param tagRegexp - The regex to use to extract the tag and version from the tag string
|
40
|
+
*
|
41
|
+
* @returns The tag and version
|
42
|
+
*/
|
43
|
+
export declare function extractTagAndVersion(tag: string, tagRegexp: string, options: GetLatestGitTagForPatternOptions): GitTagAndVersion;
|
44
|
+
/**
|
45
|
+
* Get the latest git tag for the configured release tag pattern.
|
46
|
+
*
|
47
|
+
* This function will:
|
48
|
+
* - Get all tags from the git repo, sorted by version
|
49
|
+
* - Filter the tags into a list with SEMVER-compliant tags, matching the release tag pattern
|
50
|
+
* - If a preid is provided, prioritise tags for that preid, then semver tags without a preid
|
51
|
+
* - If no preid is provided, search only for stable semver tags (i.e. no pre-release or build metadata)
|
52
|
+
*
|
53
|
+
* @param releaseTagPattern - The pattern to filter the tags list by
|
54
|
+
* @param additionalInterpolationData - Additional data used when interpolating the release tag pattern
|
55
|
+
* @param options - The options to use when getting the latest git tag for the pattern
|
56
|
+
*
|
57
|
+
* @returns The tag and version
|
58
|
+
*/
|
59
|
+
export declare function getLatestGitTagForPattern(releaseTagPattern: string, additionalInterpolationData: {}, options: GetLatestGitTagForPatternOptions): Promise<GitTagAndVersion | null>;
|
29
60
|
export declare function getGitDiff(from: string | undefined, to?: string): Promise<RawGitCommit[]>;
|
30
61
|
export declare function gitAdd({ changedFiles, deletedFiles, dryRun, verbose, logFn, cwd, }: {
|
31
62
|
changedFiles?: string[];
|
@@ -1,5 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.extractTagAndVersion = extractTagAndVersion;
|
3
4
|
exports.getLatestGitTagForPattern = getLatestGitTagForPattern;
|
4
5
|
exports.getGitDiff = getGitDiff;
|
5
6
|
exports.gitAdd = gitAdd;
|
@@ -21,12 +22,50 @@ const minimatch_1 = require("minimatch");
|
|
21
22
|
const utils_1 = require("../../../tasks-runner/utils");
|
22
23
|
const workspace_root_1 = require("../../../utils/workspace-root");
|
23
24
|
const exec_command_1 = require("./exec-command");
|
25
|
+
const shared_1 = require("./shared");
|
24
26
|
function escapeRegExp(string) {
|
25
27
|
return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
|
26
28
|
}
|
27
29
|
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
|
28
30
|
const SEMVER_REGEX = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/g;
|
29
|
-
|
31
|
+
/**
|
32
|
+
* Extract the tag and version from a tag string
|
33
|
+
*
|
34
|
+
* @param tag - The tag string to extract the tag and version from
|
35
|
+
* @param tagRegexp - The regex to use to extract the tag and version from the tag string
|
36
|
+
*
|
37
|
+
* @returns The tag and version
|
38
|
+
*/
|
39
|
+
function extractTagAndVersion(tag, tagRegexp, options) {
|
40
|
+
const { releaseTagPatternRequireSemver } = options;
|
41
|
+
const [latestMatchingTag, ...rest] = tag.match(tagRegexp);
|
42
|
+
let version = releaseTagPatternRequireSemver
|
43
|
+
? rest.filter((r) => {
|
44
|
+
return r.match(SEMVER_REGEX);
|
45
|
+
})[0]
|
46
|
+
: rest[0];
|
47
|
+
return {
|
48
|
+
tag: latestMatchingTag,
|
49
|
+
extractedVersion: version ?? null,
|
50
|
+
};
|
51
|
+
}
|
52
|
+
/**
|
53
|
+
* Get the latest git tag for the configured release tag pattern.
|
54
|
+
*
|
55
|
+
* This function will:
|
56
|
+
* - Get all tags from the git repo, sorted by version
|
57
|
+
* - Filter the tags into a list with SEMVER-compliant tags, matching the release tag pattern
|
58
|
+
* - If a preid is provided, prioritise tags for that preid, then semver tags without a preid
|
59
|
+
* - If no preid is provided, search only for stable semver tags (i.e. no pre-release or build metadata)
|
60
|
+
*
|
61
|
+
* @param releaseTagPattern - The pattern to filter the tags list by
|
62
|
+
* @param additionalInterpolationData - Additional data used when interpolating the release tag pattern
|
63
|
+
* @param options - The options to use when getting the latest git tag for the pattern
|
64
|
+
*
|
65
|
+
* @returns The tag and version
|
66
|
+
*/
|
67
|
+
async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolationData = {}, options) {
|
68
|
+
const { checkAllBranchesWhen, releaseTagPatternRequireSemver, releaseTagPatternStrictPreid, preid, } = options;
|
30
69
|
/**
|
31
70
|
* By default, we will try and resolve the latest match for the releaseTagPattern from the current branch,
|
32
71
|
* falling back to all branches if no match is found on the current branch.
|
@@ -118,16 +157,37 @@ async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolat
|
|
118
157
|
if (!matchingTags.length) {
|
119
158
|
return null;
|
120
159
|
}
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
160
|
+
if (!releaseTagPatternStrictPreid) {
|
161
|
+
// If not using strict preid, we can just return the first matching tag
|
162
|
+
return extractTagAndVersion(matchingTags[0], tagRegexp, options);
|
163
|
+
}
|
164
|
+
if (preid && preid.length > 0) {
|
165
|
+
// When a preid is provided, first try to find a tag for it
|
166
|
+
const preidReleaseTags = matchingTags.filter((tag) => {
|
167
|
+
const match = tag.match(tagRegexp);
|
168
|
+
if (!match)
|
169
|
+
return false;
|
170
|
+
const version = match.find((part) => part.match(SEMVER_REGEX));
|
171
|
+
return version && version.includes(`-${preid}.`);
|
172
|
+
});
|
173
|
+
if (preidReleaseTags.length > 0) {
|
174
|
+
return extractTagAndVersion(preidReleaseTags[0], tagRegexp, options);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
// Then try to find the latest stable release tag
|
178
|
+
const stableReleaseTags = matchingTags.filter((tag) => {
|
179
|
+
const matches = tag.match(tagRegexp);
|
180
|
+
if (!matches)
|
181
|
+
return false;
|
182
|
+
const [, version] = matches;
|
183
|
+
return version && !(0, shared_1.isPrerelease)(version);
|
184
|
+
});
|
185
|
+
// If there are stable release tags, use the latest one
|
186
|
+
if (stableReleaseTags.length > 0) {
|
187
|
+
return extractTagAndVersion(stableReleaseTags[0], tagRegexp, options);
|
188
|
+
}
|
189
|
+
// Otherwise return null
|
190
|
+
return null;
|
131
191
|
}
|
132
192
|
catch {
|
133
193
|
return null;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.ReleaseVersion = exports.noDiffInChangelogMessage = void 0;
|
4
|
+
exports.isPrerelease = isPrerelease;
|
4
5
|
exports.commitChanges = commitChanges;
|
5
6
|
exports.createCommitMessageValues = createCommitMessageValues;
|
6
7
|
exports.createGitTagValues = createGitTagValues;
|