nx 19.1.0-canary.20240522-89fdd42 → 19.1.0-canary.20240524-12c6a73
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/init-local.js +1 -1
- package/package.json +17 -13
- package/release/changelog-renderer/index.d.ts +11 -0
- package/release/changelog-renderer/index.js +40 -3
- package/schemas/nx-schema.json +1 -1
- package/src/command-line/format/format.js +47 -25
- package/src/command-line/init/implementation/angular/legacy-angular-versions.js +2 -1
- package/src/command-line/init/implementation/angular/standalone-workspace.js +0 -2
- package/src/command-line/init/implementation/react/index.js +1 -0
- package/src/command-line/release/changelog.js +67 -22
- package/src/command-line/release/publish.js +2 -0
- package/src/command-line/release/utils/git.js +8 -1
- package/src/command-line/release/utils/shared.d.ts +4 -0
- package/src/command-line/release/version.d.ts +5 -0
- package/src/command-line/release/version.js +6 -2
- package/src/core/graph/main.js +1 -1
- package/src/generators/tree.d.ts +0 -1
- package/src/plugins/js/index.js +7 -2
- package/src/plugins/js/lock-file/lock-file.js +31 -1
- package/src/project-graph/utils/project-configuration-utils.js +4 -0
- package/src/project-graph/utils/retrieve-workspace-files.d.ts +3 -3
- package/src/utils/ab-testing.js +5 -0
- package/src/utils/fileutils.d.ts +0 -1
- package/src/utils/package-json.d.ts +2 -1
- package/src/utils/package-json.js +4 -4
- package/src/utils/package-manager.d.ts +2 -2
- package/src/utils/package-manager.js +40 -8
package/bin/init-local.js
CHANGED
@@ -132,7 +132,7 @@ function handleAngularCLIFallbacks(workspace) {
|
|
132
132
|
else if (process.argv[2] === 'cache') {
|
133
133
|
console.log(`"ng cache" is not natively supported by Nx.
|
134
134
|
To clear the cache, you can delete the ".angular/cache" directory (or the directory configured by "cli.cache.path" in the "nx.json" file).
|
135
|
-
To update the cache configuration, you can directly update the relevant options in your "nx.json" file (https://angular.
|
135
|
+
To update the cache configuration, you can directly update the relevant options in your "nx.json" file (https://angular.dev/reference/configs/workspace-config#cache-options).`);
|
136
136
|
}
|
137
137
|
else {
|
138
138
|
try {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "19.1.0-canary.
|
3
|
+
"version": "19.1.0-canary.20240524-12c6a73",
|
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": {
|
@@ -20,7 +20,11 @@
|
|
20
20
|
"Nest",
|
21
21
|
"Jest",
|
22
22
|
"Cypress",
|
23
|
-
"CLI"
|
23
|
+
"CLI",
|
24
|
+
"Testing",
|
25
|
+
"Front-end",
|
26
|
+
"Backend",
|
27
|
+
"Mobile"
|
24
28
|
],
|
25
29
|
"bin": {
|
26
30
|
"nx": "./bin/nx.js",
|
@@ -65,7 +69,7 @@
|
|
65
69
|
"yargs-parser": "21.1.1",
|
66
70
|
"node-machine-id": "1.1.12",
|
67
71
|
"ora": "5.3.0",
|
68
|
-
"@nrwl/tao": "19.1.0-canary.
|
72
|
+
"@nrwl/tao": "19.1.0-canary.20240524-12c6a73"
|
69
73
|
},
|
70
74
|
"peerDependencies": {
|
71
75
|
"@swc-node/register": "^1.8.0",
|
@@ -80,16 +84,16 @@
|
|
80
84
|
}
|
81
85
|
},
|
82
86
|
"optionalDependencies": {
|
83
|
-
"@nx/nx-darwin-x64": "19.1.0-canary.
|
84
|
-
"@nx/nx-darwin-arm64": "19.1.0-canary.
|
85
|
-
"@nx/nx-linux-x64-gnu": "19.1.0-canary.
|
86
|
-
"@nx/nx-linux-x64-musl": "19.1.0-canary.
|
87
|
-
"@nx/nx-win32-x64-msvc": "19.1.0-canary.
|
88
|
-
"@nx/nx-linux-arm64-gnu": "19.1.0-canary.
|
89
|
-
"@nx/nx-linux-arm64-musl": "19.1.0-canary.
|
90
|
-
"@nx/nx-linux-arm-gnueabihf": "19.1.0-canary.
|
91
|
-
"@nx/nx-win32-arm64-msvc": "19.1.0-canary.
|
92
|
-
"@nx/nx-freebsd-x64": "19.1.0-canary.
|
87
|
+
"@nx/nx-darwin-x64": "19.1.0-canary.20240524-12c6a73",
|
88
|
+
"@nx/nx-darwin-arm64": "19.1.0-canary.20240524-12c6a73",
|
89
|
+
"@nx/nx-linux-x64-gnu": "19.1.0-canary.20240524-12c6a73",
|
90
|
+
"@nx/nx-linux-x64-musl": "19.1.0-canary.20240524-12c6a73",
|
91
|
+
"@nx/nx-win32-x64-msvc": "19.1.0-canary.20240524-12c6a73",
|
92
|
+
"@nx/nx-linux-arm64-gnu": "19.1.0-canary.20240524-12c6a73",
|
93
|
+
"@nx/nx-linux-arm64-musl": "19.1.0-canary.20240524-12c6a73",
|
94
|
+
"@nx/nx-linux-arm-gnueabihf": "19.1.0-canary.20240524-12c6a73",
|
95
|
+
"@nx/nx-win32-arm64-msvc": "19.1.0-canary.20240524-12c6a73",
|
96
|
+
"@nx/nx-freebsd-x64": "19.1.0-canary.20240524-12c6a73"
|
93
97
|
},
|
94
98
|
"nx-migrations": {
|
95
99
|
"migrations": "./migrations.json",
|
@@ -7,6 +7,15 @@ import type { ProjectGraph } from '../../src/config/project-graph';
|
|
7
7
|
* from the user's nx.json configuration and passed as is into the ChangelogRenderer function.
|
8
8
|
*/
|
9
9
|
export type ChangelogRenderOptions = Record<string, unknown>;
|
10
|
+
/**
|
11
|
+
* When versioning projects independently and enabling `"updateDependents": "always"`, there could
|
12
|
+
* be additional dependency bump information that is not captured in the commit data, but that nevertheless
|
13
|
+
* should be included in the rendered changelog.
|
14
|
+
*/
|
15
|
+
export type DependencyBump = {
|
16
|
+
dependencyName: string;
|
17
|
+
newVersion: string;
|
18
|
+
};
|
10
19
|
/**
|
11
20
|
* A ChangelogRenderer function takes in the extracted commits and other relevant metadata
|
12
21
|
* and returns a string, or a Promise of a string of changelog contents (usually markdown).
|
@@ -18,6 +27,7 @@ export type ChangelogRenderOptions = Record<string, unknown>;
|
|
18
27
|
* @param {string | null} config.project The name of specific project to generate a changelog for, or `null` if the overall workspace changelog
|
19
28
|
* @param {string | false} config.entryWhenNoChanges The (already interpolated) string to use as the changelog entry when there are no changes, or `false` if no entry should be generated
|
20
29
|
* @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
|
30
|
+
* @param {DependencyBump[]} config.dependencyBumps Optional list of additional dependency bumps that occurred as part of the release, outside of the commit data
|
21
31
|
*/
|
22
32
|
export type ChangelogRenderer = (config: {
|
23
33
|
projectGraph: ProjectGraph;
|
@@ -26,6 +36,7 @@ export type ChangelogRenderer = (config: {
|
|
26
36
|
project: string | null;
|
27
37
|
entryWhenNoChanges: string | false;
|
28
38
|
changelogRenderOptions: DefaultChangelogRenderOptions;
|
39
|
+
dependencyBumps?: DependencyBump[];
|
29
40
|
repoSlug?: RepoSlug;
|
30
41
|
conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'];
|
31
42
|
}) => Promise<string> | string;
|
@@ -10,7 +10,7 @@ const axios = _axios;
|
|
10
10
|
* The default ChangelogRenderer implementation that nx exports for the common case of generating markdown
|
11
11
|
* from the given commits and other metadata.
|
12
12
|
*/
|
13
|
-
const defaultChangelogRenderer = async ({ projectGraph, commits, releaseVersion, project, entryWhenNoChanges, changelogRenderOptions, repoSlug, conventionalCommitsConfig, }) => {
|
13
|
+
const defaultChangelogRenderer = async ({ projectGraph, commits, releaseVersion, project, entryWhenNoChanges, changelogRenderOptions, dependencyBumps, repoSlug, conventionalCommitsConfig, }) => {
|
14
14
|
const commitTypes = conventionalCommitsConfig.types;
|
15
15
|
const markdownLines = [];
|
16
16
|
const breakingChanges = [];
|
@@ -30,7 +30,15 @@ const defaultChangelogRenderer = async ({ projectGraph, commits, releaseVersion,
|
|
30
30
|
if (project === null) {
|
31
31
|
// No changes for the workspace
|
32
32
|
if (commits.length === 0) {
|
33
|
-
if (
|
33
|
+
if (dependencyBumps?.length) {
|
34
|
+
applyAdditionalDependencyBumps({
|
35
|
+
markdownLines,
|
36
|
+
dependencyBumps,
|
37
|
+
releaseVersion,
|
38
|
+
changelogRenderOptions,
|
39
|
+
});
|
40
|
+
}
|
41
|
+
else if (entryWhenNoChanges) {
|
34
42
|
markdownLines.push('', `${createVersionTitle(releaseVersion, changelogRenderOptions)}\n\n${entryWhenNoChanges}`, '');
|
35
43
|
}
|
36
44
|
return markdownLines.join('\n').trim();
|
@@ -71,7 +79,15 @@ const defaultChangelogRenderer = async ({ projectGraph, commits, releaseVersion,
|
|
71
79
|
const relevantCommits = await (0, shared_1.getCommitsRelevantToProjects)(projectGraph, commits, [project]);
|
72
80
|
// Generating for a named project, but that project has no relevant changes in the current set of commits, exit early
|
73
81
|
if (relevantCommits.length === 0) {
|
74
|
-
if (
|
82
|
+
if (dependencyBumps?.length) {
|
83
|
+
applyAdditionalDependencyBumps({
|
84
|
+
markdownLines,
|
85
|
+
dependencyBumps,
|
86
|
+
releaseVersion,
|
87
|
+
changelogRenderOptions,
|
88
|
+
});
|
89
|
+
}
|
90
|
+
else if (entryWhenNoChanges) {
|
75
91
|
markdownLines.push('', `${createVersionTitle(releaseVersion, changelogRenderOptions)}\n\n${entryWhenNoChanges}`, '');
|
76
92
|
}
|
77
93
|
return markdownLines.join('\n').trim();
|
@@ -102,6 +118,14 @@ const defaultChangelogRenderer = async ({ projectGraph, commits, releaseVersion,
|
|
102
118
|
if (breakingChanges.length > 0) {
|
103
119
|
markdownLines.push('', '#### ⚠️ Breaking Changes', '', ...breakingChanges);
|
104
120
|
}
|
121
|
+
if (dependencyBumps?.length) {
|
122
|
+
applyAdditionalDependencyBumps({
|
123
|
+
markdownLines,
|
124
|
+
dependencyBumps,
|
125
|
+
releaseVersion,
|
126
|
+
changelogRenderOptions,
|
127
|
+
});
|
128
|
+
}
|
105
129
|
if (changelogRenderOptions.authors) {
|
106
130
|
const _authors = new Map();
|
107
131
|
for (const commit of commits) {
|
@@ -163,6 +187,19 @@ const defaultChangelogRenderer = async ({ projectGraph, commits, releaseVersion,
|
|
163
187
|
return markdownLines.join('\n').trim();
|
164
188
|
};
|
165
189
|
exports.default = defaultChangelogRenderer;
|
190
|
+
function applyAdditionalDependencyBumps({ markdownLines, dependencyBumps, releaseVersion, changelogRenderOptions, }) {
|
191
|
+
if (markdownLines.length === 0) {
|
192
|
+
markdownLines.push('', `${createVersionTitle(releaseVersion, changelogRenderOptions)}\n`, '');
|
193
|
+
}
|
194
|
+
else {
|
195
|
+
markdownLines.push('');
|
196
|
+
}
|
197
|
+
markdownLines.push('### 🧱 Updated Dependencies\n');
|
198
|
+
dependencyBumps.forEach(({ dependencyName, newVersion }) => {
|
199
|
+
markdownLines.push(`- Updated ${dependencyName} to ${newVersion}`);
|
200
|
+
});
|
201
|
+
markdownLines.push('');
|
202
|
+
}
|
166
203
|
function formatName(name = '') {
|
167
204
|
return name
|
168
205
|
.split(' ')
|
package/schemas/nx-schema.json
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.format = void 0;
|
4
|
-
const
|
5
|
-
const path = require("path");
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
5
|
+
const path = require("node:path");
|
6
|
+
const file_utils_1 = require("../../project-graph/file-utils");
|
6
7
|
const command_line_utils_1 = require("../../utils/command-line-utils");
|
7
|
-
const ignore_1 = require("../../utils/ignore");
|
8
8
|
const fileutils_1 = require("../../utils/fileutils");
|
9
|
-
const
|
9
|
+
const ignore_1 = require("../../utils/ignore");
|
10
10
|
const prettier = require("prettier");
|
11
|
-
const
|
12
|
-
const package_json_1 = require("../../utils/package-json");
|
11
|
+
const configuration_1 = require("../../config/configuration");
|
13
12
|
const typescript_1 = require("../../plugins/js/utils/typescript");
|
14
|
-
const project_graph_1 = require("../../project-graph/project-graph");
|
15
13
|
const affected_project_graph_1 = require("../../project-graph/affected/affected-project-graph");
|
16
|
-
const
|
17
|
-
const chunkify_1 = require("../../utils/chunkify");
|
14
|
+
const project_graph_1 = require("../../project-graph/project-graph");
|
18
15
|
const all_file_data_1 = require("../../utils/all-file-data");
|
19
|
-
const
|
16
|
+
const chunkify_1 = require("../../utils/chunkify");
|
17
|
+
const object_sort_1 = require("../../utils/object-sort");
|
20
18
|
const output_1 = require("../../utils/output");
|
19
|
+
const package_json_1 = require("../../utils/package-json");
|
20
|
+
const workspace_root_1 = require("../../utils/workspace-root");
|
21
21
|
const PRETTIER_PATH = getPrettierPath();
|
22
22
|
async function format(command, args) {
|
23
23
|
const { nxArgs } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'affected', { printWarnings: false }, (0, configuration_1.readNxJson)());
|
@@ -33,12 +33,31 @@ async function format(command, args) {
|
|
33
33
|
addRootConfigFiles(chunkList, nxArgs);
|
34
34
|
chunkList.forEach((chunk) => write(chunk));
|
35
35
|
break;
|
36
|
-
case 'check':
|
37
|
-
const
|
38
|
-
|
36
|
+
case 'check': {
|
37
|
+
const filesWithDifferentFormatting = [];
|
38
|
+
for (const chunk of chunkList) {
|
39
|
+
const files = await check(chunk);
|
40
|
+
filesWithDifferentFormatting.push(...files);
|
41
|
+
}
|
42
|
+
if (filesWithDifferentFormatting.length > 0) {
|
43
|
+
if (nxArgs.verbose) {
|
44
|
+
output_1.output.error({
|
45
|
+
title: 'The following files are not formatted correctly based on your Prettier configuration',
|
46
|
+
bodyLines: [
|
47
|
+
'- Run "nx format:write" and commit the resulting diff to fix these files.',
|
48
|
+
'- Please note, Prettier does not support a native way to diff the output of its check logic (https://github.com/prettier/prettier/issues/6885).',
|
49
|
+
'',
|
50
|
+
...filesWithDifferentFormatting,
|
51
|
+
],
|
52
|
+
});
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
console.log(filesWithDifferentFormatting.join('\n'));
|
56
|
+
}
|
39
57
|
process.exit(1);
|
40
58
|
}
|
41
59
|
break;
|
60
|
+
}
|
42
61
|
}
|
43
62
|
}
|
44
63
|
exports.format = format;
|
@@ -113,29 +132,32 @@ function write(patterns) {
|
|
113
132
|
result[pattern.includes('.swcrc') ? 0 : 1].push(pattern);
|
114
133
|
return result;
|
115
134
|
}, [[], []]);
|
116
|
-
(0,
|
135
|
+
(0, node_child_process_1.execSync)(`node "${PRETTIER_PATH}" --write --list-different ${regularPatterns.join(' ')}`, {
|
117
136
|
stdio: [0, 1, 2],
|
118
137
|
});
|
119
138
|
if (swcrcPatterns.length > 0) {
|
120
|
-
(0,
|
139
|
+
(0, node_child_process_1.execSync)(`node "${PRETTIER_PATH}" --write --list-different ${swcrcPatterns.join(' ')} --parser json`, {
|
121
140
|
stdio: [0, 1, 2],
|
122
141
|
});
|
123
142
|
}
|
124
143
|
}
|
125
144
|
}
|
126
|
-
function check(patterns) {
|
145
|
+
async function check(patterns) {
|
127
146
|
if (patterns.length === 0) {
|
128
|
-
return
|
147
|
+
return [];
|
129
148
|
}
|
130
|
-
|
131
|
-
(0,
|
132
|
-
|
149
|
+
return new Promise((resolve) => {
|
150
|
+
(0, node_child_process_1.exec)(`node "${PRETTIER_PATH}" --list-different ${patterns.join(' ')}`, { encoding: 'utf-8' }, (error, stdout) => {
|
151
|
+
if (error) {
|
152
|
+
// The command failed so there are files with different formatting. Prettier writes them to stdout, newline separated.
|
153
|
+
resolve(stdout.trim().split('\n'));
|
154
|
+
}
|
155
|
+
else {
|
156
|
+
// The command succeeded so there are no files with different formatting
|
157
|
+
resolve([]);
|
158
|
+
}
|
133
159
|
});
|
134
|
-
|
135
|
-
}
|
136
|
-
catch {
|
137
|
-
return false;
|
138
|
-
}
|
160
|
+
});
|
139
161
|
}
|
140
162
|
function sortTsConfig() {
|
141
163
|
try {
|
@@ -15,9 +15,10 @@ const connect_to_nx_cloud_1 = require("../../../connect/connect-to-nx-cloud");
|
|
15
15
|
// key is major Angular version and value is Nx version to use
|
16
16
|
const nxAngularLegacyVersionMap = {
|
17
17
|
14: '~17.0.0',
|
18
|
+
15: '~19.0.0',
|
18
19
|
};
|
19
20
|
// min major angular version supported in latest Nx
|
20
|
-
const minMajorAngularVersionSupported =
|
21
|
+
const minMajorAngularVersionSupported = 16;
|
21
22
|
// version when the Nx CLI changed from @nrwl/tao & @nrwl/cli to nx
|
22
23
|
const versionWithConsolidatedPackages = '13.9.0';
|
23
24
|
// version when packages were rescoped from @nrwl/* to @nx/*
|
@@ -98,8 +98,6 @@ function createNxJson(repoRoot, angularJson, cacheableOperations, { eslintProjec
|
|
98
98
|
inputs: ['default', '^production'],
|
99
99
|
};
|
100
100
|
}
|
101
|
-
// Angular 15 workspaces still support defaultProject. Support was removed in Angular 16.
|
102
|
-
nxJson.defaultProject = angularJson.defaultProject;
|
103
101
|
(0, fileutils_1.writeJsonFile)((0, path_1.join)(repoRoot, 'nx.json'), nxJson);
|
104
102
|
}
|
105
103
|
function updateProjectOutputs(repoRoot, project) {
|
@@ -155,6 +155,7 @@ function moveFilesToTempWorkspace(options) {
|
|
155
155
|
options.packageManager === 'yarn' ? 'yarn.lock' : null,
|
156
156
|
options.packageManager === 'pnpm' ? 'pnpm-lock.yaml' : null,
|
157
157
|
options.packageManager === 'npm' ? 'package-lock.json' : null,
|
158
|
+
options.packageManager === 'bun' ? 'bun.lockb' : null,
|
158
159
|
];
|
159
160
|
const optionalCraFiles = ['README.md'];
|
160
161
|
const filesToMove = [...requiredCraFiles, ...optionalCraFiles].filter(Boolean);
|
@@ -120,7 +120,7 @@ async function releaseChangelog(args) {
|
|
120
120
|
if (useAutomaticFromRef) {
|
121
121
|
workspaceChangelogFromRef = await (0, git_1.getFirstGitCommit)();
|
122
122
|
if (args.verbose) {
|
123
|
-
console.log(`Determined workspace --from ref from the first commit in workspace: ${workspaceChangelogFromRef}`);
|
123
|
+
console.log(`Determined workspace --from ref from the first commit in the workspace: ${workspaceChangelogFromRef}`);
|
124
124
|
}
|
125
125
|
}
|
126
126
|
else {
|
@@ -149,6 +149,30 @@ async function releaseChangelog(args) {
|
|
149
149
|
await (0, github_1.createOrUpdateGithubRelease)(workspaceChangelog.releaseVersion, workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
150
150
|
});
|
151
151
|
}
|
152
|
+
/**
|
153
|
+
* Compute any additional dependency bumps up front because there could be cases of circular dependencies,
|
154
|
+
* and figuring them out during the main iteration would be too late.
|
155
|
+
*/
|
156
|
+
const projectToAdditionalDependencyBumps = new Map();
|
157
|
+
for (const releaseGroup of releaseGroups) {
|
158
|
+
if (releaseGroup.projectsRelationship !== 'independent') {
|
159
|
+
continue;
|
160
|
+
}
|
161
|
+
for (const project of releaseGroup.projects) {
|
162
|
+
if (projectToAdditionalDependencyBumps.has(project)) {
|
163
|
+
continue;
|
164
|
+
}
|
165
|
+
const dependentProjects = (projectsVersionData[project]?.dependentProjects || [])
|
166
|
+
.map((dep) => {
|
167
|
+
return {
|
168
|
+
dependencyName: dep.source,
|
169
|
+
newVersion: projectsVersionData[dep.source].newVersion,
|
170
|
+
};
|
171
|
+
})
|
172
|
+
.filter((b) => b.newVersion !== null);
|
173
|
+
projectToAdditionalDependencyBumps.set(project, dependentProjects);
|
174
|
+
}
|
175
|
+
}
|
152
176
|
const allProjectChangelogs = {};
|
153
177
|
for (const releaseGroup of releaseGroups) {
|
154
178
|
const config = releaseGroup.changelog;
|
@@ -157,8 +181,13 @@ async function releaseChangelog(args) {
|
|
157
181
|
continue;
|
158
182
|
}
|
159
183
|
const projects = args.projects?.length
|
160
|
-
? // If the user has passed a list of projects, we need to use the filtered list of projects within the release group
|
161
|
-
Array.from(releaseGroupToFilteredProjects.get(releaseGroup))
|
184
|
+
? // 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
|
185
|
+
Array.from(releaseGroupToFilteredProjects.get(releaseGroup)).flatMap((project) => {
|
186
|
+
return [
|
187
|
+
project,
|
188
|
+
...(projectToAdditionalDependencyBumps.get(project) || []).map((d) => d.dependencyName),
|
189
|
+
];
|
190
|
+
})
|
162
191
|
: // Otherwise, we use the full list of projects within the release group
|
163
192
|
releaseGroup.projects;
|
164
193
|
const projectNodes = projects.map((name) => projectGraph.nodes[name]);
|
@@ -171,13 +200,14 @@ async function releaseChangelog(args) {
|
|
171
200
|
let commits = null;
|
172
201
|
if (!fromRef && useAutomaticFromRef) {
|
173
202
|
const firstCommit = await (0, git_1.getFirstGitCommit)();
|
174
|
-
const
|
175
|
-
const
|
203
|
+
const allRawCommits = await (0, git_1.getGitDiff)(firstCommit, toSHA);
|
204
|
+
const allParsedCommits = (0, git_1.parseCommits)(allRawCommits);
|
205
|
+
const commitsForProject = allParsedCommits.filter((c) => c.affectedFiles.find((f) => f.startsWith(project.data.root)));
|
176
206
|
fromRef = commitsForProject[0]?.shortHash;
|
177
207
|
if (args.verbose) {
|
178
208
|
console.log(`Determined --from ref for ${project.name} from the first commit in which it exists: ${fromRef}`);
|
179
209
|
}
|
180
|
-
commits = commitsForProject;
|
210
|
+
commits = commitsForProject.filter((c) => applyConventionalCommitsConfigFilter(c, nxReleaseConfig.conventionalCommits));
|
181
211
|
}
|
182
212
|
if (!fromRef && !commits) {
|
183
213
|
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.`);
|
@@ -185,7 +215,7 @@ async function releaseChangelog(args) {
|
|
185
215
|
if (!commits) {
|
186
216
|
commits = await getCommits(fromRef, toSHA, nxReleaseConfig.conventionalCommits);
|
187
217
|
}
|
188
|
-
const projectChangelogs = await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, releaseGroup, [project], nxReleaseConfig);
|
218
|
+
const projectChangelogs = await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, releaseGroup, [project], nxReleaseConfig, projectToAdditionalDependencyBumps);
|
189
219
|
let hasPushed = false;
|
190
220
|
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
191
221
|
if (projectChangelogs &&
|
@@ -210,15 +240,23 @@ async function releaseChangelog(args) {
|
|
210
240
|
}
|
211
241
|
}
|
212
242
|
else {
|
213
|
-
|
243
|
+
let fromRef = args.from ||
|
214
244
|
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern))?.tag;
|
215
245
|
if (!fromRef) {
|
216
|
-
|
246
|
+
if (useAutomaticFromRef) {
|
247
|
+
fromRef = await (0, git_1.getFirstGitCommit)();
|
248
|
+
if (args.verbose) {
|
249
|
+
console.log(`Determined release group --from ref from the first commit in the workspace: ${fromRef}`);
|
250
|
+
}
|
251
|
+
}
|
252
|
+
else {
|
253
|
+
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.`);
|
254
|
+
}
|
217
255
|
}
|
218
256
|
// Make sure that the fromRef is actually resolvable
|
219
257
|
const fromSHA = await (0, git_1.getCommitHash)(fromRef);
|
220
258
|
const commits = await getCommits(fromSHA, toSHA, nxReleaseConfig.conventionalCommits);
|
221
|
-
const projectChangelogs = await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, releaseGroup, projectNodes, nxReleaseConfig);
|
259
|
+
const projectChangelogs = await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, releaseGroup, projectNodes, nxReleaseConfig, projectToAdditionalDependencyBumps);
|
222
260
|
let hasPushed = false;
|
223
261
|
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
224
262
|
if (projectChangelogs &&
|
@@ -377,7 +415,7 @@ async function generateChangelogForWorkspace(tree, args, projectGraph, nxRelease
|
|
377
415
|
output_1.output.warn({
|
378
416
|
title: `Workspace changelog is enabled, but you have multiple release groups configured. This is not supported, so workspace changelog will be disabled.`,
|
379
417
|
bodyLines: [
|
380
|
-
`A single workspace version cannot be determined when defining multiple release groups because versions differ between each group.`,
|
418
|
+
`A single workspace version cannot be determined when defining multiple release groups because versions can differ between each group.`,
|
381
419
|
`Project level changelogs can be enabled with the "release.changelog.projectChangelogs" property.`,
|
382
420
|
],
|
383
421
|
});
|
@@ -388,7 +426,7 @@ async function generateChangelogForWorkspace(tree, args, projectGraph, nxRelease
|
|
388
426
|
output_1.output.warn({
|
389
427
|
title: `Workspace changelog is enabled, but you have configured an independent projects relationship. This is not supported, so workspace changelog will be disabled.`,
|
390
428
|
bodyLines: [
|
391
|
-
`A single workspace version cannot be determined when using independent projects because versions differ between each project.`,
|
429
|
+
`A single workspace version cannot be determined when using independent projects because versions can differ between each project.`,
|
392
430
|
`Project level changelogs can be enabled with the "release.changelog.projectChangelogs" property.`,
|
393
431
|
],
|
394
432
|
});
|
@@ -469,7 +507,7 @@ async function generateChangelogForWorkspace(tree, args, projectGraph, nxRelease
|
|
469
507
|
contents,
|
470
508
|
};
|
471
509
|
}
|
472
|
-
async function generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, releaseGroup, projects, nxReleaseConfig) {
|
510
|
+
async function generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, releaseGroup, projects, nxReleaseConfig, projectToAdditionalDependencyBumps) {
|
473
511
|
const config = releaseGroup.changelog;
|
474
512
|
// The entire feature is disabled at the release group level, exit early
|
475
513
|
if (config === false) {
|
@@ -526,6 +564,7 @@ async function generateChangelogForProjects(tree, args, projectGraph, commits, p
|
|
526
564
|
: false,
|
527
565
|
changelogRenderOptions: config.renderOptions,
|
528
566
|
conventionalCommitsConfig: nxReleaseConfig.conventionalCommits,
|
567
|
+
dependencyBumps: projectToAdditionalDependencyBumps.get(project.name),
|
529
568
|
});
|
530
569
|
/**
|
531
570
|
* If interactive mode, make the changelog contents available for the user to modify in their editor of choice,
|
@@ -587,15 +626,21 @@ function checkChangelogFilesEnabled(nxReleaseConfig) {
|
|
587
626
|
async function getCommits(fromSHA, toSHA, conventionalCommitsConfig) {
|
588
627
|
const rawCommits = await (0, git_1.getGitDiff)(fromSHA, toSHA);
|
589
628
|
// Parse as conventional commits
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
629
|
+
const parsedCommits = (0, git_1.parseCommits)(rawCommits);
|
630
|
+
if (conventionalCommitsConfig === null) {
|
631
|
+
return parsedCommits;
|
632
|
+
}
|
633
|
+
// Apply filtering based on the conventional commits configuration
|
634
|
+
return parsedCommits.filter((c) => applyConventionalCommitsConfigFilter(c, conventionalCommitsConfig));
|
635
|
+
}
|
636
|
+
function applyConventionalCommitsConfigFilter(commit, conventionalCommitsConfig) {
|
637
|
+
const type = commit.type;
|
638
|
+
const typeConfig = conventionalCommitsConfig.types[type];
|
639
|
+
if (!typeConfig) {
|
640
|
+
// don't include commits with unknown types
|
641
|
+
return false;
|
642
|
+
}
|
643
|
+
return !typeConfig.changelog.hidden;
|
599
644
|
}
|
600
645
|
function shouldCreateGitHubRelease(changelogConfig, createReleaseArg = undefined) {
|
601
646
|
if (createReleaseArg !== undefined) {
|
@@ -137,6 +137,8 @@ async function runPublishOnProjects(args, projectGraph, nxJson, projectNames, is
|
|
137
137
|
targets: [requiredTargetName],
|
138
138
|
outputStyle: 'static',
|
139
139
|
...args,
|
140
|
+
// It is possible for workspaces to have circular dependencies between packages and still release them to a registry
|
141
|
+
nxIgnoreCycles: true,
|
140
142
|
}, overrides, null, {}, extraOptions);
|
141
143
|
if (status !== 0) {
|
142
144
|
// In order to not add noise to the overall CLI output, do not throw an additional error
|
@@ -66,11 +66,18 @@ async function getLatestGitTagForPattern(releaseTagPattern, additionalInterpolat
|
|
66
66
|
}
|
67
67
|
exports.getLatestGitTagForPattern = getLatestGitTagForPattern;
|
68
68
|
async function getGitDiff(from, to = 'HEAD') {
|
69
|
+
let range = '';
|
70
|
+
if (!from || from === to) {
|
71
|
+
range = to;
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
range = `${from}..${to}`;
|
75
|
+
}
|
69
76
|
// https://git-scm.com/docs/pretty-formats
|
70
77
|
const r = await (0, exec_command_1.execCommand)('git', [
|
71
78
|
'--no-pager',
|
72
79
|
'log',
|
73
|
-
|
80
|
+
range,
|
74
81
|
'--pretty="----%n%s|%h|%an|%ae%n%b"',
|
75
82
|
'--name-status',
|
76
83
|
]);
|
@@ -18,6 +18,10 @@ export type VersionData = Record<string, {
|
|
18
18
|
*/
|
19
19
|
newVersion: string | null;
|
20
20
|
currentVersion: string;
|
21
|
+
/**
|
22
|
+
* The list of projects which depend upon the current project.
|
23
|
+
* TODO: investigate generic type for this once more ecosystems are explored
|
24
|
+
*/
|
21
25
|
dependentProjects: any[];
|
22
26
|
}>;
|
23
27
|
export declare class ReleaseVersion {
|
@@ -23,6 +23,11 @@ export interface ReleaseVersionGeneratorSchema {
|
|
23
23
|
installArgs?: string;
|
24
24
|
installIgnoreScripts?: boolean;
|
25
25
|
conventionalCommitsConfig?: NxReleaseConfig['conventionalCommits'];
|
26
|
+
/**
|
27
|
+
* 'auto' allows users to opt into dependents being updated (a patch version bump) when a dependency is versioned.
|
28
|
+
* This is only applicable to independently released projects.
|
29
|
+
*/
|
30
|
+
updateDependents?: 'never' | 'auto';
|
26
31
|
}
|
27
32
|
export interface NxReleaseVersionResult {
|
28
33
|
/**
|
@@ -76,8 +76,12 @@ async function releaseVersion(args) {
|
|
76
76
|
const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
|
77
77
|
const versionData = {};
|
78
78
|
const commitMessage = args.gitCommitMessage || nxReleaseConfig.version.git.commitMessage;
|
79
|
-
const additionalChangedFiles = new Set();
|
80
79
|
const generatorCallbacks = [];
|
80
|
+
/**
|
81
|
+
* additionalChangedFiles are files which need to be updated as a side-effect of versioning (such as package manager lock files),
|
82
|
+
* and need to get staged and committed as part of the existing commit, if applicable.
|
83
|
+
*/
|
84
|
+
const additionalChangedFiles = new Set();
|
81
85
|
if (args.projects?.length) {
|
82
86
|
/**
|
83
87
|
* Run versioning for all remaining release groups and filtered projects within them
|
@@ -256,7 +260,7 @@ function appendVersionData(existingVersionData, newVersionData) {
|
|
256
260
|
// Mutate the existing version data
|
257
261
|
for (const [key, value] of Object.entries(newVersionData)) {
|
258
262
|
if (existingVersionData[key]) {
|
259
|
-
throw new Error(`Version data key "${key}" already exists in version data. This is likely a bug
|
263
|
+
throw new Error(`Version data key "${key}" already exists in version data. This is likely a bug, please report your use-case on https://github.com/nrwl/nx`);
|
260
264
|
}
|
261
265
|
existingVersionData[key] = value;
|
262
266
|
}
|