nx 19.5.6 → 19.6.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -12
- package/release/index.d.ts +1 -1
- package/release/index.js +2 -1
- package/schemas/nx-schema.json +3 -0
- package/src/adapter/compat.d.ts +1 -1
- package/src/adapter/compat.js +2 -0
- package/src/command-line/affected/affected.js +1 -1
- package/src/command-line/connect/connect-to-nx-cloud.js +7 -3
- package/src/command-line/release/changelog.d.ts +2 -7
- package/src/command-line/release/changelog.js +361 -347
- package/src/command-line/release/command-object.d.ts +1 -0
- package/src/command-line/release/command-object.js +14 -0
- package/src/command-line/release/config/deep-merge-json.d.ts +1 -0
- package/src/command-line/release/config/deep-merge-json.js +28 -0
- package/src/command-line/release/index.d.ts +16 -4
- package/src/command-line/release/index.js +23 -9
- package/src/command-line/release/plan.d.ts +2 -1
- package/src/command-line/release/plan.js +90 -77
- package/src/command-line/release/publish.d.ts +2 -6
- package/src/command-line/release/publish.js +67 -52
- package/src/command-line/release/release.d.ts +2 -1
- package/src/command-line/release/release.js +181 -165
- package/src/command-line/release/utils/print-config.d.ts +7 -0
- package/src/command-line/release/utils/print-config.js +36 -0
- package/src/command-line/release/version.d.ts +2 -6
- package/src/command-line/release/version.js +179 -165
- package/src/command-line/run/run-one.js +1 -1
- package/src/command-line/run-many/run-many.js +1 -1
- package/src/command-line/yargs-utils/shared-options.d.ts +1 -0
- package/src/command-line/yargs-utils/shared-options.js +5 -0
- package/src/commands-runner/create-command-graph.js +4 -2
- package/src/config/nx-json.d.ts +10 -1
- package/src/devkit-internals.d.ts +1 -1
- package/src/devkit-internals.js +2 -1
- package/src/generators/utils/project-configuration.js +41 -11
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.d.ts +4 -2
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +61 -20
- package/src/nx-cloud/nx-cloud-tasks-runner-shell.d.ts +1 -0
- package/src/nx-cloud/utilities/axios.js +9 -2
- package/src/nx-cloud/utilities/get-cloud-options.d.ts +1 -1
- package/src/nx-cloud/utilities/get-cloud-options.js +3 -2
- package/src/plugins/package-json/create-nodes.js +9 -1
- package/src/project-graph/plugins/isolation/plugin-pool.js +32 -10
- package/src/project-graph/utils/project-configuration-utils.d.ts +1 -0
- package/src/project-graph/utils/project-configuration-utils.js +1 -0
- package/src/tasks-runner/cache.js +1 -1
- package/src/tasks-runner/run-command.js +6 -1
- package/src/tasks-runner/utils.js +14 -10
- package/src/utils/command-line-utils.d.ts +1 -0
- package/src/utils/nx-cloud-utils.js +3 -1
- package/src/utils/package-json.d.ts +2 -9
@@ -1,7 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.releaseChangelogCLIHandler = void 0;
|
4
|
-
exports.
|
4
|
+
exports.createAPI = createAPI;
|
5
5
|
exports.shouldCreateGitHubRelease = shouldCreateGitHubRelease;
|
6
6
|
const chalk = require("chalk");
|
7
7
|
const enquirer_1 = require("enquirer");
|
@@ -20,6 +20,7 @@ const params_1 = require("../../utils/params");
|
|
20
20
|
const path_1 = require("../../utils/path");
|
21
21
|
const workspace_root_1 = require("../../utils/workspace-root");
|
22
22
|
const config_1 = require("./config/config");
|
23
|
+
const deep_merge_json_1 = require("./config/deep-merge-json");
|
23
24
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
24
25
|
const version_plans_1 = require("./config/version-plans");
|
25
26
|
const git_1 = require("./utils/git");
|
@@ -27,251 +28,362 @@ const github_1 = require("./utils/github");
|
|
27
28
|
const launch_editor_1 = require("./utils/launch-editor");
|
28
29
|
const markdown_1 = require("./utils/markdown");
|
29
30
|
const print_changes_1 = require("./utils/print-changes");
|
31
|
+
const print_config_1 = require("./utils/print-config");
|
30
32
|
const resolve_changelog_renderer_1 = require("./utils/resolve-changelog-renderer");
|
31
33
|
const resolve_nx_json_error_message_1 = require("./utils/resolve-nx-json-error-message");
|
32
34
|
const shared_1 = require("./utils/shared");
|
33
|
-
const releaseChangelogCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () =>
|
35
|
+
const releaseChangelogCLIHandler = (args) => (0, params_1.handleErrors)(args.verbose, () => createAPI({})(args));
|
34
36
|
exports.releaseChangelogCLIHandler = releaseChangelogCLIHandler;
|
35
|
-
|
36
|
-
* NOTE: This function is also exported for programmatic usage and forms part of the public API
|
37
|
-
* of Nx. We intentionally do not wrap the implementation with handleErrors because users need
|
38
|
-
* to have control over their own error handling when using the API.
|
39
|
-
*/
|
40
|
-
async function releaseChangelog(args) {
|
41
|
-
const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
|
42
|
-
const nxJson = (0, nx_json_1.readNxJson)();
|
43
|
-
if (args.verbose) {
|
44
|
-
process.env.NX_VERBOSE_LOGGING = 'true';
|
45
|
-
}
|
46
|
-
// Apply default configuration to any optional user configuration
|
47
|
-
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), nxJson.release);
|
48
|
-
if (configError) {
|
49
|
-
return await (0, config_1.handleNxReleaseConfigError)(configError);
|
50
|
-
}
|
51
|
-
// The nx release top level command will always override these three git args. This is how we can tell
|
52
|
-
// if the top level release command was used or if the user is using the changelog subcommand.
|
53
|
-
// If the user explicitly overrides these args, then it doesn't matter if the top level config is set,
|
54
|
-
// as all of the git options would be overridden anyway.
|
55
|
-
if ((args.gitCommit === undefined ||
|
56
|
-
args.gitTag === undefined ||
|
57
|
-
args.stageChanges === undefined) &&
|
58
|
-
nxJson.release?.git) {
|
59
|
-
const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)([
|
60
|
-
'release',
|
61
|
-
'git',
|
62
|
-
]);
|
63
|
-
output_1.output.error({
|
64
|
-
title: `The "release.git" property in nx.json may not be used with the "nx release changelog" subcommand or programmatic API. Instead, configure git options for subcommands directly with "release.version.git" and "release.changelog.git".`,
|
65
|
-
bodyLines: [nxJsonMessage],
|
66
|
-
});
|
67
|
-
process.exit(1);
|
68
|
-
}
|
69
|
-
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
70
|
-
if (filterError) {
|
71
|
-
output_1.output.error(filterError);
|
72
|
-
process.exit(1);
|
73
|
-
}
|
74
|
-
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
75
|
-
(0, version_plans_1.setVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
76
|
-
if (args.deleteVersionPlans === undefined) {
|
77
|
-
// default to deleting version plans in this command instead of after versioning
|
78
|
-
args.deleteVersionPlans = true;
|
79
|
-
}
|
80
|
-
const changelogGenerationEnabled = !!nxReleaseConfig.changelog.workspaceChangelog ||
|
81
|
-
Object.values(nxReleaseConfig.groups).some((g) => g.changelog);
|
82
|
-
if (!changelogGenerationEnabled) {
|
83
|
-
output_1.output.warn({
|
84
|
-
title: `Changelogs are disabled. No changelog entries will be generated`,
|
85
|
-
bodyLines: [
|
86
|
-
`To explicitly enable changelog generation, configure "release.changelog.workspaceChangelog" or "release.changelog.projectChangelogs" in nx.json.`,
|
87
|
-
],
|
88
|
-
});
|
89
|
-
return {};
|
90
|
-
}
|
91
|
-
const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
|
92
|
-
const useAutomaticFromRef = nxReleaseConfig.changelog?.automaticFromRef || args.firstRelease;
|
93
|
-
/**
|
94
|
-
* For determining the versions to use within changelog files, there are a few different possibilities:
|
95
|
-
* - the user is using the nx CLI, and therefore passes a single --version argument which represents the version for any and all changelog
|
96
|
-
* files which will be generated (i.e. both the workspace changelog, and all project changelogs, depending on which of those has been enabled)
|
97
|
-
* - the user is using the nxReleaseChangelog API programmatically, and:
|
98
|
-
* - passes only a version property
|
99
|
-
* - this works in the same way as described above for the CLI
|
100
|
-
* - passes only a versionData object
|
101
|
-
* - this is a special case where the user is providing a version for each project, and therefore the version argument is not needed
|
102
|
-
* - NOTE: it is not possible to generate a workspace level changelog with only a versionData object, and this will produce an error
|
103
|
-
* - passes both a version and a versionData object
|
104
|
-
* - in this case, the version property will be used as the reference for the workspace changelog, and the versionData object will be used
|
105
|
-
* to generate project changelogs
|
106
|
-
*/
|
107
|
-
const { workspaceChangelogVersion, projectsVersionData } = resolveChangelogVersions(args, releaseGroups, releaseGroupToFilteredProjects);
|
108
|
-
const to = args.to || 'HEAD';
|
109
|
-
const toSHA = await (0, git_1.getCommitHash)(to);
|
110
|
-
const headSHA = to === 'HEAD' ? toSHA : await (0, git_1.getCommitHash)('HEAD');
|
37
|
+
function createAPI(overrideReleaseConfig) {
|
111
38
|
/**
|
112
|
-
*
|
113
|
-
*
|
39
|
+
* NOTE: This function is also exported for programmatic usage and forms part of the public API
|
40
|
+
* of Nx. We intentionally do not wrap the implementation with handleErrors because users need
|
41
|
+
* to have control over their own error handling when using the API.
|
114
42
|
*/
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
// 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
|
122
|
-
const gitTagValues = args.gitTag ?? nxReleaseConfig.changelog.git.tag
|
123
|
-
? (0, shared_1.createGitTagValues)(releaseGroups, releaseGroupToFilteredProjects, projectsVersionData)
|
124
|
-
: [];
|
125
|
-
(0, shared_1.handleDuplicateGitTags)(gitTagValues);
|
126
|
-
const postGitTasks = [];
|
127
|
-
let workspaceChangelogChanges = [];
|
128
|
-
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
129
|
-
let workspaceChangelogCommits = [];
|
130
|
-
// If there are multiple release groups, we'll just skip the workspace changelog anyway.
|
131
|
-
const versionPlansEnabledForWorkspaceChangelog = releaseGroups[0].versionPlans;
|
132
|
-
if (versionPlansEnabledForWorkspaceChangelog) {
|
133
|
-
if (releaseGroups.length === 1) {
|
134
|
-
const releaseGroup = releaseGroups[0];
|
135
|
-
if (releaseGroup.projectsRelationship === 'fixed') {
|
136
|
-
const versionPlans = releaseGroup.versionPlans;
|
137
|
-
workspaceChangelogChanges = filterHiddenChanges(versionPlans
|
138
|
-
.map((vp) => {
|
139
|
-
const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
|
140
|
-
// only properly formatted conventional commits messages will be included in the changelog
|
141
|
-
if (!parsedMessage) {
|
142
|
-
return null;
|
143
|
-
}
|
144
|
-
return {
|
145
|
-
type: parsedMessage.type,
|
146
|
-
scope: parsedMessage.scope,
|
147
|
-
description: parsedMessage.description,
|
148
|
-
body: '',
|
149
|
-
isBreaking: parsedMessage.breaking,
|
150
|
-
githubReferences: [],
|
151
|
-
};
|
152
|
-
})
|
153
|
-
.filter(Boolean), nxReleaseConfig.conventionalCommits);
|
154
|
-
}
|
43
|
+
return async function releaseChangelog(args) {
|
44
|
+
const projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
|
45
|
+
const nxJson = (0, nx_json_1.readNxJson)();
|
46
|
+
const userProvidedReleaseConfig = (0, deep_merge_json_1.deepMergeJson)(nxJson.release ?? {}, overrideReleaseConfig ?? {});
|
47
|
+
if (args.verbose) {
|
48
|
+
process.env.NX_VERBOSE_LOGGING = 'true';
|
155
49
|
}
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
if (!workspaceChangelogFromRef) {
|
161
|
-
if (useAutomaticFromRef) {
|
162
|
-
workspaceChangelogFromRef = await (0, git_1.getFirstGitCommit)();
|
163
|
-
if (args.verbose) {
|
164
|
-
console.log(`Determined workspace --from ref from the first commit in the workspace: ${workspaceChangelogFromRef}`);
|
165
|
-
}
|
166
|
-
}
|
167
|
-
else {
|
168
|
-
throw new Error(`Unable to determine the previous git tag. If this is the first release of your workspace, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`);
|
169
|
-
}
|
50
|
+
// Apply default configuration to any optional user configuration
|
51
|
+
const { error: configError, nxReleaseConfig } = await (0, config_1.createNxReleaseConfig)(projectGraph, await (0, file_map_utils_1.createProjectFileMapUsingProjectGraph)(projectGraph), userProvidedReleaseConfig);
|
52
|
+
if (configError) {
|
53
|
+
return await (0, config_1.handleNxReleaseConfigError)(configError);
|
170
54
|
}
|
171
|
-
//
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
55
|
+
// --print-config exits directly as it is not designed to be combined with any other programmatic operations
|
56
|
+
if (args.printConfig) {
|
57
|
+
return (0, print_config_1.printConfigAndExit)({
|
58
|
+
userProvidedReleaseConfig,
|
59
|
+
nxReleaseConfig,
|
60
|
+
isDebug: args.printConfig === 'debug',
|
61
|
+
});
|
62
|
+
}
|
63
|
+
// The nx release top level command will always override these three git args. This is how we can tell
|
64
|
+
// if the top level release command was used or if the user is using the changelog subcommand.
|
65
|
+
// If the user explicitly overrides these args, then it doesn't matter if the top level config is set,
|
66
|
+
// as all of the git options would be overridden anyway.
|
67
|
+
if ((args.gitCommit === undefined ||
|
68
|
+
args.gitTag === undefined ||
|
69
|
+
args.stageChanges === undefined) &&
|
70
|
+
userProvidedReleaseConfig.git) {
|
71
|
+
const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)([
|
72
|
+
'release',
|
73
|
+
'git',
|
74
|
+
]);
|
75
|
+
output_1.output.error({
|
76
|
+
title: `The "release.git" property in nx.json may not be used with the "nx release changelog" subcommand or programmatic API. Instead, configure git options for subcommands directly with "release.version.git" and "release.changelog.git".`,
|
77
|
+
bodyLines: [nxJsonMessage],
|
78
|
+
});
|
79
|
+
process.exit(1);
|
80
|
+
}
|
81
|
+
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
82
|
+
if (filterError) {
|
83
|
+
output_1.output.error(filterError);
|
84
|
+
process.exit(1);
|
85
|
+
}
|
86
|
+
const rawVersionPlans = await (0, version_plans_1.readRawVersionPlans)();
|
87
|
+
(0, version_plans_1.setVersionPlansOnGroups)(rawVersionPlans, releaseGroups, Object.keys(projectGraph.nodes));
|
88
|
+
if (args.deleteVersionPlans === undefined) {
|
89
|
+
// default to deleting version plans in this command instead of after versioning
|
90
|
+
args.deleteVersionPlans = true;
|
91
|
+
}
|
92
|
+
const changelogGenerationEnabled = !!nxReleaseConfig.changelog.workspaceChangelog ||
|
93
|
+
Object.values(nxReleaseConfig.groups).some((g) => g.changelog);
|
94
|
+
if (!changelogGenerationEnabled) {
|
95
|
+
output_1.output.warn({
|
96
|
+
title: `Changelogs are disabled. No changelog entries will be generated`,
|
97
|
+
bodyLines: [
|
98
|
+
`To explicitly enable changelog generation, configure "release.changelog.workspaceChangelog" or "release.changelog.projectChangelogs" in nx.json.`,
|
99
|
+
],
|
100
|
+
});
|
101
|
+
return {};
|
102
|
+
}
|
103
|
+
const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
|
104
|
+
const useAutomaticFromRef = nxReleaseConfig.changelog?.automaticFromRef || args.firstRelease;
|
105
|
+
/**
|
106
|
+
* For determining the versions to use within changelog files, there are a few different possibilities:
|
107
|
+
* - the user is using the nx CLI, and therefore passes a single --version argument which represents the version for any and all changelog
|
108
|
+
* files which will be generated (i.e. both the workspace changelog, and all project changelogs, depending on which of those has been enabled)
|
109
|
+
* - the user is using the nxReleaseChangelog API programmatically, and:
|
110
|
+
* - passes only a version property
|
111
|
+
* - this works in the same way as described above for the CLI
|
112
|
+
* - passes only a versionData object
|
113
|
+
* - this is a special case where the user is providing a version for each project, and therefore the version argument is not needed
|
114
|
+
* - NOTE: it is not possible to generate a workspace level changelog with only a versionData object, and this will produce an error
|
115
|
+
* - passes both a version and a versionData object
|
116
|
+
* - in this case, the version property will be used as the reference for the workspace changelog, and the versionData object will be used
|
117
|
+
* to generate project changelogs
|
118
|
+
*/
|
119
|
+
const { workspaceChangelogVersion, projectsVersionData } = resolveChangelogVersions(args, releaseGroups, releaseGroupToFilteredProjects);
|
120
|
+
const to = args.to || 'HEAD';
|
121
|
+
const toSHA = await (0, git_1.getCommitHash)(to);
|
122
|
+
const headSHA = to === 'HEAD' ? toSHA : await (0, git_1.getCommitHash)('HEAD');
|
123
|
+
/**
|
124
|
+
* Protect the user against attempting to create a new commit when recreating an old release changelog,
|
125
|
+
* this seems like it would always be unintentional.
|
126
|
+
*/
|
127
|
+
const autoCommitEnabled = args.gitCommit ?? nxReleaseConfig.changelog.git.commit;
|
128
|
+
if (autoCommitEnabled && headSHA !== toSHA) {
|
129
|
+
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`);
|
130
|
+
}
|
131
|
+
const commitMessage = args.gitCommitMessage || nxReleaseConfig.changelog.git.commitMessage;
|
132
|
+
const commitMessageValues = (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, projectsVersionData, commitMessage);
|
133
|
+
// 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
|
134
|
+
const gitTagValues = args.gitTag ?? nxReleaseConfig.changelog.git.tag
|
135
|
+
? (0, shared_1.createGitTagValues)(releaseGroups, releaseGroupToFilteredProjects, projectsVersionData)
|
136
|
+
: [];
|
137
|
+
(0, shared_1.handleDuplicateGitTags)(gitTagValues);
|
138
|
+
const postGitTasks = [];
|
139
|
+
let workspaceChangelogChanges = [];
|
196
140
|
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
141
|
+
let workspaceChangelogCommits = [];
|
142
|
+
// If there are multiple release groups, we'll just skip the workspace changelog anyway.
|
143
|
+
const versionPlansEnabledForWorkspaceChangelog = releaseGroups[0].versionPlans;
|
144
|
+
if (versionPlansEnabledForWorkspaceChangelog) {
|
145
|
+
if (releaseGroups.length === 1) {
|
146
|
+
const releaseGroup = releaseGroups[0];
|
147
|
+
if (releaseGroup.projectsRelationship === 'fixed') {
|
148
|
+
const versionPlans = releaseGroup.versionPlans;
|
149
|
+
workspaceChangelogChanges = filterHiddenChanges(versionPlans
|
150
|
+
.map((vp) => {
|
151
|
+
const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
|
152
|
+
// only properly formatted conventional commits messages will be included in the changelog
|
153
|
+
if (!parsedMessage) {
|
154
|
+
return null;
|
155
|
+
}
|
156
|
+
return {
|
157
|
+
type: parsedMessage.type,
|
158
|
+
scope: parsedMessage.scope,
|
159
|
+
description: parsedMessage.description,
|
160
|
+
body: '',
|
161
|
+
isBreaking: parsedMessage.breaking,
|
162
|
+
githubReferences: [],
|
163
|
+
};
|
164
|
+
})
|
165
|
+
.filter(Boolean), nxReleaseConfig.conventionalCommits);
|
166
|
+
}
|
212
167
|
}
|
213
|
-
output_1.output.logSingleLine(`Creating GitHub Release`);
|
214
|
-
await (0, github_1.createOrUpdateGithubRelease)(workspaceChangelog.releaseVersion, workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
215
|
-
});
|
216
|
-
}
|
217
|
-
/**
|
218
|
-
* Compute any additional dependency bumps up front because there could be cases of circular dependencies,
|
219
|
-
* and figuring them out during the main iteration would be too late.
|
220
|
-
*/
|
221
|
-
const projectToAdditionalDependencyBumps = new Map();
|
222
|
-
for (const releaseGroup of releaseGroups) {
|
223
|
-
if (releaseGroup.projectsRelationship !== 'independent') {
|
224
|
-
continue;
|
225
168
|
}
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
169
|
+
else {
|
170
|
+
let workspaceChangelogFromRef = args.from ||
|
171
|
+
(await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern))
|
172
|
+
?.tag;
|
173
|
+
if (!workspaceChangelogFromRef) {
|
174
|
+
if (useAutomaticFromRef) {
|
175
|
+
workspaceChangelogFromRef = await (0, git_1.getFirstGitCommit)();
|
176
|
+
if (args.verbose) {
|
177
|
+
console.log(`Determined workspace --from ref from the first commit in the workspace: ${workspaceChangelogFromRef}`);
|
178
|
+
}
|
179
|
+
}
|
180
|
+
else {
|
181
|
+
throw new Error(`Unable to determine the previous git tag. If this is the first release of your workspace, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`);
|
182
|
+
}
|
231
183
|
}
|
232
|
-
|
233
|
-
|
184
|
+
// Make sure that the fromRef is actually resolvable
|
185
|
+
const workspaceChangelogFromSHA = await (0, git_1.getCommitHash)(workspaceChangelogFromRef);
|
186
|
+
workspaceChangelogCommits = await getCommits(workspaceChangelogFromSHA, toSHA);
|
187
|
+
workspaceChangelogChanges = filterHiddenChanges(workspaceChangelogCommits.map((c) => {
|
234
188
|
return {
|
235
|
-
|
236
|
-
|
189
|
+
type: c.type,
|
190
|
+
scope: c.scope,
|
191
|
+
description: c.description,
|
192
|
+
body: c.body,
|
193
|
+
isBreaking: c.isBreaking,
|
194
|
+
githubReferences: c.references,
|
195
|
+
author: c.author,
|
196
|
+
shortHash: c.shortHash,
|
197
|
+
revertedHashes: c.revertedHashes,
|
198
|
+
affectedProjects: '*',
|
237
199
|
};
|
238
|
-
})
|
239
|
-
.filter((b) => b.newVersion !== null);
|
240
|
-
for (const dependent of dependentProjects) {
|
241
|
-
const additionalDependencyBumpsForProject = projectToAdditionalDependencyBumps.has(dependent.dependencyName)
|
242
|
-
? projectToAdditionalDependencyBumps.get(dependent.dependencyName)
|
243
|
-
: [];
|
244
|
-
additionalDependencyBumpsForProject.push({
|
245
|
-
dependencyName: project,
|
246
|
-
newVersion: projectsVersionData[project].newVersion,
|
247
|
-
});
|
248
|
-
projectToAdditionalDependencyBumps.set(dependent.dependencyName, additionalDependencyBumpsForProject);
|
249
|
-
}
|
200
|
+
}), nxReleaseConfig.conventionalCommits);
|
250
201
|
}
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
202
|
+
const workspaceChangelog = await generateChangelogForWorkspace({
|
203
|
+
tree,
|
204
|
+
args,
|
205
|
+
projectGraph,
|
206
|
+
nxReleaseConfig,
|
207
|
+
workspaceChangelogVersion,
|
208
|
+
changes: workspaceChangelogChanges,
|
209
|
+
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
210
|
+
commits: filterHiddenCommits(workspaceChangelogCommits, nxReleaseConfig.conventionalCommits),
|
211
|
+
});
|
212
|
+
if (workspaceChangelog &&
|
213
|
+
shouldCreateGitHubRelease(nxReleaseConfig.changelog.workspaceChangelog, args.createRelease)) {
|
214
|
+
let hasPushed = false;
|
215
|
+
postGitTasks.push(async (latestCommit) => {
|
216
|
+
if (!hasPushed) {
|
217
|
+
output_1.output.logSingleLine(`Pushing to git remote`);
|
218
|
+
// Before we can create/update the release we need to ensure the commit exists on the remote
|
219
|
+
await (0, git_1.gitPush)({
|
220
|
+
gitRemote: args.gitRemote,
|
221
|
+
dryRun: args.dryRun,
|
222
|
+
verbose: args.verbose,
|
223
|
+
});
|
224
|
+
hasPushed = true;
|
225
|
+
}
|
226
|
+
output_1.output.logSingleLine(`Creating GitHub Release`);
|
227
|
+
await (0, github_1.createOrUpdateGithubRelease)(workspaceChangelog.releaseVersion, workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
228
|
+
});
|
258
229
|
}
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
230
|
+
/**
|
231
|
+
* Compute any additional dependency bumps up front because there could be cases of circular dependencies,
|
232
|
+
* and figuring them out during the main iteration would be too late.
|
233
|
+
*/
|
234
|
+
const projectToAdditionalDependencyBumps = new Map();
|
235
|
+
for (const releaseGroup of releaseGroups) {
|
236
|
+
if (releaseGroup.projectsRelationship !== 'independent') {
|
237
|
+
continue;
|
238
|
+
}
|
239
|
+
for (const project of releaseGroup.projects) {
|
240
|
+
// If the project does not have any changes, do not process its dependents
|
241
|
+
if (!projectsVersionData[project] ||
|
242
|
+
projectsVersionData[project].newVersion === null) {
|
243
|
+
continue;
|
244
|
+
}
|
245
|
+
const dependentProjects = (projectsVersionData[project].dependentProjects || [])
|
246
|
+
.map((dep) => {
|
247
|
+
return {
|
248
|
+
dependencyName: dep.source,
|
249
|
+
newVersion: projectsVersionData[dep.source].newVersion,
|
250
|
+
};
|
266
251
|
})
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
252
|
+
.filter((b) => b.newVersion !== null);
|
253
|
+
for (const dependent of dependentProjects) {
|
254
|
+
const additionalDependencyBumpsForProject = projectToAdditionalDependencyBumps.has(dependent.dependencyName)
|
255
|
+
? projectToAdditionalDependencyBumps.get(dependent.dependencyName)
|
256
|
+
: [];
|
257
|
+
additionalDependencyBumpsForProject.push({
|
258
|
+
dependencyName: project,
|
259
|
+
newVersion: projectsVersionData[project].newVersion,
|
260
|
+
});
|
261
|
+
projectToAdditionalDependencyBumps.set(dependent.dependencyName, additionalDependencyBumpsForProject);
|
262
|
+
}
|
263
|
+
}
|
264
|
+
}
|
265
|
+
const allProjectChangelogs = {};
|
266
|
+
for (const releaseGroup of releaseGroups) {
|
267
|
+
const config = releaseGroup.changelog;
|
268
|
+
// The entire feature is disabled at the release group level, exit early
|
269
|
+
if (config === false) {
|
270
|
+
continue;
|
271
|
+
}
|
272
|
+
const projects = args.projects?.length
|
273
|
+
? // If the user has passed a list of projects, we need to use the filtered list of projects within the release group, plus any dependents
|
274
|
+
Array.from(releaseGroupToFilteredProjects.get(releaseGroup)).flatMap((project) => {
|
275
|
+
return [
|
276
|
+
project,
|
277
|
+
...(projectsVersionData[project]?.dependentProjects.map((dep) => dep.source) || []),
|
278
|
+
];
|
279
|
+
})
|
280
|
+
: // Otherwise, we use the full list of projects within the release group
|
281
|
+
releaseGroup.projects;
|
282
|
+
const projectNodes = projects.map((name) => projectGraph.nodes[name]);
|
283
|
+
if (releaseGroup.projectsRelationship === 'independent') {
|
284
|
+
for (const project of projectNodes) {
|
285
|
+
let changes = null;
|
286
|
+
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
287
|
+
let commits;
|
288
|
+
if (releaseGroup.versionPlans) {
|
289
|
+
changes = filterHiddenChanges(releaseGroup.versionPlans
|
290
|
+
.map((vp) => {
|
291
|
+
const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
|
292
|
+
// only properly formatted conventional commits messages will be included in the changelog
|
293
|
+
if (!parsedMessage) {
|
294
|
+
return null;
|
295
|
+
}
|
296
|
+
return {
|
297
|
+
type: parsedMessage.type,
|
298
|
+
scope: parsedMessage.scope,
|
299
|
+
description: parsedMessage.description,
|
300
|
+
body: '',
|
301
|
+
isBreaking: parsedMessage.breaking,
|
302
|
+
affectedProjects: Object.keys(vp.projectVersionBumps),
|
303
|
+
githubReferences: [],
|
304
|
+
};
|
305
|
+
})
|
306
|
+
.filter(Boolean), nxReleaseConfig.conventionalCommits);
|
307
|
+
}
|
308
|
+
else {
|
309
|
+
let fromRef = args.from ||
|
310
|
+
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {
|
311
|
+
projectName: project.name,
|
312
|
+
releaseGroupName: releaseGroup.name,
|
313
|
+
}))?.tag;
|
314
|
+
if (!fromRef && useAutomaticFromRef) {
|
315
|
+
const firstCommit = await (0, git_1.getFirstGitCommit)();
|
316
|
+
const allCommits = await getCommits(firstCommit, toSHA);
|
317
|
+
const commitsForProject = allCommits.filter((c) => c.affectedFiles.find((f) => f.startsWith(project.data.root)));
|
318
|
+
fromRef = commitsForProject[0]?.shortHash;
|
319
|
+
if (args.verbose) {
|
320
|
+
console.log(`Determined --from ref for ${project.name} from the first commit in which it exists: ${fromRef}`);
|
321
|
+
}
|
322
|
+
commits = commitsForProject;
|
323
|
+
}
|
324
|
+
if (!fromRef && !commits) {
|
325
|
+
throw new Error(`Unable to determine the previous git tag. If this is the first release of your workspace, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`);
|
326
|
+
}
|
327
|
+
if (!commits) {
|
328
|
+
commits = await getCommits(fromRef, toSHA);
|
329
|
+
}
|
330
|
+
const { fileMap } = await (0, file_map_utils_1.createFileMapUsingProjectGraph)(projectGraph);
|
331
|
+
const fileToProjectMap = createFileToProjectMap(fileMap.projectFileMap);
|
332
|
+
changes = filterHiddenChanges(commits.map((c) => ({
|
333
|
+
type: c.type,
|
334
|
+
scope: c.scope,
|
335
|
+
description: c.description,
|
336
|
+
body: c.body,
|
337
|
+
isBreaking: c.isBreaking,
|
338
|
+
githubReferences: c.references,
|
339
|
+
author: c.author,
|
340
|
+
shortHash: c.shortHash,
|
341
|
+
revertedHashes: c.revertedHashes,
|
342
|
+
affectedProjects: commitChangesNonProjectFiles(c, fileMap.nonProjectFiles)
|
343
|
+
? '*'
|
344
|
+
: getProjectsAffectedByCommit(c, fileToProjectMap),
|
345
|
+
})), nxReleaseConfig.conventionalCommits);
|
346
|
+
}
|
347
|
+
const projectChangelogs = await generateChangelogForProjects({
|
348
|
+
tree,
|
349
|
+
args,
|
350
|
+
projectGraph,
|
351
|
+
changes,
|
352
|
+
projectsVersionData,
|
353
|
+
releaseGroup,
|
354
|
+
projects: [project],
|
355
|
+
nxReleaseConfig,
|
356
|
+
projectToAdditionalDependencyBumps,
|
357
|
+
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
358
|
+
commits: filterHiddenCommits(commits, nxReleaseConfig.conventionalCommits),
|
359
|
+
});
|
360
|
+
let hasPushed = false;
|
361
|
+
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
362
|
+
if (projectChangelogs &&
|
363
|
+
shouldCreateGitHubRelease(releaseGroup.changelog, args.createRelease)) {
|
364
|
+
postGitTasks.push(async (latestCommit) => {
|
365
|
+
if (!hasPushed) {
|
366
|
+
output_1.output.logSingleLine(`Pushing to git remote`);
|
367
|
+
// Before we can create/update the release we need to ensure the commit exists on the remote
|
368
|
+
await (0, git_1.gitPush)({
|
369
|
+
gitRemote: args.gitRemote,
|
370
|
+
dryRun: args.dryRun,
|
371
|
+
verbose: args.verbose,
|
372
|
+
});
|
373
|
+
hasPushed = true;
|
374
|
+
}
|
375
|
+
output_1.output.logSingleLine(`Creating GitHub Release`);
|
376
|
+
await (0, github_1.createOrUpdateGithubRelease)(projectChangelog.releaseVersion, projectChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
377
|
+
});
|
378
|
+
}
|
379
|
+
allProjectChangelogs[projectName] = projectChangelog;
|
380
|
+
}
|
381
|
+
}
|
382
|
+
}
|
383
|
+
else {
|
384
|
+
let changes = [];
|
273
385
|
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
274
|
-
let commits;
|
386
|
+
let commits = [];
|
275
387
|
if (releaseGroup.versionPlans) {
|
276
388
|
changes = filterHiddenChanges(releaseGroup.versionPlans
|
277
389
|
.map((vp) => {
|
@@ -286,36 +398,32 @@ async function releaseChangelog(args) {
|
|
286
398
|
description: parsedMessage.description,
|
287
399
|
body: '',
|
288
400
|
isBreaking: parsedMessage.breaking,
|
289
|
-
affectedProjects: Object.keys(vp.projectVersionBumps),
|
290
401
|
githubReferences: [],
|
402
|
+
affectedProjects: '*',
|
291
403
|
};
|
292
404
|
})
|
293
405
|
.filter(Boolean), nxReleaseConfig.conventionalCommits);
|
294
406
|
}
|
295
407
|
else {
|
296
408
|
let fromRef = args.from ||
|
297
|
-
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
409
|
+
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern))
|
410
|
+
?.tag;
|
411
|
+
if (!fromRef) {
|
412
|
+
if (useAutomaticFromRef) {
|
413
|
+
fromRef = await (0, git_1.getFirstGitCommit)();
|
414
|
+
if (args.verbose) {
|
415
|
+
console.log(`Determined release group --from ref from the first commit in the workspace: ${fromRef}`);
|
416
|
+
}
|
417
|
+
}
|
418
|
+
else {
|
419
|
+
throw new Error(`Unable to determine the previous git tag. If this is the first release of your release group, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`);
|
308
420
|
}
|
309
|
-
commits = commitsForProject;
|
310
|
-
}
|
311
|
-
if (!fromRef && !commits) {
|
312
|
-
throw new Error(`Unable to determine the previous git tag. If this is the first release of your workspace, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`);
|
313
|
-
}
|
314
|
-
if (!commits) {
|
315
|
-
commits = await getCommits(fromRef, toSHA);
|
316
421
|
}
|
422
|
+
// Make sure that the fromRef is actually resolvable
|
423
|
+
const fromSHA = await (0, git_1.getCommitHash)(fromRef);
|
317
424
|
const { fileMap } = await (0, file_map_utils_1.createFileMapUsingProjectGraph)(projectGraph);
|
318
425
|
const fileToProjectMap = createFileToProjectMap(fileMap.projectFileMap);
|
426
|
+
commits = await getCommits(fromSHA, toSHA);
|
319
427
|
changes = filterHiddenChanges(commits.map((c) => ({
|
320
428
|
type: c.type,
|
321
429
|
scope: c.scope,
|
@@ -338,7 +446,7 @@ async function releaseChangelog(args) {
|
|
338
446
|
changes,
|
339
447
|
projectsVersionData,
|
340
448
|
releaseGroup,
|
341
|
-
projects:
|
449
|
+
projects: projectNodes,
|
342
450
|
nxReleaseConfig,
|
343
451
|
projectToAdditionalDependencyBumps,
|
344
452
|
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
@@ -367,105 +475,11 @@ async function releaseChangelog(args) {
|
|
367
475
|
}
|
368
476
|
}
|
369
477
|
}
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
changes = filterHiddenChanges(releaseGroup.versionPlans
|
376
|
-
.map((vp) => {
|
377
|
-
const parsedMessage = (0, git_1.parseConventionalCommitsMessage)(vp.message);
|
378
|
-
// only properly formatted conventional commits messages will be included in the changelog
|
379
|
-
if (!parsedMessage) {
|
380
|
-
return null;
|
381
|
-
}
|
382
|
-
return {
|
383
|
-
type: parsedMessage.type,
|
384
|
-
scope: parsedMessage.scope,
|
385
|
-
description: parsedMessage.description,
|
386
|
-
body: '',
|
387
|
-
isBreaking: parsedMessage.breaking,
|
388
|
-
githubReferences: [],
|
389
|
-
affectedProjects: '*',
|
390
|
-
};
|
391
|
-
})
|
392
|
-
.filter(Boolean), nxReleaseConfig.conventionalCommits);
|
393
|
-
}
|
394
|
-
else {
|
395
|
-
let fromRef = args.from ||
|
396
|
-
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern))
|
397
|
-
?.tag;
|
398
|
-
if (!fromRef) {
|
399
|
-
if (useAutomaticFromRef) {
|
400
|
-
fromRef = await (0, git_1.getFirstGitCommit)();
|
401
|
-
if (args.verbose) {
|
402
|
-
console.log(`Determined release group --from ref from the first commit in the workspace: ${fromRef}`);
|
403
|
-
}
|
404
|
-
}
|
405
|
-
else {
|
406
|
-
throw new Error(`Unable to determine the previous git tag. If this is the first release of your release group, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`);
|
407
|
-
}
|
408
|
-
}
|
409
|
-
// Make sure that the fromRef is actually resolvable
|
410
|
-
const fromSHA = await (0, git_1.getCommitHash)(fromRef);
|
411
|
-
const { fileMap } = await (0, file_map_utils_1.createFileMapUsingProjectGraph)(projectGraph);
|
412
|
-
const fileToProjectMap = createFileToProjectMap(fileMap.projectFileMap);
|
413
|
-
commits = await getCommits(fromSHA, toSHA);
|
414
|
-
changes = filterHiddenChanges(commits.map((c) => ({
|
415
|
-
type: c.type,
|
416
|
-
scope: c.scope,
|
417
|
-
description: c.description,
|
418
|
-
body: c.body,
|
419
|
-
isBreaking: c.isBreaking,
|
420
|
-
githubReferences: c.references,
|
421
|
-
author: c.author,
|
422
|
-
shortHash: c.shortHash,
|
423
|
-
revertedHashes: c.revertedHashes,
|
424
|
-
affectedProjects: commitChangesNonProjectFiles(c, fileMap.nonProjectFiles)
|
425
|
-
? '*'
|
426
|
-
: getProjectsAffectedByCommit(c, fileToProjectMap),
|
427
|
-
})), nxReleaseConfig.conventionalCommits);
|
428
|
-
}
|
429
|
-
const projectChangelogs = await generateChangelogForProjects({
|
430
|
-
tree,
|
431
|
-
args,
|
432
|
-
projectGraph,
|
433
|
-
changes,
|
434
|
-
projectsVersionData,
|
435
|
-
releaseGroup,
|
436
|
-
projects: projectNodes,
|
437
|
-
nxReleaseConfig,
|
438
|
-
projectToAdditionalDependencyBumps,
|
439
|
-
// TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
|
440
|
-
commits: filterHiddenCommits(commits, nxReleaseConfig.conventionalCommits),
|
441
|
-
});
|
442
|
-
let hasPushed = false;
|
443
|
-
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
444
|
-
if (projectChangelogs &&
|
445
|
-
shouldCreateGitHubRelease(releaseGroup.changelog, args.createRelease)) {
|
446
|
-
postGitTasks.push(async (latestCommit) => {
|
447
|
-
if (!hasPushed) {
|
448
|
-
output_1.output.logSingleLine(`Pushing to git remote`);
|
449
|
-
// Before we can create/update the release we need to ensure the commit exists on the remote
|
450
|
-
await (0, git_1.gitPush)({
|
451
|
-
gitRemote: args.gitRemote,
|
452
|
-
dryRun: args.dryRun,
|
453
|
-
verbose: args.verbose,
|
454
|
-
});
|
455
|
-
hasPushed = true;
|
456
|
-
}
|
457
|
-
output_1.output.logSingleLine(`Creating GitHub Release`);
|
458
|
-
await (0, github_1.createOrUpdateGithubRelease)(projectChangelog.releaseVersion, projectChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
459
|
-
});
|
460
|
-
}
|
461
|
-
allProjectChangelogs[projectName] = projectChangelog;
|
462
|
-
}
|
463
|
-
}
|
464
|
-
}
|
465
|
-
await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues, releaseGroups);
|
466
|
-
return {
|
467
|
-
workspaceChangelog,
|
468
|
-
projectChangelogs: allProjectChangelogs,
|
478
|
+
await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues, releaseGroups);
|
479
|
+
return {
|
480
|
+
workspaceChangelog,
|
481
|
+
projectChangelogs: allProjectChangelogs,
|
482
|
+
};
|
469
483
|
};
|
470
484
|
}
|
471
485
|
function resolveChangelogVersions(args, releaseGroups, releaseGroupToFilteredProjects) {
|