nx 17.2.8 → 17.3.0-beta.2
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/README.md +9 -4
- package/package.json +12 -12
- package/src/adapter/ngcli-adapter.d.ts +13 -2
- package/src/adapter/ngcli-adapter.js +34 -6
- package/src/command-line/connect/command-object.d.ts +1 -2
- package/src/command-line/connect/command-object.js +3 -7
- package/src/command-line/connect/connect-to-nx-cloud.d.ts +2 -5
- package/src/command-line/connect/connect-to-nx-cloud.js +3 -5
- package/src/command-line/init/implementation/add-nx-to-nest.js +0 -1
- package/src/command-line/init/implementation/angular/index.js +1 -0
- package/src/command-line/migrate/migrate.js +2 -4
- package/src/command-line/nx-commands.js +1 -1
- package/src/command-line/release/changelog.js +76 -34
- package/src/command-line/release/utils/github.js +64 -1
- package/src/command-line/release/utils/shared.js +14 -10
- package/src/command-line/release/version.js +17 -0
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/polyfills.js +1 -1
- package/src/native/index.d.ts +1 -0
- package/src/project-graph/project-graph.js +1 -1
- package/src/utils/workspace-context.d.ts +1 -0
- package/src/utils/workspace-context.js +6 -1
package/README.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
<p style="text-align: center;"
|
|
1
|
+
<p style="text-align: center;">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
|
|
4
|
+
<img alt="Nx - Smart Monorepos · Fast CI" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
2
7
|
|
|
3
8
|
<div style="text-align: center;">
|
|
4
9
|
|
|
@@ -15,9 +20,9 @@
|
|
|
15
20
|
|
|
16
21
|
<hr>
|
|
17
22
|
|
|
18
|
-
# Nx: Smart
|
|
23
|
+
# Nx: Smart Monorepos · Fast CI
|
|
19
24
|
|
|
20
|
-
Nx is a
|
|
25
|
+
Nx is a build system with built-in tooling and advanced CI capabilities. It helps you maintain and scale monorepos, both locally and on CI.
|
|
21
26
|
|
|
22
27
|
## Getting Started
|
|
23
28
|
|
|
@@ -57,5 +62,5 @@ npx nx@latest init
|
|
|
57
62
|
- [Blog Posts About Nx](https://blog.nrwl.io/nx/home)
|
|
58
63
|
|
|
59
64
|
<p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
|
|
60
|
-
width="100%" alt="Nx - Smart
|
|
65
|
+
width="100%" alt="Nx - Smart Monorepos · Fast CI"></a></p>
|
|
61
66
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nx",
|
|
3
|
-
"version": "17.2
|
|
3
|
+
"version": "17.3.0-beta.2",
|
|
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": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"yargs": "^17.6.2",
|
|
67
67
|
"yargs-parser": "21.1.1",
|
|
68
68
|
"node-machine-id": "1.1.12",
|
|
69
|
-
"@nrwl/tao": "17.2
|
|
69
|
+
"@nrwl/tao": "17.3.0-beta.2"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@swc-node/register": "^1.6.7",
|
|
@@ -81,16 +81,16 @@
|
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
83
|
"optionalDependencies": {
|
|
84
|
-
"@nx/nx-darwin-x64": "17.2
|
|
85
|
-
"@nx/nx-darwin-arm64": "17.2
|
|
86
|
-
"@nx/nx-linux-x64-gnu": "17.2
|
|
87
|
-
"@nx/nx-linux-x64-musl": "17.2
|
|
88
|
-
"@nx/nx-win32-x64-msvc": "17.2
|
|
89
|
-
"@nx/nx-linux-arm64-gnu": "17.2
|
|
90
|
-
"@nx/nx-linux-arm64-musl": "17.2
|
|
91
|
-
"@nx/nx-linux-arm-gnueabihf": "17.2
|
|
92
|
-
"@nx/nx-win32-arm64-msvc": "17.2
|
|
93
|
-
"@nx/nx-freebsd-x64": "17.2
|
|
84
|
+
"@nx/nx-darwin-x64": "17.3.0-beta.2",
|
|
85
|
+
"@nx/nx-darwin-arm64": "17.3.0-beta.2",
|
|
86
|
+
"@nx/nx-linux-x64-gnu": "17.3.0-beta.2",
|
|
87
|
+
"@nx/nx-linux-x64-musl": "17.3.0-beta.2",
|
|
88
|
+
"@nx/nx-win32-x64-msvc": "17.3.0-beta.2",
|
|
89
|
+
"@nx/nx-linux-arm64-gnu": "17.3.0-beta.2",
|
|
90
|
+
"@nx/nx-linux-arm64-musl": "17.3.0-beta.2",
|
|
91
|
+
"@nx/nx-linux-arm-gnueabihf": "17.3.0-beta.2",
|
|
92
|
+
"@nx/nx-win32-arm64-msvc": "17.3.0-beta.2",
|
|
93
|
+
"@nx/nx-freebsd-x64": "17.3.0-beta.2"
|
|
94
94
|
},
|
|
95
95
|
"nx-migrations": {
|
|
96
96
|
"migrations": "./migrations.json",
|
|
@@ -24,15 +24,26 @@ export declare class NxScopedHost extends virtualFs.ScopedHost<any> {
|
|
|
24
24
|
private root;
|
|
25
25
|
constructor(root: string);
|
|
26
26
|
read(path: Path): Observable<FileBuffer>;
|
|
27
|
-
|
|
27
|
+
protected readMergedWorkspaceConfiguration(): Observable<any>;
|
|
28
28
|
write(path: Path, content: FileBuffer): Observable<void>;
|
|
29
29
|
isFile(path: Path): Observable<boolean>;
|
|
30
30
|
exists(path: Path): Observable<boolean>;
|
|
31
31
|
mergeProjectConfiguration(existing: AngularProjectConfiguration, updated: AngularProjectConfiguration, projectName: string): AngularProjectConfiguration;
|
|
32
32
|
readExistingAngularJson(): Observable<any>;
|
|
33
|
-
|
|
33
|
+
protected readJson<T = any>(path: string): Observable<T>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Host used by Angular CLI builders. It reads the project configurations from
|
|
37
|
+
* the project graph to access the expanded targets.
|
|
38
|
+
*/
|
|
39
|
+
export declare class NxScopedHostForBuilders extends NxScopedHost {
|
|
40
|
+
protected readMergedWorkspaceConfiguration(): Observable<any>;
|
|
34
41
|
}
|
|
35
42
|
export declare function arrayBufferToString(buffer: any): string;
|
|
43
|
+
/**
|
|
44
|
+
* Host used by Angular CLI schematics. It reads the project configurations from
|
|
45
|
+
* the project configuration files.
|
|
46
|
+
*/
|
|
36
47
|
export declare class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
|
|
37
48
|
private readonly host;
|
|
38
49
|
constructor(root: string, host: Tree);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getLogger = exports.wrapAngularDevkitSchematic = exports.mockSchematicsForTesting = exports.runMigration = exports.generate = exports.NxScopeHostUsedForWrappedSchematics = exports.arrayBufferToString = exports.NxScopedHost = exports.scheduleTarget = exports.createBuilderContext = void 0;
|
|
3
|
+
exports.getLogger = exports.wrapAngularDevkitSchematic = exports.mockSchematicsForTesting = exports.runMigration = exports.generate = exports.NxScopeHostUsedForWrappedSchematics = exports.arrayBufferToString = exports.NxScopedHostForBuilders = exports.NxScopedHost = exports.scheduleTarget = exports.createBuilderContext = void 0;
|
|
4
4
|
const core_1 = require("@angular-devkit/core");
|
|
5
5
|
const node_1 = require("@angular-devkit/core/node");
|
|
6
6
|
const chalk = require("chalk");
|
|
@@ -23,7 +23,7 @@ const nx_plugin_1 = require("../utils/nx-plugin");
|
|
|
23
23
|
const schema_utils_1 = require("../config/schema-utils");
|
|
24
24
|
async function createBuilderContext(builderInfo, context) {
|
|
25
25
|
require('./compat');
|
|
26
|
-
const fsHost = new
|
|
26
|
+
const fsHost = new NxScopedHostForBuilders(context.root);
|
|
27
27
|
// the top level import is not patched because it is imported before the
|
|
28
28
|
// patching happens so we require it here to use the patched version below
|
|
29
29
|
const { workspaces } = require('@angular-devkit/core');
|
|
@@ -108,7 +108,7 @@ exports.createBuilderContext = createBuilderContext;
|
|
|
108
108
|
async function scheduleTarget(root, opts, verbose) {
|
|
109
109
|
const { Architect } = require('@angular-devkit/architect');
|
|
110
110
|
const logger = (0, exports.getLogger)(verbose);
|
|
111
|
-
const fsHost = new
|
|
111
|
+
const fsHost = new NxScopedHostForBuilders(root);
|
|
112
112
|
const { workspace } = await core_1.workspaces.readWorkspace('angular.json', core_1.workspaces.createWorkspaceHost(fsHost));
|
|
113
113
|
const registry = new core_1.schema.CoreSchemaRegistry();
|
|
114
114
|
registry.addPostTransform(core_1.schema.transforms.addUndefinedDefaults);
|
|
@@ -225,7 +225,7 @@ async function runSchematic(host, root, workflow, logger, opts, schematic, print
|
|
|
225
225
|
.toPromise();
|
|
226
226
|
}
|
|
227
227
|
catch (e) {
|
|
228
|
-
console.
|
|
228
|
+
console.error(e);
|
|
229
229
|
throw e;
|
|
230
230
|
}
|
|
231
231
|
if (!record.error) {
|
|
@@ -273,8 +273,8 @@ class NxScopedHost extends core_1.virtualFs.ScopedHost {
|
|
|
273
273
|
return workspaceConfig;
|
|
274
274
|
}));
|
|
275
275
|
}), (0, operators_1.catchError)((err) => {
|
|
276
|
-
console.
|
|
277
|
-
console.
|
|
276
|
+
console.error('Unable to read angular.json');
|
|
277
|
+
console.error(err);
|
|
278
278
|
process.exit(1);
|
|
279
279
|
}));
|
|
280
280
|
}
|
|
@@ -378,6 +378,30 @@ class NxScopedHost extends core_1.virtualFs.ScopedHost {
|
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
380
|
exports.NxScopedHost = NxScopedHost;
|
|
381
|
+
/**
|
|
382
|
+
* Host used by Angular CLI builders. It reads the project configurations from
|
|
383
|
+
* the project graph to access the expanded targets.
|
|
384
|
+
*/
|
|
385
|
+
class NxScopedHostForBuilders extends NxScopedHost {
|
|
386
|
+
readMergedWorkspaceConfiguration() {
|
|
387
|
+
return (0, rxjs_1.zip)((0, rxjs_1.from)((0, project_graph_1.createProjectGraphAsync)()), this.readExistingAngularJson(), this.readJson('nx.json')).pipe((0, operators_1.map)(([graph, angularJson, nxJson]) => {
|
|
388
|
+
const workspaceConfig = (angularJson || { projects: {} });
|
|
389
|
+
workspaceConfig.cli ??= nxJson.cli;
|
|
390
|
+
workspaceConfig.schematics ??= nxJson.generators;
|
|
391
|
+
for (const projectName of Object.keys(graph.nodes)) {
|
|
392
|
+
workspaceConfig.projects[projectName] ??= {
|
|
393
|
+
...graph.nodes[projectName].data,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
return workspaceConfig;
|
|
397
|
+
}), (0, operators_1.catchError)((err) => {
|
|
398
|
+
console.error('Unable to read angular.json');
|
|
399
|
+
console.error(err);
|
|
400
|
+
process.exit(1);
|
|
401
|
+
}));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
exports.NxScopedHostForBuilders = NxScopedHostForBuilders;
|
|
381
405
|
function arrayBufferToString(buffer) {
|
|
382
406
|
const array = new Uint8Array(buffer);
|
|
383
407
|
let result = '';
|
|
@@ -390,6 +414,10 @@ function arrayBufferToString(buffer) {
|
|
|
390
414
|
return result;
|
|
391
415
|
}
|
|
392
416
|
exports.arrayBufferToString = arrayBufferToString;
|
|
417
|
+
/**
|
|
418
|
+
* Host used by Angular CLI schematics. It reads the project configurations from
|
|
419
|
+
* the project configuration files.
|
|
420
|
+
*/
|
|
393
421
|
class NxScopeHostUsedForWrappedSchematics extends NxScopedHost {
|
|
394
422
|
constructor(root, host) {
|
|
395
423
|
super(root);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { CommandModule } from 'yargs';
|
|
2
|
-
|
|
3
|
-
export declare const yargsConnectCommand: CommandModule<{}, ConnectToNxCloudOptions>;
|
|
2
|
+
export declare const yargsConnectCommand: CommandModule;
|
|
4
3
|
export declare const yargsViewLogsCommand: CommandModule;
|
|
@@ -6,13 +6,9 @@ exports.yargsConnectCommand = {
|
|
|
6
6
|
command: 'connect',
|
|
7
7
|
aliases: ['connect-to-nx-cloud'],
|
|
8
8
|
describe: `Connect workspace to Nx Cloud`,
|
|
9
|
-
builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)(yargs
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
default: true,
|
|
13
|
-
}), 'connect-to-nx-cloud'),
|
|
14
|
-
handler: async (options) => {
|
|
15
|
-
await (await Promise.resolve().then(() => require('./connect-to-nx-cloud'))).connectToNxCloudCommand(options);
|
|
9
|
+
builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)(yargs, 'connect-to-nx-cloud'),
|
|
10
|
+
handler: async () => {
|
|
11
|
+
await (await Promise.resolve().then(() => require('./connect-to-nx-cloud'))).connectToNxCloudCommand();
|
|
16
12
|
process.exit(0);
|
|
17
13
|
},
|
|
18
14
|
};
|
|
@@ -2,8 +2,5 @@ import { NxJsonConfiguration } from '../../config/nx-json';
|
|
|
2
2
|
import { NxArgs } from '../../utils/command-line-utils';
|
|
3
3
|
export declare function onlyDefaultRunnerIsUsed(nxJson: NxJsonConfiguration): boolean;
|
|
4
4
|
export declare function connectToNxCloudIfExplicitlyAsked(opts: NxArgs): Promise<void>;
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
promptOverride?: string;
|
|
8
|
-
}
|
|
9
|
-
export declare function connectToNxCloudCommand({ promptOverride, interactive, }: ConnectToNxCloudOptions): Promise<boolean>;
|
|
5
|
+
export declare function connectToNxCloudCommand(): Promise<boolean>;
|
|
6
|
+
export declare function connectToNxCloudPrompt(prompt?: string): Promise<boolean>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.connectToNxCloudCommand = exports.connectToNxCloudIfExplicitlyAsked = exports.onlyDefaultRunnerIsUsed = void 0;
|
|
3
|
+
exports.connectToNxCloudPrompt = exports.connectToNxCloudCommand = exports.connectToNxCloudIfExplicitlyAsked = exports.onlyDefaultRunnerIsUsed = void 0;
|
|
4
4
|
const output_1 = require("../../utils/output");
|
|
5
5
|
const configuration_1 = require("../../config/configuration");
|
|
6
6
|
const nx_cloud_utils_1 = require("../../utils/nx-cloud-utils");
|
|
@@ -34,7 +34,7 @@ async function connectToNxCloudIfExplicitlyAsked(opts) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
exports.connectToNxCloudIfExplicitlyAsked = connectToNxCloudIfExplicitlyAsked;
|
|
37
|
-
async function connectToNxCloudCommand(
|
|
37
|
+
async function connectToNxCloudCommand() {
|
|
38
38
|
const nxJson = (0, configuration_1.readNxJson)();
|
|
39
39
|
if ((0, nx_cloud_utils_1.isNxCloudUsed)(nxJson)) {
|
|
40
40
|
output_1.output.log({
|
|
@@ -49,9 +49,6 @@ async function connectToNxCloudCommand({ promptOverride, interactive, }) {
|
|
|
49
49
|
});
|
|
50
50
|
return false;
|
|
51
51
|
}
|
|
52
|
-
const res = interactive ? await connectToNxCloudPrompt(promptOverride) : true;
|
|
53
|
-
if (!res)
|
|
54
|
-
return false;
|
|
55
52
|
(0, child_process_1.runNxSync)(`g nx:connect-to-nx-cloud --quiet --no-interactive`, {
|
|
56
53
|
stdio: [0, 1, 2],
|
|
57
54
|
});
|
|
@@ -79,3 +76,4 @@ async function connectToNxCloudPrompt(prompt) {
|
|
|
79
76
|
])
|
|
80
77
|
.then((a) => a.NxCloud === 'Yes');
|
|
81
78
|
}
|
|
79
|
+
exports.connectToNxCloudPrompt = connectToNxCloudPrompt;
|
|
@@ -106,6 +106,7 @@ function addPluginDependencies() {
|
|
|
106
106
|
(0, fileutils_1.writeJsonFile)(packageJsonPath, packageJson);
|
|
107
107
|
}
|
|
108
108
|
async function setupWorkspace(cacheableOperations, isIntegratedMigration) {
|
|
109
|
+
(0, utils_1.updateGitIgnore)(repoRoot);
|
|
109
110
|
if (isIntegratedMigration) {
|
|
110
111
|
(0, integrated_workspace_1.setupIntegratedWorkspace)();
|
|
111
112
|
}
|
|
@@ -751,10 +751,8 @@ async function generateMigrationsJsonAndUpdatePackageJson(root, opts) {
|
|
|
751
751
|
(await isMigratingToNewMajor(from, opts.targetVersion)) &&
|
|
752
752
|
!(0, is_ci_1.isCI)() &&
|
|
753
753
|
!(0, nx_cloud_utils_1.isNxCloudUsed)(originalNxJson)) {
|
|
754
|
-
const
|
|
755
|
-
|
|
756
|
-
interactive: true,
|
|
757
|
-
});
|
|
754
|
+
const setNxCloud = await (0, connect_to_nx_cloud_1.connectToNxCloudPrompt)(ab_testing_1.messages.getPromptMessage('nxCloudMigration'));
|
|
755
|
+
const useCloud = setNxCloud ? await (0, connect_to_nx_cloud_1.connectToNxCloudCommand)() : false;
|
|
758
756
|
await (0, ab_testing_1.recordStat)({
|
|
759
757
|
command: 'migrate',
|
|
760
758
|
nxVersion: versions_1.nxVersion,
|
|
@@ -36,7 +36,7 @@ exports.parserConfiguration = {
|
|
|
36
36
|
*/
|
|
37
37
|
exports.commandsObject = yargs
|
|
38
38
|
.parserConfiguration(exports.parserConfiguration)
|
|
39
|
-
.usage(chalk.bold('Smart
|
|
39
|
+
.usage(chalk.bold('Smart Monorepos · Fast CI'))
|
|
40
40
|
.demandCommand(1, '')
|
|
41
41
|
.command(command_object_1.yargsAffectedBuildCommand)
|
|
42
42
|
.command(command_object_1.yargsAffectedCommand)
|
|
@@ -73,24 +73,6 @@ async function releaseChangelog(args) {
|
|
|
73
73
|
if (autoCommitEnabled && headSHA !== toSHA) {
|
|
74
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
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;
|
|
91
|
-
}
|
|
92
|
-
return false;
|
|
93
|
-
});
|
|
94
76
|
const tree = new tree_1.FsTree(workspace_root_1.workspaceRoot, args.verbose);
|
|
95
77
|
const userCommitMessage = args.gitCommitMessage || nxReleaseConfig.changelog.git.commitMessage;
|
|
96
78
|
const commitMessageValues = (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, projectsVersionData, userCommitMessage);
|
|
@@ -100,23 +82,51 @@ async function releaseChangelog(args) {
|
|
|
100
82
|
: [];
|
|
101
83
|
(0, shared_1.handleDuplicateGitTags)(gitTagValues);
|
|
102
84
|
const postGitTasks = [];
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
*/
|
|
108
|
-
for (const releaseGroup of releaseGroups) {
|
|
109
|
-
const projectNodes = Array.from(releaseGroupToFilteredProjects.get(releaseGroup)).map((name) => projectGraph.nodes[name]);
|
|
110
|
-
await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, projectNodes);
|
|
111
|
-
}
|
|
112
|
-
return await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues);
|
|
85
|
+
const workspaceChangelogFromRef = args.from ||
|
|
86
|
+
(await (0, git_1.getLatestGitTagForPattern)(nxReleaseConfig.releaseTagPattern))?.tag;
|
|
87
|
+
if (!workspaceChangelogFromRef) {
|
|
88
|
+
throw new Error(`Unable to determine the previous git tag, please provide an explicit git reference using --from`);
|
|
113
89
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
90
|
+
// Make sure that the fromRef is actually resolvable
|
|
91
|
+
const workspaceChangelogFromSHA = await (0, git_1.getCommitHash)(workspaceChangelogFromRef);
|
|
92
|
+
const workspaceChangelogCommits = await getCommits(workspaceChangelogFromSHA, toSHA);
|
|
93
|
+
await generateChangelogForWorkspace(tree, args, projectGraph, nxReleaseConfig, workspaceChangelogVersion, workspaceChangelogCommits, postGitTasks, nxJson.release?.changelog?.workspaceChangelog);
|
|
117
94
|
for (const releaseGroup of releaseGroups) {
|
|
118
|
-
const
|
|
119
|
-
|
|
95
|
+
const config = releaseGroup.changelog;
|
|
96
|
+
// The entire feature is disabled at the release group level, exit early
|
|
97
|
+
if (config === false) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const projects = args.projects?.length
|
|
101
|
+
? // If the user has passed a list of projects, we need to use the filtered list of projects within the release group
|
|
102
|
+
Array.from(releaseGroupToFilteredProjects.get(releaseGroup))
|
|
103
|
+
: // Otherwise, we use the full list of projects within the release group
|
|
104
|
+
releaseGroup.projects;
|
|
105
|
+
const projectNodes = projects.map((name) => projectGraph.nodes[name]);
|
|
106
|
+
if (releaseGroup.projectsRelationship === 'independent') {
|
|
107
|
+
for (const project of projectNodes) {
|
|
108
|
+
const fromRef = args.from ||
|
|
109
|
+
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern, {
|
|
110
|
+
projectName: project.name,
|
|
111
|
+
}))?.tag;
|
|
112
|
+
if (!fromRef) {
|
|
113
|
+
throw new Error(`Unable to determine the previous git tag, please provide an explicit git reference using --from`);
|
|
114
|
+
}
|
|
115
|
+
const commits = await getCommits(fromRef, toSHA);
|
|
116
|
+
await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, [project]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const fromRef = args.from ||
|
|
121
|
+
(await (0, git_1.getLatestGitTagForPattern)(releaseGroup.releaseTagPattern))?.tag;
|
|
122
|
+
if (!fromRef) {
|
|
123
|
+
throw new Error(`Unable to determine the previous git tag, please provide an explicit git reference using --from`);
|
|
124
|
+
}
|
|
125
|
+
// Make sure that the fromRef is actually resolvable
|
|
126
|
+
const fromSHA = await (0, git_1.getCommitHash)(fromRef);
|
|
127
|
+
const commits = await getCommits(fromSHA, toSHA);
|
|
128
|
+
await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, projectNodes);
|
|
129
|
+
}
|
|
120
130
|
}
|
|
121
131
|
return await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues);
|
|
122
132
|
}
|
|
@@ -225,7 +235,7 @@ function resolveChangelogRenderer(changelogRendererPath) {
|
|
|
225
235
|
}
|
|
226
236
|
return changelogRenderer;
|
|
227
237
|
}
|
|
228
|
-
async function generateChangelogForWorkspace(tree, args, projectGraph, nxReleaseConfig, workspaceChangelogVersion, commits, postGitTasks) {
|
|
238
|
+
async function generateChangelogForWorkspace(tree, args, projectGraph, nxReleaseConfig, workspaceChangelogVersion, commits, postGitTasks, explicitWorkspaceChangelogConfig) {
|
|
229
239
|
const config = nxReleaseConfig.changelog.workspaceChangelog;
|
|
230
240
|
const isEnabled = args.workspaceChangelog ?? config;
|
|
231
241
|
// The entire feature is disabled at the workspace level, exit early
|
|
@@ -243,6 +253,25 @@ async function generateChangelogForWorkspace(tree, args, projectGraph, nxRelease
|
|
|
243
253
|
if (!workspaceChangelogVersion && args.workspaceChangelog) {
|
|
244
254
|
throw new Error(`Workspace changelog is enabled but no overall version was provided. Please provide an explicit version using --version`);
|
|
245
255
|
}
|
|
256
|
+
if (Object.entries(nxReleaseConfig.groups).length > 1 ||
|
|
257
|
+
Object.values(nxReleaseConfig.groups)[0].projectsRelationship ===
|
|
258
|
+
'independent') {
|
|
259
|
+
if (explicitWorkspaceChangelogConfig !== undefined &&
|
|
260
|
+
explicitWorkspaceChangelogConfig !== false) {
|
|
261
|
+
// only warn the user if they explicitly enabled workspace changelog
|
|
262
|
+
// if they didn't, then just disable it quietly, since it was enabled by default
|
|
263
|
+
output_1.output.warn({
|
|
264
|
+
title: `Workspace changelog is enabled, but you have multiple release groups configured or have configured an independent projects relationship. This is not supported, so workspace changelog will be disabled.`,
|
|
265
|
+
bodyLines: [
|
|
266
|
+
`A single workspace version cannot be determined when defining multiple release groups because versions differ between each group.`,
|
|
267
|
+
`Also, a single workspace version also cannot be determined when using independent projects because versions differ between each project.`,
|
|
268
|
+
`If you want to generate a workspace changelog, please use a single release group.`,
|
|
269
|
+
`Alternatively, project level changelogs can be enabled with the "projectChangelogs" property.`,
|
|
270
|
+
],
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
246
275
|
// Only trigger interactive mode for the workspace changelog if the user explicitly requested it via "all" or "workspace"
|
|
247
276
|
const interactive = args.interactive === 'all' || args.interactive === 'workspace';
|
|
248
277
|
const dryRun = !!args.dryRun;
|
|
@@ -593,3 +622,16 @@ function checkChangelogFilesEnabled(nxReleaseConfig) {
|
|
|
593
622
|
}
|
|
594
623
|
return false;
|
|
595
624
|
}
|
|
625
|
+
async function getCommits(fromSHA, toSHA) {
|
|
626
|
+
const rawCommits = await (0, git_1.getGitDiff)(fromSHA, toSHA);
|
|
627
|
+
// Parse as conventional commits
|
|
628
|
+
return (0, git_1.parseCommits)(rawCommits).filter((c) => {
|
|
629
|
+
const type = c.type;
|
|
630
|
+
// Always ignore non user-facing commits for now
|
|
631
|
+
// TODO: allow this filter to be configurable via config in a future release
|
|
632
|
+
if (type === 'feat' || type === 'fix' || type === 'perf') {
|
|
633
|
+
return true;
|
|
634
|
+
}
|
|
635
|
+
return false;
|
|
636
|
+
});
|
|
637
|
+
}
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.formatReferences = exports.getGithubReleaseByTag = exports.resolveGithubToken = exports.createOrUpdateGithubRelease = exports.getGitHubRepoSlug = void 0;
|
|
4
4
|
const chalk = require("chalk");
|
|
5
|
+
const enquirer_1 = require("enquirer");
|
|
5
6
|
const node_child_process_1 = require("node:child_process");
|
|
6
7
|
const node_fs_1 = require("node:fs");
|
|
7
8
|
const node_os_1 = require("node:os");
|
|
9
|
+
const output_1 = require("../../../utils/output");
|
|
8
10
|
const path_1 = require("../../../utils/path");
|
|
9
11
|
// axios types and values don't seem to match
|
|
10
12
|
const _axios = require("axios");
|
|
@@ -32,6 +34,66 @@ function getGitHubRepoSlug(remoteName = 'origin') {
|
|
|
32
34
|
exports.getGitHubRepoSlug = getGitHubRepoSlug;
|
|
33
35
|
async function createOrUpdateGithubRelease(githubRequestConfig, release, existingGithubReleaseForVersion) {
|
|
34
36
|
const result = await syncGithubRelease(githubRequestConfig, release, existingGithubReleaseForVersion);
|
|
37
|
+
/**
|
|
38
|
+
* If something went wrong POSTing to Github we can still pre-populate the web form on github.com
|
|
39
|
+
* to allow the user to manually complete the release if they so choose.
|
|
40
|
+
*/
|
|
41
|
+
if (result.status === 'manual') {
|
|
42
|
+
if (result.error) {
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
if (result.error.response?.data) {
|
|
45
|
+
// There's a nicely formatted error from GitHub we can display to the user
|
|
46
|
+
output_1.output.error({
|
|
47
|
+
title: `A GitHub API Error occurred when creating/updating the release`,
|
|
48
|
+
bodyLines: [
|
|
49
|
+
`GitHub Error: ${JSON.stringify(result.error.response.data)}`,
|
|
50
|
+
`---`,
|
|
51
|
+
`Request Data:`,
|
|
52
|
+
`Repo: ${githubRequestConfig.repo}`,
|
|
53
|
+
`Token: ${githubRequestConfig.token}`,
|
|
54
|
+
`Body: ${JSON.stringify(result.requestData)}`,
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(result.error);
|
|
60
|
+
console.error(`An unknown error occurred while trying to create a release on GitHub, please report this on https://github.com/nrwl/nx (NOTE: make sure to redact your GitHub token from the error message!)`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const reply = await (0, enquirer_1.prompt)([
|
|
64
|
+
{
|
|
65
|
+
name: 'open',
|
|
66
|
+
message: 'Do you want to finish creating the release manually in your browser?',
|
|
67
|
+
type: 'autocomplete',
|
|
68
|
+
choices: [
|
|
69
|
+
{
|
|
70
|
+
name: 'Yes',
|
|
71
|
+
hint: 'It will pre-populate the form for you',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'No',
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
initial: 'Yes',
|
|
78
|
+
},
|
|
79
|
+
]).catch(() => {
|
|
80
|
+
return { open: 'No' };
|
|
81
|
+
});
|
|
82
|
+
if (reply.open === 'Yes') {
|
|
83
|
+
const open = require('open');
|
|
84
|
+
await open(result.url)
|
|
85
|
+
.then(() => {
|
|
86
|
+
console.info(`\nFollow up in the browser to manually create the release:\n\n` +
|
|
87
|
+
chalk.underline(chalk.cyan(result.url)) +
|
|
88
|
+
`\n`);
|
|
89
|
+
})
|
|
90
|
+
.catch(() => {
|
|
91
|
+
console.info(`Open this link to manually create a release: \n` +
|
|
92
|
+
chalk.underline(chalk.cyan(result.url)) +
|
|
93
|
+
'\n');
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
35
97
|
/**
|
|
36
98
|
* If something went wrong POSTing to Github we can still pre-populate the web form on github.com
|
|
37
99
|
* to allow the user to manually complete the release.
|
|
@@ -79,6 +141,7 @@ async function syncGithubRelease(githubRequestConfig, release, existingGithubRel
|
|
|
79
141
|
status: 'manual',
|
|
80
142
|
error,
|
|
81
143
|
url: githubNewReleaseURL(githubRequestConfig, release),
|
|
144
|
+
requestData: ghRelease,
|
|
82
145
|
};
|
|
83
146
|
}
|
|
84
147
|
}
|
|
@@ -139,7 +202,7 @@ async function updateGithubRelease(config, id, body) {
|
|
|
139
202
|
});
|
|
140
203
|
}
|
|
141
204
|
function githubNewReleaseURL(config, release) {
|
|
142
|
-
return `https://github.com/${config.repo}/releases/new?tag
|
|
205
|
+
return `https://github.com/${config.repo}/releases/new?tag=${release.version}&title=${release.version}&body=${encodeURIComponent(release.body)}`;
|
|
143
206
|
}
|
|
144
207
|
const providerToRefSpec = {
|
|
145
208
|
github: { 'pull-request': 'pull', hash: 'commit', issue: 'issues' },
|
|
@@ -111,12 +111,14 @@ function createCommitMessageValues(releaseGroups, releaseGroupToFilteredProjects
|
|
|
111
111
|
if (releaseGroup.projectsRelationship === 'independent') {
|
|
112
112
|
for (const project of releaseGroupProjectNames) {
|
|
113
113
|
const projectVersionData = versionData[project];
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
if (projectVersionData.newVersion !== null) {
|
|
115
|
+
const releaseVersion = new ReleaseVersion({
|
|
116
|
+
version: projectVersionData.newVersion,
|
|
117
|
+
releaseTagPattern: releaseGroup.releaseTagPattern,
|
|
118
|
+
projectName: project,
|
|
119
|
+
});
|
|
120
|
+
commitMessageValues.push(`- project: ${project} ${releaseVersion.rawVersion}`);
|
|
121
|
+
}
|
|
120
122
|
}
|
|
121
123
|
continue;
|
|
122
124
|
}
|
|
@@ -150,10 +152,12 @@ function createGitTagValues(releaseGroups, releaseGroupToFilteredProjects, versi
|
|
|
150
152
|
if (releaseGroup.projectsRelationship === 'independent') {
|
|
151
153
|
for (const project of releaseGroupProjectNames) {
|
|
152
154
|
const projectVersionData = versionData[project];
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
if (projectVersionData.newVersion !== null) {
|
|
156
|
+
tags.push((0, utils_1.interpolate)(releaseGroup.releaseTagPattern, {
|
|
157
|
+
version: projectVersionData.newVersion,
|
|
158
|
+
projectName: project,
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
157
161
|
}
|
|
158
162
|
continue;
|
|
159
163
|
}
|
|
@@ -67,6 +67,23 @@ async function releaseVersion(args) {
|
|
|
67
67
|
: [];
|
|
68
68
|
(0, shared_1.handleDuplicateGitTags)(gitTagValues);
|
|
69
69
|
printAndFlushChanges(tree, !!args.dryRun);
|
|
70
|
+
const changedFiles = tree.listChanges().map((f) => f.path);
|
|
71
|
+
// No further actions are necessary in this scenario (e.g. if conventional commits detected no changes)
|
|
72
|
+
if (!changedFiles.length) {
|
|
73
|
+
return {
|
|
74
|
+
// An overall workspace version cannot be relevant when filtering to independent projects
|
|
75
|
+
workspaceVersion: undefined,
|
|
76
|
+
projectsVersionData: versionData,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (args.stageChanges) {
|
|
80
|
+
devkit_exports_1.output.logSingleLine(`Staging changed files with git because --stage-changes was set`);
|
|
81
|
+
await (0, git_1.gitAdd)({
|
|
82
|
+
changedFiles,
|
|
83
|
+
dryRun: args.dryRun,
|
|
84
|
+
verbose: args.verbose,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
70
87
|
if (args.gitCommit ?? nxReleaseConfig.version.git.commit) {
|
|
71
88
|
await (0, shared_1.commitChanges)(tree.listChanges().map((f) => f.path), !!args.dryRun, !!args.verbose, (0, shared_1.createCommitMessageValues)(releaseGroups, releaseGroupToFilteredProjects, versionData, userCommitMessage), args.gitCommitArgs || nxReleaseConfig.version.git.commitArgs);
|
|
72
89
|
}
|