nx 17.2.0-beta.1 → 17.2.0-beta.10
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 +0 -16
- package/package.json +12 -13
- package/src/command-line/affected/print-affected.js +10 -1
- package/src/command-line/graph/graph.js +2 -2
- package/src/command-line/init/implementation/add-nx-to-nest.js +1 -1
- package/src/command-line/release/changelog.d.ts +7 -1
- package/src/command-line/release/changelog.js +153 -86
- package/src/command-line/release/command-object.d.ts +9 -4
- package/src/command-line/release/command-object.js +14 -3
- package/src/command-line/release/config/config.d.ts +10 -2
- package/src/command-line/release/config/config.js +24 -3
- package/src/command-line/release/index.d.ts +12 -0
- package/src/command-line/release/index.js +18 -0
- package/src/command-line/release/publish.d.ts +7 -3
- package/src/command-line/release/publish.js +23 -8
- package/src/command-line/release/utils/git.js +1 -1
- package/src/command-line/release/utils/resolve-semver-specifier.js +10 -3
- package/src/command-line/release/version.d.ts +22 -1
- package/src/command-line/release/version.js +46 -7
- package/src/command-line/yargs-utils/shared-options.d.ts +3 -1
- package/src/command-line/yargs-utils/shared-options.js +14 -8
- package/src/config/nx-json.d.ts +22 -4
- package/src/daemon/server/handle-hash-tasks.js +2 -2
- package/src/daemon/server/project-graph-incremental-recomputation.d.ts +4 -0
- package/src/daemon/server/project-graph-incremental-recomputation.js +23 -18
- package/src/executors/run-commands/run-commands.impl.d.ts +1 -0
- package/src/executors/run-commands/run-commands.impl.js +9 -8
- package/src/executors/run-commands/schema.json +7 -0
- package/src/executors/utils/convert-nx-executor.js +1 -1
- package/src/hasher/hash-task.js +6 -0
- package/src/hasher/native-task-hasher-impl.d.ts +19 -0
- package/src/hasher/native-task-hasher-impl.js +35 -0
- package/src/hasher/node-task-hasher-impl.d.ts +49 -0
- package/src/hasher/node-task-hasher-impl.js +431 -0
- package/src/hasher/task-hasher.d.ts +29 -17
- package/src/hasher/task-hasher.js +28 -426
- package/src/native/index.d.ts +42 -6
- package/src/native/index.js +3 -2
- package/src/native/transform-objects.js +2 -0
- package/src/plugins/js/package-json/create-package-json.js +1 -1
- package/src/project-graph/build-project-graph.d.ts +3 -1
- package/src/project-graph/build-project-graph.js +5 -1
- package/src/project-graph/file-map-utils.d.ts +9 -5
- package/src/project-graph/file-map-utils.js +16 -63
- package/src/project-graph/project-graph.js +3 -2
- package/src/project-graph/utils/build-all-workspace-files.d.ts +2 -0
- package/src/project-graph/utils/build-all-workspace-files.js +15 -0
- package/src/project-graph/utils/retrieve-workspace-files.d.ts +13 -22
- package/src/project-graph/utils/retrieve-workspace-files.js +17 -55
- package/src/tasks-runner/run-command.js +2 -6
- package/src/utils/nx-plugin.js +12 -2
- package/src/utils/workspace-context.d.ts +3 -2
- package/src/utils/workspace-context.js +7 -8
package/bin/nx.js
CHANGED
|
@@ -38,22 +38,6 @@ function main() {
|
|
|
38
38
|
require('nx/src/command-line/nx-commands').commandsObject.argv;
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
|
-
// v8-compile-cache doesn't support ESM. Attempting to import ESM
|
|
42
|
-
// with it enabled results in an error that reads "Invalid host options".
|
|
43
|
-
//
|
|
44
|
-
// Angular CLI, and prettier both use ESM so we need to disable it in these cases.
|
|
45
|
-
if (workspace &&
|
|
46
|
-
workspace.type === 'nx' &&
|
|
47
|
-
![
|
|
48
|
-
'format',
|
|
49
|
-
'format:check',
|
|
50
|
-
'format:write',
|
|
51
|
-
'g',
|
|
52
|
-
'generate',
|
|
53
|
-
'release',
|
|
54
|
-
].some((cmd) => process.argv[2] === cmd)) {
|
|
55
|
-
require('v8-compile-cache');
|
|
56
|
-
}
|
|
57
41
|
if (!client_1.daemonClient.enabled() && workspace !== null) {
|
|
58
42
|
(0, workspace_context_1.setupWorkspaceContext)(workspace.dir);
|
|
59
43
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nx",
|
|
3
|
-
"version": "17.2.0-beta.
|
|
3
|
+
"version": "17.2.0-beta.10",
|
|
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": {
|
|
@@ -63,11 +63,10 @@
|
|
|
63
63
|
"tmp": "~0.2.1",
|
|
64
64
|
"tsconfig-paths": "^4.1.2",
|
|
65
65
|
"tslib": "^2.3.0",
|
|
66
|
-
"v8-compile-cache": "2.3.0",
|
|
67
66
|
"yargs": "^17.6.2",
|
|
68
67
|
"yargs-parser": "21.1.1",
|
|
69
68
|
"node-machine-id": "1.1.12",
|
|
70
|
-
"@nrwl/tao": "17.2.0-beta.
|
|
69
|
+
"@nrwl/tao": "17.2.0-beta.10"
|
|
71
70
|
},
|
|
72
71
|
"peerDependencies": {
|
|
73
72
|
"@swc-node/register": "^1.6.7",
|
|
@@ -82,16 +81,16 @@
|
|
|
82
81
|
}
|
|
83
82
|
},
|
|
84
83
|
"optionalDependencies": {
|
|
85
|
-
"@nx/nx-darwin-x64": "17.2.0-beta.
|
|
86
|
-
"@nx/nx-darwin-arm64": "17.2.0-beta.
|
|
87
|
-
"@nx/nx-linux-x64-gnu": "17.2.0-beta.
|
|
88
|
-
"@nx/nx-linux-x64-musl": "17.2.0-beta.
|
|
89
|
-
"@nx/nx-win32-x64-msvc": "17.2.0-beta.
|
|
90
|
-
"@nx/nx-linux-arm64-gnu": "17.2.0-beta.
|
|
91
|
-
"@nx/nx-linux-arm64-musl": "17.2.0-beta.
|
|
92
|
-
"@nx/nx-linux-arm-gnueabihf": "17.2.0-beta.
|
|
93
|
-
"@nx/nx-win32-arm64-msvc": "17.2.0-beta.
|
|
94
|
-
"@nx/nx-freebsd-x64": "17.2.0-beta.
|
|
84
|
+
"@nx/nx-darwin-x64": "17.2.0-beta.10",
|
|
85
|
+
"@nx/nx-darwin-arm64": "17.2.0-beta.10",
|
|
86
|
+
"@nx/nx-linux-x64-gnu": "17.2.0-beta.10",
|
|
87
|
+
"@nx/nx-linux-x64-musl": "17.2.0-beta.10",
|
|
88
|
+
"@nx/nx-win32-x64-msvc": "17.2.0-beta.10",
|
|
89
|
+
"@nx/nx-linux-arm64-gnu": "17.2.0-beta.10",
|
|
90
|
+
"@nx/nx-linux-arm64-musl": "17.2.0-beta.10",
|
|
91
|
+
"@nx/nx-linux-arm-gnueabihf": "17.2.0-beta.10",
|
|
92
|
+
"@nx/nx-win32-arm64-msvc": "17.2.0-beta.10",
|
|
93
|
+
"@nx/nx-freebsd-x64": "17.2.0-beta.10"
|
|
95
94
|
},
|
|
96
95
|
"nx-migrations": {
|
|
97
96
|
"migrations": "./migrations.json",
|
|
@@ -9,6 +9,8 @@ const package_manager_1 = require("../../utils/package-manager");
|
|
|
9
9
|
const command_object_1 = require("./command-object");
|
|
10
10
|
const logger_1 = require("../../utils/logger");
|
|
11
11
|
const task_env_1 = require("../../tasks-runner/task-env");
|
|
12
|
+
const build_project_graph_1 = require("../../project-graph/build-project-graph");
|
|
13
|
+
const client_1 = require("../../daemon/client/client");
|
|
12
14
|
/**
|
|
13
15
|
* @deprecated Use showProjectsHandler, generateGraph, or affected (without the print-affected mode) instead.
|
|
14
16
|
*/
|
|
@@ -35,7 +37,14 @@ exports.printAffected = printAffected;
|
|
|
35
37
|
async function createTasks(affectedProjectsWithTargetAndConfig, projectGraph, nxArgs, nxJson, overrides) {
|
|
36
38
|
const defaultDependencyConfigs = (0, create_task_graph_1.mapTargetDefaultsToDependencies)(nxJson.targetDefaults);
|
|
37
39
|
const taskGraph = (0, create_task_graph_1.createTaskGraph)(projectGraph, defaultDependencyConfigs, affectedProjectsWithTargetAndConfig.map((p) => p.name), nxArgs.targets, nxArgs.configuration, overrides);
|
|
38
|
-
|
|
40
|
+
let hasher;
|
|
41
|
+
if (client_1.daemonClient.enabled()) {
|
|
42
|
+
hasher = new task_hasher_1.DaemonBasedTaskHasher(client_1.daemonClient, {});
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const { fileMap, allWorkspaceFiles, rustReferences } = (0, build_project_graph_1.getFileMap)();
|
|
46
|
+
hasher = new task_hasher_1.InProcessTaskHasher(fileMap?.projectFileMap, allWorkspaceFiles, projectGraph, nxJson, rustReferences, {});
|
|
47
|
+
}
|
|
39
48
|
const execCommand = (0, package_manager_1.getPackageManagerCommand)().exec;
|
|
40
49
|
const tasks = Object.values(taskGraph.tasks);
|
|
41
50
|
await Promise.all(tasks.map((t) => (0, hash_task_1.hashTask)(hasher, projectGraph, taskGraph, t,
|
|
@@ -15,7 +15,6 @@ const fileutils_1 = require("../../utils/fileutils");
|
|
|
15
15
|
const output_1 = require("../../utils/output");
|
|
16
16
|
const workspace_root_1 = require("../../utils/workspace-root");
|
|
17
17
|
const client_1 = require("../../daemon/client/client");
|
|
18
|
-
const task_hasher_1 = require("../../hasher/task-hasher");
|
|
19
18
|
const typescript_1 = require("../../plugins/js/utils/typescript");
|
|
20
19
|
const operators_1 = require("../../project-graph/operators");
|
|
21
20
|
const project_graph_1 = require("../../project-graph/project-graph");
|
|
@@ -26,6 +25,7 @@ const native_1 = require("../../native");
|
|
|
26
25
|
const transform_objects_1 = require("../../native/transform-objects");
|
|
27
26
|
const affected_1 = require("../affected/affected");
|
|
28
27
|
const nx_deps_cache_1 = require("../../project-graph/nx-deps-cache");
|
|
28
|
+
const task_hasher_1 = require("../../hasher/task-hasher");
|
|
29
29
|
// maps file extention to MIME types
|
|
30
30
|
const mimeType = {
|
|
31
31
|
'.ico': 'image/x-icon',
|
|
@@ -435,7 +435,7 @@ async function createTaskGraphClientResponse(pruneExternal = false) {
|
|
|
435
435
|
perf_hooks_1.performance.mark('task graph generation:start');
|
|
436
436
|
const taskGraphs = getAllTaskGraphsForWorkspace(nxJson, graph);
|
|
437
437
|
perf_hooks_1.performance.mark('task graph generation:end');
|
|
438
|
-
const planner = new native_1.HashPlanner(
|
|
438
|
+
const planner = new native_1.HashPlanner(nxJson, (0, native_1.transferProjectGraph)((0, transform_objects_1.transformProjectGraphForRust)(graph)));
|
|
439
439
|
perf_hooks_1.performance.mark('task hash plan generation:start');
|
|
440
440
|
const plans = {};
|
|
441
441
|
for (const individualTaskGraph of Object.values(taskGraphs.taskGraphs)) {
|
|
@@ -173,7 +173,7 @@ function createProjectJson(repoRoot, packageJson, nestCLIOptions) {
|
|
|
173
173
|
executor: '@nx/eslint:lint',
|
|
174
174
|
outputs: ['{options.outputFile}'],
|
|
175
175
|
options: {
|
|
176
|
-
lintFilePatterns: ['src
|
|
176
|
+
lintFilePatterns: ['./src', './test'],
|
|
177
177
|
},
|
|
178
178
|
};
|
|
179
179
|
// test and e2e
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import { ChangelogOptions } from './command-object';
|
|
2
|
-
export declare
|
|
2
|
+
export declare const releaseChangelogCLIHandler: (args: ChangelogOptions) => Promise<any>;
|
|
3
|
+
/**
|
|
4
|
+
* NOTE: This function is also exported for programmatic usage and forms part of the public API
|
|
5
|
+
* of Nx. We intentionally do not wrap the implementation with handleErrors because users need
|
|
6
|
+
* to have control over their own error handling when using the API.
|
|
7
|
+
*/
|
|
8
|
+
export declare function releaseChangelog(args: ChangelogOptions): Promise<number>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.releaseChangelog = exports.releaseChangelogCLIHandler = void 0;
|
|
4
4
|
const chalk = require("chalk");
|
|
5
5
|
const node_fs_1 = require("node:fs");
|
|
6
6
|
const semver_1 = require("semver");
|
|
@@ -24,103 +24,158 @@ const launch_editor_1 = require("./utils/launch-editor");
|
|
|
24
24
|
const markdown_1 = require("./utils/markdown");
|
|
25
25
|
const print_changes_1 = require("./utils/print-changes");
|
|
26
26
|
const shared_1 = require("./utils/shared");
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
const releaseChangelogCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => releaseChangelog(args));
|
|
28
|
+
exports.releaseChangelogCLIHandler = releaseChangelogCLIHandler;
|
|
29
|
+
/**
|
|
30
|
+
* NOTE: This function is also exported for programmatic usage and forms part of the public API
|
|
31
|
+
* of Nx. We intentionally do not wrap the implementation with handleErrors because users need
|
|
32
|
+
* to have control over their own error handling when using the API.
|
|
33
|
+
*/
|
|
34
|
+
async function releaseChangelog(args) {
|
|
35
|
+
const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
|
|
36
|
+
const nxJson = (0, nx_json_1.readNxJson)();
|
|
37
|
+
if (args.verbose) {
|
|
38
|
+
process.env.NX_VERBOSE_LOGGING = 'true';
|
|
39
|
+
}
|
|
40
|
+
// Apply default configuration to any optional user configuration
|
|
41
|
+
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, nxJson.release);
|
|
42
|
+
if (configError) {
|
|
43
|
+
return await (0, config_1.handleNxReleaseConfigError)(configError);
|
|
44
|
+
}
|
|
45
|
+
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
|
46
|
+
if (filterError) {
|
|
47
|
+
output_1.output.error(filterError);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* For determining the versions to use within changelog files, there are a few different possibilities:
|
|
52
|
+
* - the user is using the nx CLI, and therefore passes a single --version argument which represents the version for any and all changelog
|
|
53
|
+
* files which will be generated (i.e. both the workspace changelog, and all project changelogs, depending on which of those has been enabled)
|
|
54
|
+
* - the user is using the nxReleaseChangelog API programmatically, and:
|
|
55
|
+
* - passes only a version property
|
|
56
|
+
* - this works in the same way as described above for the CLI
|
|
57
|
+
* - passes only a versionData object
|
|
58
|
+
* - this is a special case where the user is providing a version for each project, and therefore the version argument is not needed
|
|
59
|
+
* - NOTE: it is not possible to generate a workspace level changelog with only a versionData object, and this will produce an error
|
|
60
|
+
* - passes both a version and a versionData object
|
|
61
|
+
* - in this case, the version property will be used as the reference for the workspace changelog, and the versionData object will be used
|
|
62
|
+
* to generate project changelogs
|
|
63
|
+
*/
|
|
64
|
+
const { workspaceChangelogVersion, projectsVersionData } = resolveChangelogVersions(args, releaseGroups, releaseGroupToFilteredProjects);
|
|
65
|
+
const to = args.to || 'HEAD';
|
|
66
|
+
const toSHA = await (0, git_1.getCommitHash)(to);
|
|
67
|
+
const headSHA = to === 'HEAD' ? toSHA : await (0, git_1.getCommitHash)('HEAD');
|
|
68
|
+
/**
|
|
69
|
+
* Protect the user against attempting to create a new commit when recreating an old release changelog,
|
|
70
|
+
* this seems like it would always be unintentional.
|
|
71
|
+
*/
|
|
72
|
+
const autoCommitEnabled = args.gitCommit ?? nxReleaseConfig.changelog.git.commit;
|
|
73
|
+
if (autoCommitEnabled && headSHA !== toSHA) {
|
|
74
|
+
throw new Error(`You are attempting to recreate the changelog for an old release, but you have enabled auto-commit mode. Please disable auto-commit mode by updating your nx.json, or passing --git-commit=false`);
|
|
75
|
+
}
|
|
76
|
+
const fromRef = args.from ||
|
|
77
|
+
(await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern))?.tag;
|
|
78
|
+
if (!fromRef) {
|
|
79
|
+
throw new Error(`Unable to determine the previous git tag, please provide an explicit git reference using --from`);
|
|
80
|
+
}
|
|
81
|
+
// Make sure that the fromRef is actually resolvable
|
|
82
|
+
const fromSHA = await (0, git_1.getCommitHash)(fromRef);
|
|
83
|
+
const rawCommits = await (0, git_1.getGitDiff)(fromSHA, toSHA);
|
|
84
|
+
// Parse as conventional commits
|
|
85
|
+
const commits = (0, git_1.parseCommits)(rawCommits).filter((c) => {
|
|
86
|
+
const type = c.type;
|
|
87
|
+
// Always ignore non user-facing commits for now
|
|
88
|
+
// TODO: allow this filter to be configurable via config in a future release
|
|
89
|
+
if (type === 'feat' || type === 'fix' || type === 'perf') {
|
|
90
|
+
return true;
|
|
42
91
|
}
|
|
43
|
-
|
|
44
|
-
|
|
92
|
+
return false;
|
|
93
|
+
});
|
|
94
|
+
const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
|
|
95
|
+
const userCommitMessage = args.gitCommitMessage || nxReleaseConfig.changelog.git.commitMessage;
|
|
96
|
+
const commitMessageValues = (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, projectsVersionData, userCommitMessage);
|
|
97
|
+
// Resolve any git tags as early as possible so that we can hard error in case of any duplicates before reaching the actual git command
|
|
98
|
+
const gitTagValues = args.gitTag ?? nxReleaseConfig.changelog.git.tag
|
|
99
|
+
? (0, shared_1.createGitTagValues)(releaseGroups, releaseGroupToFilteredProjects, projectsVersionData)
|
|
100
|
+
: [];
|
|
101
|
+
(0, shared_1.handleDuplicateGitTags)(gitTagValues);
|
|
102
|
+
const postGitTasks = [];
|
|
103
|
+
await generateChangelogForWorkspace(tree, args, nxReleaseConfig, workspaceChangelogVersion, commits, postGitTasks);
|
|
104
|
+
if (args.projects?.length) {
|
|
45
105
|
/**
|
|
46
|
-
*
|
|
47
|
-
* this seems like it would always be unintentional.
|
|
106
|
+
* Run changelog generation for all remaining release groups and filtered projects within them
|
|
48
107
|
*/
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
|
54
|
-
if (filterError) {
|
|
55
|
-
output_1.output.error(filterError);
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
const fromRef = args.from ||
|
|
59
|
-
(await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern))?.tag;
|
|
60
|
-
if (!fromRef) {
|
|
61
|
-
throw new Error(`Unable to determine the previous git tag, please provide an explicit git reference using --from`);
|
|
108
|
+
for (const releaseGroup of releaseGroups) {
|
|
109
|
+
const projectNodes = Array.from(releaseGroupToFilteredProjects.get(releaseGroup)).map((name) => projectGraph.nodes[name]);
|
|
110
|
+
await generateChangelogForProjects(tree, args, commits, projectsVersionData, postGitTasks, releaseGroup, projectNodes);
|
|
62
111
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
112
|
+
return await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Run changelog generation for all remaining release groups
|
|
116
|
+
*/
|
|
117
|
+
for (const releaseGroup of releaseGroups) {
|
|
118
|
+
const projectNodes = releaseGroup.projects.map((name) => projectGraph.nodes[name]);
|
|
119
|
+
await generateChangelogForProjects(tree, args, commits, projectsVersionData, postGitTasks, releaseGroup, projectNodes);
|
|
120
|
+
}
|
|
121
|
+
return await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues);
|
|
122
|
+
}
|
|
123
|
+
exports.releaseChangelog = releaseChangelog;
|
|
124
|
+
function resolveChangelogVersions(args, releaseGroups, releaseGroupToFilteredProjects) {
|
|
125
|
+
if (!args.version && !args.versionData) {
|
|
126
|
+
throw new Error(`You must provide a version string and/or a versionData object.`);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* TODO: revaluate this assumption holistically in a dedicated PR when we add support for calver
|
|
130
|
+
* (e.g. the Release class also uses semver utils to check if prerelease).
|
|
131
|
+
*
|
|
132
|
+
* Right now, the given version must be valid semver in order to proceed
|
|
133
|
+
*/
|
|
134
|
+
if (args.version && !(0, semver_1.valid)(args.version)) {
|
|
135
|
+
throw new Error(`The given version "${args.version}" is not a valid semver version. Please provide your version in the format "1.0.0", "1.0.0-beta.1" etc`);
|
|
136
|
+
}
|
|
137
|
+
const versionData = releaseGroups.reduce((versionData, releaseGroup) => {
|
|
138
|
+
const releaseGroupProjectNames = Array.from(releaseGroupToFilteredProjects.get(releaseGroup));
|
|
139
|
+
for (const projectName of releaseGroupProjectNames) {
|
|
140
|
+
if (!args.versionData) {
|
|
81
141
|
versionData[projectName] = {
|
|
82
142
|
newVersion: args.version,
|
|
83
143
|
currentVersion: '',
|
|
84
|
-
dependentProjects: [], // not
|
|
144
|
+
dependentProjects: [], // not relevant within changelog/commit generation
|
|
85
145
|
};
|
|
146
|
+
continue;
|
|
86
147
|
}
|
|
87
|
-
return versionData;
|
|
88
|
-
}, {});
|
|
89
|
-
const userCommitMessage = args.gitCommitMessage || nxReleaseConfig.changelog.git.commitMessage;
|
|
90
|
-
const commitMessageValues = (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, userCommitMessage);
|
|
91
|
-
// Resolve any git tags as early as possible so that we can hard error in case of any duplicates before reaching the actual git command
|
|
92
|
-
const gitTagValues = args.gitTag ?? nxReleaseConfig.changelog.git.tag
|
|
93
|
-
? (0, shared_1.createGitTagValues)(releaseGroups, releaseGroupToFilteredProjects, versionData)
|
|
94
|
-
: [];
|
|
95
|
-
(0, shared_1.handleDuplicateGitTags)(gitTagValues);
|
|
96
|
-
const postGitTasks = [];
|
|
97
|
-
await generateChangelogForWorkspace(tree, args, nxReleaseConfig, commits, postGitTasks);
|
|
98
|
-
if (args.projects?.length) {
|
|
99
148
|
/**
|
|
100
|
-
*
|
|
149
|
+
* In the case where a versionData object was provided, we need to make sure all projects are present,
|
|
150
|
+
* otherwise it suggests a filtering mismatch between the version and changelog command invocations.
|
|
101
151
|
*/
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
await generateChangelogForProjects(tree, args, commits, postGitTasks, releaseGroup, projectNodes);
|
|
152
|
+
if (!args.versionData[projectName]) {
|
|
153
|
+
throw new Error(`The provided versionData object does not contain a version for project "${projectName}". This suggests a filtering mismatch between the version and changelog command invocations.`);
|
|
105
154
|
}
|
|
106
|
-
return await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues);
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Run changelog generation for all remaining release groups
|
|
110
|
-
*/
|
|
111
|
-
for (const releaseGroup of releaseGroups) {
|
|
112
|
-
const projectNodes = releaseGroup.projects.map((name) => projectGraph.nodes[name]);
|
|
113
|
-
await generateChangelogForProjects(tree, args, commits, postGitTasks, releaseGroup, projectNodes);
|
|
114
155
|
}
|
|
115
|
-
return
|
|
116
|
-
});
|
|
156
|
+
return versionData;
|
|
157
|
+
}, args.versionData || {});
|
|
158
|
+
return {
|
|
159
|
+
workspaceChangelogVersion: args.version,
|
|
160
|
+
projectsVersionData: versionData,
|
|
161
|
+
};
|
|
117
162
|
}
|
|
118
|
-
exports.changelogHandler = changelogHandler;
|
|
119
163
|
async function applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues) {
|
|
120
164
|
let latestCommit = toSHA;
|
|
165
|
+
const changes = tree.listChanges();
|
|
166
|
+
// This could happen we using conventional commits, for example
|
|
167
|
+
if (!changes.length) {
|
|
168
|
+
output_1.output.warn({
|
|
169
|
+
title: `No changes detected for changelogs`,
|
|
170
|
+
bodyLines: [
|
|
171
|
+
`No changes were detected for any changelog files, so no changelog entries will be generated.`,
|
|
172
|
+
],
|
|
173
|
+
});
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
121
176
|
// Generate a new commit for the changes, if configured to do so
|
|
122
177
|
if (args.gitCommit ?? nxReleaseConfig.changelog.git.commit) {
|
|
123
|
-
await (0, shared_1.commitChanges)(
|
|
178
|
+
await (0, shared_1.commitChanges)(changes.map((f) => f.path), !!args.dryRun, !!args.verbose, commitMessageValues, args.gitCommitArgs || nxReleaseConfig.changelog.git.commitArgs);
|
|
124
179
|
// Resolve the commit we just made
|
|
125
180
|
latestCommit = await (0, git_1.getCommitHash)('HEAD');
|
|
126
181
|
}
|
|
@@ -165,16 +220,22 @@ function resolveChangelogRenderer(changelogRendererPath) {
|
|
|
165
220
|
}
|
|
166
221
|
return changelogRenderer;
|
|
167
222
|
}
|
|
168
|
-
async function generateChangelogForWorkspace(tree, args, nxReleaseConfig, commits, postGitTasks) {
|
|
223
|
+
async function generateChangelogForWorkspace(tree, args, nxReleaseConfig, workspaceChangelogVersion, commits, postGitTasks) {
|
|
169
224
|
const config = nxReleaseConfig.changelog.workspaceChangelog;
|
|
170
225
|
// The entire feature is disabled at the workspace level, exit early
|
|
171
226
|
if (config === false) {
|
|
172
227
|
return;
|
|
173
228
|
}
|
|
229
|
+
// If explicitly null it must mean that no changes were detected (e.g. when using conventional commits), so do nothing
|
|
230
|
+
if (workspaceChangelogVersion === null) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!workspaceChangelogVersion) {
|
|
234
|
+
throw new Error(`Workspace changelog is enabled but no overall version was provided. Please provide an explicit version using --version`);
|
|
235
|
+
}
|
|
174
236
|
// Only trigger interactive mode for the workspace changelog if the user explicitly requested it via "all" or "workspace"
|
|
175
237
|
const interactive = args.interactive === 'all' || args.interactive === 'workspace';
|
|
176
238
|
const dryRun = !!args.dryRun;
|
|
177
|
-
const verbose = !!args.verbose;
|
|
178
239
|
const gitRemote = args.gitRemote;
|
|
179
240
|
const changelogRenderer = resolveChangelogRenderer(config.renderer);
|
|
180
241
|
let interpolatedTreePath = config.file || '';
|
|
@@ -186,7 +247,7 @@ async function generateChangelogForWorkspace(tree, args, nxReleaseConfig, commit
|
|
|
186
247
|
});
|
|
187
248
|
}
|
|
188
249
|
const releaseVersion = new shared_1.ReleaseVersion({
|
|
189
|
-
version:
|
|
250
|
+
version: workspaceChangelogVersion,
|
|
190
251
|
releaseTagPattern: nxReleaseConfig.releaseTagPattern,
|
|
191
252
|
});
|
|
192
253
|
// We are either creating/previewing a changelog file, a Github release, or both
|
|
@@ -329,7 +390,7 @@ async function generateChangelogForWorkspace(tree, args, nxReleaseConfig, commit
|
|
|
329
390
|
}
|
|
330
391
|
printSummary();
|
|
331
392
|
}
|
|
332
|
-
async function generateChangelogForProjects(tree, args, commits, postGitTasks, releaseGroup, projects) {
|
|
393
|
+
async function generateChangelogForProjects(tree, args, commits, projectsVersionData, postGitTasks, releaseGroup, projects) {
|
|
333
394
|
const config = releaseGroup.changelog;
|
|
334
395
|
// The entire feature is disabled at the release group level, exit early
|
|
335
396
|
if (config === false) {
|
|
@@ -339,7 +400,6 @@ async function generateChangelogForProjects(tree, args, commits, postGitTasks, r
|
|
|
339
400
|
const interactive = args.interactive === 'all' || args.interactive === 'projects';
|
|
340
401
|
const dryRun = !!args.dryRun;
|
|
341
402
|
const gitRemote = args.gitRemote;
|
|
342
|
-
const rawVersion = args.version;
|
|
343
403
|
const changelogRenderer = resolveChangelogRenderer(config.renderer);
|
|
344
404
|
for (const project of projects) {
|
|
345
405
|
let interpolatedTreePath = config.file || '';
|
|
@@ -350,8 +410,15 @@ async function generateChangelogForProjects(tree, args, commits, postGitTasks, r
|
|
|
350
410
|
workspaceRoot: '', // within the tree, workspaceRoot is the root
|
|
351
411
|
});
|
|
352
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* newVersion will be null in the case that no changes were detected (e.g. in conventional commits mode),
|
|
415
|
+
* no changelog entry is relevant in that case.
|
|
416
|
+
*/
|
|
417
|
+
if (projectsVersionData[project.name].newVersion === null) {
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
353
420
|
const releaseVersion = new shared_1.ReleaseVersion({
|
|
354
|
-
version:
|
|
421
|
+
version: projectsVersionData[project.name].newVersion,
|
|
355
422
|
releaseTagPattern: releaseGroup.releaseTagPattern,
|
|
356
423
|
projectName: project.name,
|
|
357
424
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommandModule } from 'yargs';
|
|
2
|
-
import { RunManyOptions } from '../yargs-utils/shared-options';
|
|
2
|
+
import { OutputStyle, RunManyOptions } from '../yargs-utils/shared-options';
|
|
3
|
+
import { VersionData } from './utils/shared';
|
|
3
4
|
export interface NxReleaseArgs {
|
|
4
5
|
groups?: string[];
|
|
5
6
|
projects?: string[];
|
|
@@ -17,15 +18,19 @@ interface GitCommitAndTagOptions {
|
|
|
17
18
|
export type VersionOptions = NxReleaseArgs & GitCommitAndTagOptions & {
|
|
18
19
|
specifier?: string;
|
|
19
20
|
preid?: string;
|
|
21
|
+
stageChanges?: boolean;
|
|
20
22
|
};
|
|
21
23
|
export type ChangelogOptions = NxReleaseArgs & GitCommitAndTagOptions & {
|
|
22
|
-
version
|
|
23
|
-
|
|
24
|
+
version?: string | null;
|
|
25
|
+
versionData?: VersionData;
|
|
26
|
+
to?: string;
|
|
24
27
|
from?: string;
|
|
25
28
|
interactive?: string;
|
|
26
29
|
gitRemote?: string;
|
|
27
30
|
};
|
|
28
|
-
export type PublishOptions = NxReleaseArgs & RunManyOptions & {
|
|
31
|
+
export type PublishOptions = NxReleaseArgs & Partial<RunManyOptions> & {
|
|
32
|
+
outputStyle?: OutputStyle;
|
|
33
|
+
} & {
|
|
29
34
|
registry?: string;
|
|
30
35
|
tag?: string;
|
|
31
36
|
otp?: number;
|
|
@@ -68,8 +68,19 @@ const versionCommand = {
|
|
|
68
68
|
type: 'string',
|
|
69
69
|
describe: 'The optional prerelease identifier to apply to the version, in the case that specifier has been set to prerelease.',
|
|
70
70
|
default: '',
|
|
71
|
+
})
|
|
72
|
+
.option('stageChanges', {
|
|
73
|
+
type: 'boolean',
|
|
74
|
+
describe: 'Whether or not to stage the changes made by this command, irrespective of the git config in nx.json related to automated commits. Useful when combining this command with changelog generation.',
|
|
75
|
+
default: false,
|
|
71
76
|
})),
|
|
72
|
-
handler: (args) => Promise.resolve().then(() => require('./version')).then((m) => m.
|
|
77
|
+
handler: (args) => Promise.resolve().then(() => require('./version')).then((m) => m.releaseVersionCLIHandler(args))
|
|
78
|
+
.then((versionDataOrExitCode) => {
|
|
79
|
+
if (typeof versionDataOrExitCode === 'number') {
|
|
80
|
+
return process.exit(versionDataOrExitCode);
|
|
81
|
+
}
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}),
|
|
73
84
|
};
|
|
74
85
|
const changelogCommand = {
|
|
75
86
|
command: 'changelog [version]',
|
|
@@ -109,7 +120,7 @@ const changelogCommand = {
|
|
|
109
120
|
return true;
|
|
110
121
|
})),
|
|
111
122
|
handler: async (args) => {
|
|
112
|
-
const status = await (await Promise.resolve().then(() => require('./changelog'))).
|
|
123
|
+
const status = await (await Promise.resolve().then(() => require('./changelog'))).releaseChangelogCLIHandler(args);
|
|
113
124
|
process.exit(status);
|
|
114
125
|
},
|
|
115
126
|
};
|
|
@@ -130,7 +141,7 @@ const publishCommand = {
|
|
|
130
141
|
type: 'number',
|
|
131
142
|
description: 'A one-time password for publishing to a registry that requires 2FA',
|
|
132
143
|
}),
|
|
133
|
-
handler: (args) => Promise.resolve().then(() => require('./publish')).then((m) => m.
|
|
144
|
+
handler: (args) => Promise.resolve().then(() => require('./publish')).then((m) => m.releasePublishCLIHandler(coerceParallelOption((0, shared_options_1.withOverrides)(args, 2)))),
|
|
134
145
|
};
|
|
135
146
|
function coerceParallelOption(args) {
|
|
136
147
|
if (args['parallel'] === 'false' || args['parallel'] === false) {
|
|
@@ -23,6 +23,13 @@ type EnsureProjectsArray<T> = {
|
|
|
23
23
|
projects: string[];
|
|
24
24
|
} : T[K];
|
|
25
25
|
};
|
|
26
|
+
type RemoveTrueFromType<T> = T extends true ? never : T;
|
|
27
|
+
type RemoveTrueFromProperties<T, K extends keyof T> = {
|
|
28
|
+
[P in keyof T]: P extends K ? RemoveTrueFromType<T[P]> : T[P];
|
|
29
|
+
};
|
|
30
|
+
type RemoveTrueFromPropertiesOnEach<T, K extends keyof T[keyof T]> = {
|
|
31
|
+
[U in keyof T]: RemoveTrueFromProperties<T[U], K>;
|
|
32
|
+
};
|
|
26
33
|
export declare const CATCH_ALL_RELEASE_GROUP = "__default__";
|
|
27
34
|
/**
|
|
28
35
|
* Our source of truth is a deeply required variant of the user-facing config interface, so that command
|
|
@@ -34,7 +41,8 @@ export declare const CATCH_ALL_RELEASE_GROUP = "__default__";
|
|
|
34
41
|
* pattern such as directories and globs).
|
|
35
42
|
*/
|
|
36
43
|
export type NxReleaseConfig = DeepRequired<NxJsonConfiguration['release'] & {
|
|
37
|
-
groups: DeepRequired<EnsureProjectsArray<NxJsonConfiguration['release']['groups']>>;
|
|
44
|
+
groups: DeepRequired<RemoveTrueFromPropertiesOnEach<EnsureProjectsArray<NxJsonConfiguration['release']['groups']>, 'changelog'>>;
|
|
45
|
+
changelog: RemoveTrueFromProperties<DeepRequired<NxJsonConfiguration['release']['changelog']>, 'workspaceChangelog' | 'projectChangelogs'>;
|
|
38
46
|
}>;
|
|
39
47
|
export interface CreateNxReleaseConfigError {
|
|
40
48
|
code: 'RELEASE_GROUP_MATCHES_NO_PROJECTS' | 'RELEASE_GROUP_RELEASE_TAG_PATTERN_VERSION_PLACEHOLDER_MISSING_OR_EXCESSIVE' | 'PROJECT_MATCHES_MULTIPLE_GROUPS' | 'PROJECTS_MISSING_TARGET';
|
|
@@ -44,5 +52,5 @@ export declare function createNxReleaseConfig(projectGraph: ProjectGraph, userCo
|
|
|
44
52
|
error: null | CreateNxReleaseConfigError;
|
|
45
53
|
nxReleaseConfig: NxReleaseConfig | null;
|
|
46
54
|
}>;
|
|
47
|
-
export declare function handleNxReleaseConfigError(error: CreateNxReleaseConfigError): Promise<
|
|
55
|
+
export declare function handleNxReleaseConfigError(error: CreateNxReleaseConfigError): Promise<never>;
|
|
48
56
|
export {};
|
|
@@ -92,15 +92,25 @@ requiredTargetName) {
|
|
|
92
92
|
// Merge in the git defaults from the top level
|
|
93
93
|
{ git: rootGitConfig },
|
|
94
94
|
], userConfig.version);
|
|
95
|
+
if (userConfig.changelog?.workspaceChangelog) {
|
|
96
|
+
userConfig.changelog.workspaceChangelog = normalizeTrueToEmptyObject(userConfig.changelog.workspaceChangelog);
|
|
97
|
+
}
|
|
98
|
+
if (userConfig.changelog?.projectChangelogs) {
|
|
99
|
+
userConfig.changelog.projectChangelogs = normalizeTrueToEmptyObject(userConfig.changelog.projectChangelogs);
|
|
100
|
+
}
|
|
95
101
|
const rootChangelogConfig = deepMergeDefaults([
|
|
96
102
|
WORKSPACE_DEFAULTS.changelog,
|
|
97
103
|
// Merge in the git defaults from the top level
|
|
98
104
|
{ git: rootGitConfig },
|
|
99
|
-
], userConfig.changelog);
|
|
105
|
+
], normalizeTrueToEmptyObject(userConfig.changelog));
|
|
100
106
|
// git configuration is not supported at the group level, only the root/command level
|
|
101
107
|
const rootVersionWithoutGit = { ...rootVersionConfig };
|
|
102
108
|
delete rootVersionWithoutGit.git;
|
|
103
|
-
const allProjects = (0, find_matching_projects_1.findMatchingProjects)(['*'], projectGraph.nodes)
|
|
109
|
+
const allProjects = (0, find_matching_projects_1.findMatchingProjects)(['*'], projectGraph.nodes).filter(
|
|
110
|
+
// only include libs by default when the user has no groups config,
|
|
111
|
+
// because the default implementation assumes npm js packages
|
|
112
|
+
// and these will usually be libs
|
|
113
|
+
(project) => projectGraph.nodes[project].type === 'lib');
|
|
104
114
|
const groups = userConfig.groups && Object.keys(userConfig.groups).length
|
|
105
115
|
? ensureProjectsConfigIsArray(userConfig.groups)
|
|
106
116
|
: /**
|
|
@@ -183,6 +193,9 @@ requiredTargetName) {
|
|
|
183
193
|
groupChangelogDefaults.push(rootChangelogConfig.projectChangelogs);
|
|
184
194
|
}
|
|
185
195
|
const projectsRelationship = releaseGroup.projectsRelationship || GROUP_DEFAULTS.projectsRelationship;
|
|
196
|
+
if (releaseGroup.changelog) {
|
|
197
|
+
releaseGroup.changelog = normalizeTrueToEmptyObject(releaseGroup.changelog);
|
|
198
|
+
}
|
|
186
199
|
const groupDefaults = {
|
|
187
200
|
projectsRelationship,
|
|
188
201
|
projects: matchingProjects,
|
|
@@ -197,7 +210,7 @@ requiredTargetName) {
|
|
|
197
210
|
// The appropriate group default releaseTagPattern is dependent upon the projectRelationships
|
|
198
211
|
(projectsRelationship === 'independent'
|
|
199
212
|
? defaultIndependentReleaseTagPattern
|
|
200
|
-
: defaultFixedReleaseTagPattern),
|
|
213
|
+
: userConfig.releaseTagPattern || defaultFixedReleaseTagPattern),
|
|
201
214
|
};
|
|
202
215
|
releaseGroups[releaseGroupName] = deepMergeDefaults([groupDefaults], {
|
|
203
216
|
...releaseGroup,
|
|
@@ -218,6 +231,14 @@ requiredTargetName) {
|
|
|
218
231
|
};
|
|
219
232
|
}
|
|
220
233
|
exports.createNxReleaseConfig = createNxReleaseConfig;
|
|
234
|
+
/**
|
|
235
|
+
* In some cases it is much cleaner and more intuitive for the user to be able to
|
|
236
|
+
* specify `true` in their config when they want to use the default config for a
|
|
237
|
+
* particular property, rather than having to specify an empty object.
|
|
238
|
+
*/
|
|
239
|
+
function normalizeTrueToEmptyObject(value) {
|
|
240
|
+
return value === true ? {} : value;
|
|
241
|
+
}
|
|
221
242
|
async function handleNxReleaseConfigError(error) {
|
|
222
243
|
switch (error.code) {
|
|
223
244
|
case 'RELEASE_GROUP_MATCHES_NO_PROJECTS':
|