nx 18.1.0-canary.20240210-b1d0294 → 18.1.0-canary.20240214-b625a79
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/src/command-line/migrate/migrate.js +11 -1
- package/src/command-line/release/changelog.d.ts +16 -1
- package/src/command-line/release/changelog.js +104 -194
- package/src/command-line/release/command-object.d.ts +1 -0
- package/src/command-line/release/command-object.js +1 -1
- package/src/command-line/release/release.js +56 -3
- package/src/command-line/release/utils/git.d.ts +5 -1
- package/src/command-line/release/utils/git.js +26 -11
- package/src/command-line/release/utils/github.d.ts +4 -8
- package/src/command-line/release/utils/github.js +61 -2
- package/src/command-line/release/utils/shared.d.ts +1 -0
- package/src/command-line/release/utils/shared.js +3 -1
- package/src/config/nx-json.d.ts +1 -13
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/polyfills.js +1 -1
- package/src/utils/output.js +4 -2
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "18.1.0-canary.
|
3
|
+
"version": "18.1.0-canary.20240214-b625a79",
|
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-parser": "21.1.1",
|
67
67
|
"node-machine-id": "1.1.12",
|
68
68
|
"ora": "5.3.0",
|
69
|
-
"@nrwl/tao": "18.1.0-canary.
|
69
|
+
"@nrwl/tao": "18.1.0-canary.20240214-b625a79"
|
70
70
|
},
|
71
71
|
"peerDependencies": {
|
72
72
|
"@swc-node/register": "^1.8.0",
|
@@ -81,16 +81,16 @@
|
|
81
81
|
}
|
82
82
|
},
|
83
83
|
"optionalDependencies": {
|
84
|
-
"@nx/nx-darwin-x64": "18.1.0-canary.
|
85
|
-
"@nx/nx-darwin-arm64": "18.1.0-canary.
|
86
|
-
"@nx/nx-linux-x64-gnu": "18.1.0-canary.
|
87
|
-
"@nx/nx-linux-x64-musl": "18.1.0-canary.
|
88
|
-
"@nx/nx-win32-x64-msvc": "18.1.0-canary.
|
89
|
-
"@nx/nx-linux-arm64-gnu": "18.1.0-canary.
|
90
|
-
"@nx/nx-linux-arm64-musl": "18.1.0-canary.
|
91
|
-
"@nx/nx-linux-arm-gnueabihf": "18.1.0-canary.
|
92
|
-
"@nx/nx-win32-arm64-msvc": "18.1.0-canary.
|
93
|
-
"@nx/nx-freebsd-x64": "18.1.0-canary.
|
84
|
+
"@nx/nx-darwin-x64": "18.1.0-canary.20240214-b625a79",
|
85
|
+
"@nx/nx-darwin-arm64": "18.1.0-canary.20240214-b625a79",
|
86
|
+
"@nx/nx-linux-x64-gnu": "18.1.0-canary.20240214-b625a79",
|
87
|
+
"@nx/nx-linux-x64-musl": "18.1.0-canary.20240214-b625a79",
|
88
|
+
"@nx/nx-win32-x64-msvc": "18.1.0-canary.20240214-b625a79",
|
89
|
+
"@nx/nx-linux-arm64-gnu": "18.1.0-canary.20240214-b625a79",
|
90
|
+
"@nx/nx-linux-arm64-musl": "18.1.0-canary.20240214-b625a79",
|
91
|
+
"@nx/nx-linux-arm-gnueabihf": "18.1.0-canary.20240214-b625a79",
|
92
|
+
"@nx/nx-win32-arm64-msvc": "18.1.0-canary.20240214-b625a79",
|
93
|
+
"@nx/nx-freebsd-x64": "18.1.0-canary.20240214-b625a79"
|
94
94
|
},
|
95
95
|
"nx-migrations": {
|
96
96
|
"migrations": "./migrations.json",
|
@@ -862,7 +862,17 @@ function runInstall() {
|
|
862
862
|
async function executeMigrations(root, migrations, isVerbose, shouldCreateCommits, commitPrefix) {
|
863
863
|
const depsBeforeMigrations = getStringifiedPackageJsonDeps(root);
|
864
864
|
const migrationsWithNoChanges = [];
|
865
|
-
|
865
|
+
const sortedMigrations = migrations.sort((a, b) => {
|
866
|
+
// special case for the split configuration migration to run first
|
867
|
+
if (a.name === '15-7-0-split-configuration-into-project-json-files') {
|
868
|
+
return -1;
|
869
|
+
}
|
870
|
+
if (b.name === '15-7-0-split-configuration-into-project-json-files') {
|
871
|
+
return 1;
|
872
|
+
}
|
873
|
+
return (0, semver_1.lt)(a.version, b.version) ? -1 : 1;
|
874
|
+
});
|
875
|
+
for (const m of sortedMigrations) {
|
866
876
|
try {
|
867
877
|
const { collection, collectionPath } = readMigrationCollection(m.package, root);
|
868
878
|
if (!isAngularMigration(collection, collectionPath, m.name)) {
|
@@ -1,8 +1,23 @@
|
|
1
|
+
import { NxReleaseChangelogConfiguration } from '../../config/nx-json';
|
1
2
|
import { ChangelogOptions } from './command-object';
|
3
|
+
import { ReleaseVersion } from './utils/shared';
|
4
|
+
export interface NxReleaseChangelogResult {
|
5
|
+
workspaceChangelog?: {
|
6
|
+
releaseVersion: ReleaseVersion;
|
7
|
+
contents: string;
|
8
|
+
};
|
9
|
+
projectChangelogs?: {
|
10
|
+
[projectName: string]: {
|
11
|
+
releaseVersion: ReleaseVersion;
|
12
|
+
contents: string;
|
13
|
+
};
|
14
|
+
};
|
15
|
+
}
|
2
16
|
export declare const releaseChangelogCLIHandler: (args: ChangelogOptions) => Promise<any>;
|
3
17
|
/**
|
4
18
|
* NOTE: This function is also exported for programmatic usage and forms part of the public API
|
5
19
|
* of Nx. We intentionally do not wrap the implementation with handleErrors because users need
|
6
20
|
* to have control over their own error handling when using the API.
|
7
21
|
*/
|
8
|
-
export declare function releaseChangelog(args: ChangelogOptions): Promise<
|
22
|
+
export declare function releaseChangelog(args: ChangelogOptions): Promise<NxReleaseChangelogResult>;
|
23
|
+
export declare function shouldCreateGitHubRelease(changelogConfig: NxReleaseChangelogConfiguration | false | undefined, createReleaseArg?: ChangelogOptions['createRelease'] | undefined): boolean;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.releaseChangelog = exports.releaseChangelogCLIHandler = void 0;
|
3
|
+
exports.shouldCreateGitHubRelease = exports.releaseChangelog = exports.releaseChangelogCLIHandler = void 0;
|
4
4
|
const chalk = require("chalk");
|
5
5
|
const node_fs_1 = require("node:fs");
|
6
6
|
const semver_1 = require("semver");
|
@@ -74,7 +74,7 @@ async function releaseChangelog(args) {
|
|
74
74
|
`To explicitly enable changelog generation, configure "release.changelog.workspaceChangelog" or "release.changelog.projectChangelogs" in nx.json.`,
|
75
75
|
],
|
76
76
|
});
|
77
|
-
return
|
77
|
+
return {};
|
78
78
|
}
|
79
79
|
const useAutomaticFromRef = nxReleaseConfig.changelog?.automaticFromRef || args.firstRelease;
|
80
80
|
/**
|
@@ -128,7 +128,26 @@ async function releaseChangelog(args) {
|
|
128
128
|
// Make sure that the fromRef is actually resolvable
|
129
129
|
const workspaceChangelogFromSHA = await (0, git_1.getCommitHash)(workspaceChangelogFromRef);
|
130
130
|
const workspaceChangelogCommits = await getCommits(workspaceChangelogFromSHA, toSHA);
|
131
|
-
await generateChangelogForWorkspace(tree, args, projectGraph, nxReleaseConfig, workspaceChangelogVersion, workspaceChangelogCommits
|
131
|
+
const workspaceChangelog = await generateChangelogForWorkspace(tree, args, projectGraph, nxReleaseConfig, workspaceChangelogVersion, workspaceChangelogCommits);
|
132
|
+
if (workspaceChangelog &&
|
133
|
+
shouldCreateGitHubRelease(nxReleaseConfig.changelog.workspaceChangelog, args.createRelease)) {
|
134
|
+
let hasPushed = false;
|
135
|
+
postGitTasks.push(async (latestCommit) => {
|
136
|
+
if (!hasPushed) {
|
137
|
+
output_1.output.logSingleLine(`Pushing to git remote`);
|
138
|
+
// Before we can create/update the release we need to ensure the commit exists on the remote
|
139
|
+
await (0, git_1.gitPush)({
|
140
|
+
gitRemote: args.gitRemote,
|
141
|
+
dryRun: args.dryRun,
|
142
|
+
verbose: args.verbose,
|
143
|
+
});
|
144
|
+
hasPushed = true;
|
145
|
+
}
|
146
|
+
output_1.output.logSingleLine(`Creating GitHub Release`);
|
147
|
+
await (0, github_1.createOrUpdateGithubRelease)(workspaceChangelog.releaseVersion, workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
148
|
+
});
|
149
|
+
}
|
150
|
+
const allProjectChangelogs = {};
|
132
151
|
for (const releaseGroup of releaseGroups) {
|
133
152
|
const config = releaseGroup.changelog;
|
134
153
|
// The entire feature is disabled at the release group level, exit early
|
@@ -164,7 +183,28 @@ async function releaseChangelog(args) {
|
|
164
183
|
if (!commits) {
|
165
184
|
commits = await getCommits(fromRef, toSHA);
|
166
185
|
}
|
167
|
-
await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, [project]);
|
186
|
+
const projectChangelogs = await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, [project]);
|
187
|
+
let hasPushed = false;
|
188
|
+
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
189
|
+
if (projectChangelogs &&
|
190
|
+
shouldCreateGitHubRelease(releaseGroup.changelog, args.createRelease)) {
|
191
|
+
postGitTasks.push(async (latestCommit) => {
|
192
|
+
if (!hasPushed) {
|
193
|
+
output_1.output.logSingleLine(`Pushing to git remote`);
|
194
|
+
// Before we can create/update the release we need to ensure the commit exists on the remote
|
195
|
+
await (0, git_1.gitPush)({
|
196
|
+
gitRemote: args.gitRemote,
|
197
|
+
dryRun: args.dryRun,
|
198
|
+
verbose: args.verbose,
|
199
|
+
});
|
200
|
+
hasPushed = true;
|
201
|
+
}
|
202
|
+
output_1.output.logSingleLine(`Creating GitHub Release`);
|
203
|
+
await (0, github_1.createOrUpdateGithubRelease)(projectChangelog.releaseVersion, projectChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
204
|
+
});
|
205
|
+
}
|
206
|
+
allProjectChangelogs[projectName] = projectChangelog;
|
207
|
+
}
|
168
208
|
}
|
169
209
|
}
|
170
210
|
else {
|
@@ -176,10 +216,35 @@ async function releaseChangelog(args) {
|
|
176
216
|
// Make sure that the fromRef is actually resolvable
|
177
217
|
const fromSHA = await (0, git_1.getCommitHash)(fromRef);
|
178
218
|
const commits = await getCommits(fromSHA, toSHA);
|
179
|
-
await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, projectNodes);
|
219
|
+
const projectChangelogs = await generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, projectNodes);
|
220
|
+
let hasPushed = false;
|
221
|
+
for (const [projectName, projectChangelog] of Object.entries(projectChangelogs)) {
|
222
|
+
if (projectChangelogs &&
|
223
|
+
shouldCreateGitHubRelease(releaseGroup.changelog, args.createRelease)) {
|
224
|
+
postGitTasks.push(async (latestCommit) => {
|
225
|
+
if (!hasPushed) {
|
226
|
+
output_1.output.logSingleLine(`Pushing to git remote`);
|
227
|
+
// Before we can create/update the release we need to ensure the commit exists on the remote
|
228
|
+
await (0, git_1.gitPush)({
|
229
|
+
gitRemote: args.gitRemote,
|
230
|
+
dryRun: args.dryRun,
|
231
|
+
verbose: args.verbose,
|
232
|
+
});
|
233
|
+
hasPushed = true;
|
234
|
+
}
|
235
|
+
output_1.output.logSingleLine(`Creating GitHub Release`);
|
236
|
+
await (0, github_1.createOrUpdateGithubRelease)(projectChangelog.releaseVersion, projectChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
237
|
+
});
|
238
|
+
}
|
239
|
+
allProjectChangelogs[projectName] = projectChangelog;
|
240
|
+
}
|
180
241
|
}
|
181
242
|
}
|
182
|
-
|
243
|
+
await applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues);
|
244
|
+
return {
|
245
|
+
workspaceChangelog,
|
246
|
+
projectChangelogs: allProjectChangelogs,
|
247
|
+
};
|
183
248
|
}
|
184
249
|
exports.releaseChangelog = releaseChangelog;
|
185
250
|
function resolveChangelogVersions(args, releaseGroups, releaseGroupToFilteredProjects) {
|
@@ -237,7 +302,7 @@ async function applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTa
|
|
237
302
|
`No changes were detected for any changelog files, so no changelog entries will be generated.`,
|
238
303
|
],
|
239
304
|
});
|
240
|
-
return
|
305
|
+
return;
|
241
306
|
}
|
242
307
|
// Generate a new commit for the changes, if configured to do so
|
243
308
|
if (args.gitCommit ?? nxReleaseConfig.changelog.git.commit) {
|
@@ -271,7 +336,7 @@ async function applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTa
|
|
271
336
|
for (const postGitTask of postGitTasks) {
|
272
337
|
await postGitTask(latestCommit);
|
273
338
|
}
|
274
|
-
return
|
339
|
+
return;
|
275
340
|
}
|
276
341
|
function resolveChangelogRenderer(changelogRendererPath) {
|
277
342
|
// Try and load the provided (or default) changelog renderer
|
@@ -292,7 +357,7 @@ function resolveChangelogRenderer(changelogRendererPath) {
|
|
292
357
|
}
|
293
358
|
return changelogRenderer;
|
294
359
|
}
|
295
|
-
async function generateChangelogForWorkspace(tree, args, projectGraph, nxReleaseConfig, workspaceChangelogVersion, commits
|
360
|
+
async function generateChangelogForWorkspace(tree, args, projectGraph, nxReleaseConfig, workspaceChangelogVersion, commits) {
|
296
361
|
const config = nxReleaseConfig.changelog.workspaceChangelog;
|
297
362
|
// The entire feature is disabled at the workspace level, exit early
|
298
363
|
if (config === false) {
|
@@ -344,21 +409,12 @@ async function generateChangelogForWorkspace(tree, args, projectGraph, nxRelease
|
|
344
409
|
version: workspaceChangelogVersion,
|
345
410
|
releaseTagPattern: nxReleaseConfig.releaseTagPattern,
|
346
411
|
});
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
case !!interpolatedTreePath:
|
354
|
-
logTitle += `n entry in ${interpolatedTreePath} for ${chalk.white(releaseVersion.gitTag)}`;
|
355
|
-
break;
|
356
|
-
case config.createRelease === 'github':
|
357
|
-
logTitle += ` GitHub release for ${chalk.white(releaseVersion.gitTag)}`;
|
358
|
-
}
|
359
|
-
output_1.output.log({
|
360
|
-
title: logTitle,
|
361
|
-
});
|
412
|
+
if (interpolatedTreePath) {
|
413
|
+
const prefix = dryRun ? 'Previewing' : 'Generating';
|
414
|
+
output_1.output.log({
|
415
|
+
title: `${prefix} an entry in ${interpolatedTreePath} for ${chalk.white(releaseVersion.gitTag)}`,
|
416
|
+
});
|
417
|
+
}
|
362
418
|
const githubRepoSlug = (0, github_1.getGitHubRepoSlug)(gitRemote);
|
363
419
|
let contents = await changelogRenderer({
|
364
420
|
projectGraph,
|
@@ -382,12 +438,6 @@ async function generateChangelogForWorkspace(tree, args, projectGraph, nxRelease
|
|
382
438
|
await (0, launch_editor_1.launchEditor)(changelogPath);
|
383
439
|
contents = (0, node_fs_1.readFileSync)(changelogPath, 'utf-8');
|
384
440
|
}
|
385
|
-
/**
|
386
|
-
* The exact logic we use for printing the summary/diff to the user is dependent upon whether they are creating
|
387
|
-
* a changelog file, a GitHub release, or both.
|
388
|
-
*/
|
389
|
-
let printSummary = () => { };
|
390
|
-
const noDiffInChangelogMessage = chalk.yellow(`NOTE: There was no diff detected for the changelog entry. Maybe you intended to pass alternative git references via --from and --to?`);
|
391
441
|
if (interpolatedTreePath) {
|
392
442
|
let rootChangelogContents = tree.exists(interpolatedTreePath)
|
393
443
|
? tree.read(interpolatedTreePath).toString()
|
@@ -409,79 +459,12 @@ async function generateChangelogForWorkspace(tree, args, projectGraph, nxRelease
|
|
409
459
|
rootChangelogContents = contents;
|
410
460
|
}
|
411
461
|
tree.write(interpolatedTreePath, rootChangelogContents);
|
412
|
-
|
413
|
-
}
|
414
|
-
if (config.createRelease === 'github') {
|
415
|
-
if (!githubRepoSlug) {
|
416
|
-
output_1.output.error({
|
417
|
-
title: `Unable to create a GitHub release because the GitHub repo slug could not be determined.`,
|
418
|
-
bodyLines: [
|
419
|
-
`Please ensure you have a valid GitHub remote configured. You can run \`git remote -v\` to list your current remotes.`,
|
420
|
-
],
|
421
|
-
});
|
422
|
-
process.exit(1);
|
423
|
-
}
|
424
|
-
const token = await (0, github_1.resolveGithubToken)();
|
425
|
-
const githubRequestConfig = {
|
426
|
-
repo: githubRepoSlug,
|
427
|
-
token,
|
428
|
-
};
|
429
|
-
let existingGithubReleaseForVersion;
|
430
|
-
try {
|
431
|
-
existingGithubReleaseForVersion = await (0, github_1.getGithubReleaseByTag)(githubRequestConfig, releaseVersion.gitTag);
|
432
|
-
}
|
433
|
-
catch (err) {
|
434
|
-
if (err.response?.status === 401) {
|
435
|
-
output_1.output.error({
|
436
|
-
title: `Unable to resolve data via the GitHub API. You can use any of the following options to resolve this:`,
|
437
|
-
bodyLines: [
|
438
|
-
'- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid GitHub token with `repo` scope',
|
439
|
-
'- Have an active session via the official gh CLI tool (https://cli.github.com) in your current terminal',
|
440
|
-
],
|
441
|
-
});
|
442
|
-
process.exit(1);
|
443
|
-
}
|
444
|
-
if (err.response?.status === 404) {
|
445
|
-
// No existing release found, this is fine
|
446
|
-
}
|
447
|
-
else {
|
448
|
-
// Rethrow unknown errors for now
|
449
|
-
throw err;
|
450
|
-
}
|
451
|
-
}
|
452
|
-
let existingPrintSummaryFn = printSummary;
|
453
|
-
printSummary = () => {
|
454
|
-
const logTitle = `https://github.com/${githubRepoSlug}/releases/tag/${releaseVersion.gitTag}`;
|
455
|
-
if (existingGithubReleaseForVersion) {
|
456
|
-
console.error(`${chalk.white('UPDATE')} ${logTitle}${dryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
|
457
|
-
}
|
458
|
-
else {
|
459
|
-
console.error(`${chalk.green('CREATE')} ${logTitle}${dryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
|
460
|
-
}
|
461
|
-
// Only print the diff here if we are not already going to be printing changes from the Tree
|
462
|
-
if (!interpolatedTreePath) {
|
463
|
-
console.log('');
|
464
|
-
(0, print_changes_1.printDiff)(existingGithubReleaseForVersion
|
465
|
-
? existingGithubReleaseForVersion.body
|
466
|
-
: '', contents, 3, noDiffInChangelogMessage);
|
467
|
-
}
|
468
|
-
existingPrintSummaryFn();
|
469
|
-
};
|
470
|
-
// Only schedule the actual GitHub update when not in dry-run mode
|
471
|
-
if (!dryRun) {
|
472
|
-
postGitTasks.push(async (latestCommit) => {
|
473
|
-
// Before we can create/update the release we need to ensure the commit exists on the remote
|
474
|
-
await (0, git_1.gitPush)();
|
475
|
-
await (0, github_1.createOrUpdateGithubRelease)(githubRequestConfig, {
|
476
|
-
version: releaseVersion.gitTag,
|
477
|
-
prerelease: releaseVersion.isPrerelease,
|
478
|
-
body: contents,
|
479
|
-
commit: latestCommit,
|
480
|
-
}, existingGithubReleaseForVersion);
|
481
|
-
});
|
482
|
-
}
|
462
|
+
(0, print_changes_1.printAndFlushChanges)(tree, !!dryRun, 3, false, shared_1.noDiffInChangelogMessage);
|
483
463
|
}
|
484
|
-
|
464
|
+
return {
|
465
|
+
releaseVersion,
|
466
|
+
contents,
|
467
|
+
};
|
485
468
|
}
|
486
469
|
async function generateChangelogForProjects(tree, args, projectGraph, commits, projectsVersionData, postGitTasks, releaseGroup, projects) {
|
487
470
|
const config = releaseGroup.changelog;
|
@@ -494,6 +477,7 @@ async function generateChangelogForProjects(tree, args, projectGraph, commits, p
|
|
494
477
|
const dryRun = !!args.dryRun;
|
495
478
|
const gitRemote = args.gitRemote;
|
496
479
|
const changelogRenderer = resolveChangelogRenderer(config.renderer);
|
480
|
+
const projectChangelogs = {};
|
497
481
|
for (const project of projects) {
|
498
482
|
let interpolatedTreePath = config.file || '';
|
499
483
|
if (interpolatedTreePath) {
|
@@ -515,21 +499,12 @@ async function generateChangelogForProjects(tree, args, projectGraph, commits, p
|
|
515
499
|
releaseTagPattern: releaseGroup.releaseTagPattern,
|
516
500
|
projectName: project.name,
|
517
501
|
});
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
break;
|
524
|
-
case !!interpolatedTreePath:
|
525
|
-
logTitle += `n entry in ${interpolatedTreePath} for ${chalk.white(releaseVersion.gitTag)}`;
|
526
|
-
break;
|
527
|
-
case config.createRelease === 'github':
|
528
|
-
logTitle += ` GitHub release for ${chalk.white(releaseVersion.gitTag)}`;
|
502
|
+
if (interpolatedTreePath) {
|
503
|
+
const prefix = dryRun ? 'Previewing' : 'Generating';
|
504
|
+
output_1.output.log({
|
505
|
+
title: `${prefix} an entry in ${interpolatedTreePath} for ${chalk.white(releaseVersion.gitTag)}`,
|
506
|
+
});
|
529
507
|
}
|
530
|
-
output_1.output.log({
|
531
|
-
title: logTitle,
|
532
|
-
});
|
533
508
|
const githubRepoSlug = config.createRelease === 'github'
|
534
509
|
? (0, github_1.getGitHubRepoSlug)(gitRemote)
|
535
510
|
: undefined;
|
@@ -561,12 +536,6 @@ async function generateChangelogForProjects(tree, args, projectGraph, commits, p
|
|
561
536
|
await (0, launch_editor_1.launchEditor)(changelogPath);
|
562
537
|
contents = (0, node_fs_1.readFileSync)(changelogPath, 'utf-8');
|
563
538
|
}
|
564
|
-
/**
|
565
|
-
* The exact logic we use for printing the summary/diff to the user is dependent upon whether they are creating
|
566
|
-
* a changelog file, a GitHub release, or both.
|
567
|
-
*/
|
568
|
-
let printSummary = () => { };
|
569
|
-
const noDiffInChangelogMessage = chalk.yellow(`NOTE: There was no diff detected for the changelog entry. Maybe you intended to pass alternative git references via --from and --to?`);
|
570
539
|
if (interpolatedTreePath) {
|
571
540
|
let changelogContents = tree.exists(interpolatedTreePath)
|
572
541
|
? tree.read(interpolatedTreePath).toString()
|
@@ -588,82 +557,16 @@ async function generateChangelogForProjects(tree, args, projectGraph, commits, p
|
|
588
557
|
changelogContents = contents;
|
589
558
|
}
|
590
559
|
tree.write(interpolatedTreePath, changelogContents);
|
591
|
-
|
560
|
+
(0, print_changes_1.printAndFlushChanges)(tree, !!dryRun, 3, false, shared_1.noDiffInChangelogMessage,
|
592
561
|
// Only print the change for the current changelog file at this point
|
593
562
|
(f) => f.path === interpolatedTreePath);
|
594
563
|
}
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
bodyLines: [
|
600
|
-
`Please ensure you have a valid GitHub remote configured. You can run \`git remote -v\` to list your current remotes.`,
|
601
|
-
],
|
602
|
-
});
|
603
|
-
process.exit(1);
|
604
|
-
}
|
605
|
-
const token = await (0, github_1.resolveGithubToken)();
|
606
|
-
const githubRequestConfig = {
|
607
|
-
repo: githubRepoSlug,
|
608
|
-
token,
|
609
|
-
};
|
610
|
-
let existingGithubReleaseForVersion;
|
611
|
-
try {
|
612
|
-
existingGithubReleaseForVersion = await (0, github_1.getGithubReleaseByTag)(githubRequestConfig, releaseVersion.gitTag);
|
613
|
-
}
|
614
|
-
catch (err) {
|
615
|
-
if (err.response?.status === 401) {
|
616
|
-
output_1.output.error({
|
617
|
-
title: `Unable to resolve data via the GitHub API. You can use any of the following options to resolve this:`,
|
618
|
-
bodyLines: [
|
619
|
-
'- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid GitHub token with `repo` scope',
|
620
|
-
'- Have an active session via the official gh CLI tool (https://cli.github.com) in your current terminal',
|
621
|
-
],
|
622
|
-
});
|
623
|
-
process.exit(1);
|
624
|
-
}
|
625
|
-
if (err.response?.status === 404) {
|
626
|
-
// No existing release found, this is fine
|
627
|
-
}
|
628
|
-
else {
|
629
|
-
// Rethrow unknown errors for now
|
630
|
-
throw err;
|
631
|
-
}
|
632
|
-
}
|
633
|
-
let existingPrintSummaryFn = printSummary;
|
634
|
-
printSummary = () => {
|
635
|
-
const logTitle = `https://github.com/${githubRepoSlug}/releases/tag/${releaseVersion.gitTag}`;
|
636
|
-
if (existingGithubReleaseForVersion) {
|
637
|
-
console.error(`${chalk.white('UPDATE')} ${logTitle}${dryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
|
638
|
-
}
|
639
|
-
else {
|
640
|
-
console.error(`${chalk.green('CREATE')} ${logTitle}${dryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
|
641
|
-
}
|
642
|
-
// Only print the diff here if we are not already going to be printing changes from the Tree
|
643
|
-
if (!interpolatedTreePath) {
|
644
|
-
console.log('');
|
645
|
-
(0, print_changes_1.printDiff)(existingGithubReleaseForVersion
|
646
|
-
? existingGithubReleaseForVersion.body
|
647
|
-
: '', contents, 3, noDiffInChangelogMessage);
|
648
|
-
}
|
649
|
-
existingPrintSummaryFn();
|
650
|
-
};
|
651
|
-
// Only schedule the actual GitHub update when not in dry-run mode
|
652
|
-
if (!dryRun) {
|
653
|
-
postGitTasks.push(async (latestCommit) => {
|
654
|
-
// Before we can create/update the release we need to ensure the commit exists on the remote
|
655
|
-
await (0, git_1.gitPush)(gitRemote);
|
656
|
-
await (0, github_1.createOrUpdateGithubRelease)(githubRequestConfig, {
|
657
|
-
version: releaseVersion.gitTag,
|
658
|
-
prerelease: releaseVersion.isPrerelease,
|
659
|
-
body: contents,
|
660
|
-
commit: latestCommit,
|
661
|
-
}, existingGithubReleaseForVersion);
|
662
|
-
});
|
663
|
-
}
|
664
|
-
}
|
665
|
-
printSummary();
|
564
|
+
projectChangelogs[project.name] = {
|
565
|
+
releaseVersion,
|
566
|
+
contents,
|
567
|
+
};
|
666
568
|
}
|
569
|
+
return projectChangelogs;
|
667
570
|
}
|
668
571
|
function checkChangelogFilesEnabled(nxReleaseConfig) {
|
669
572
|
if (nxReleaseConfig.changelog.workspaceChangelog &&
|
@@ -690,3 +593,10 @@ async function getCommits(fromSHA, toSHA) {
|
|
690
593
|
return false;
|
691
594
|
});
|
692
595
|
}
|
596
|
+
function shouldCreateGitHubRelease(changelogConfig, createReleaseArg = undefined) {
|
597
|
+
if (createReleaseArg !== undefined) {
|
598
|
+
return createReleaseArg === 'github';
|
599
|
+
}
|
600
|
+
return (changelogConfig || {}).createRelease === 'github';
|
601
|
+
}
|
602
|
+
exports.shouldCreateGitHubRelease = shouldCreateGitHubRelease;
|
@@ -29,6 +29,7 @@ export type ChangelogOptions = NxReleaseArgs & GitCommitAndTagOptions & {
|
|
29
29
|
from?: string;
|
30
30
|
interactive?: string;
|
31
31
|
gitRemote?: string;
|
32
|
+
createRelease?: false | 'github';
|
32
33
|
};
|
33
34
|
export type PublishOptions = NxReleaseArgs & Partial<RunManyOptions> & {
|
34
35
|
outputStyle?: OutputStyle;
|
@@ -7,7 +7,7 @@ const logger_1 = require("../../utils/logger");
|
|
7
7
|
const shared_options_1 = require("../yargs-utils/shared-options");
|
8
8
|
exports.yargsReleaseCommand = {
|
9
9
|
command: 'release',
|
10
|
-
describe: '
|
10
|
+
describe: 'Orchestrate versioning and publishing of applications and libraries',
|
11
11
|
builder: (yargs) => yargs
|
12
12
|
.command(releaseCommand)
|
13
13
|
.command(versionCommand)
|
@@ -11,6 +11,7 @@ const config_1 = require("./config/config");
|
|
11
11
|
const filter_release_groups_1 = require("./config/filter-release-groups");
|
12
12
|
const publish_1 = require("./publish");
|
13
13
|
const git_1 = require("./utils/git");
|
14
|
+
const github_1 = require("./utils/github");
|
14
15
|
const resolve_nx_json_error_message_1 = require("./utils/resolve-nx-json-error-message");
|
15
16
|
const shared_1 = require("./utils/shared");
|
16
17
|
const version_1 = require("./version");
|
@@ -51,13 +52,14 @@ async function release(args) {
|
|
51
52
|
gitCommit: false,
|
52
53
|
gitTag: false,
|
53
54
|
});
|
54
|
-
await (0, changelog_1.releaseChangelog)({
|
55
|
+
const changelogResult = await (0, changelog_1.releaseChangelog)({
|
55
56
|
...args,
|
56
57
|
versionData: versionResult.projectsVersionData,
|
57
58
|
version: versionResult.workspaceVersion,
|
58
59
|
stageChanges: shouldStage,
|
59
60
|
gitCommit: false,
|
60
61
|
gitTag: false,
|
62
|
+
createRelease: false,
|
61
63
|
});
|
62
64
|
const { error: filterError, releaseGroups, releaseGroupToFilteredProjects, } = (0, filter_release_groups_1.filterReleaseGroups)(projectGraph, nxReleaseConfig, args.projects, args.groups);
|
63
65
|
if (filterError) {
|
@@ -90,8 +92,59 @@ async function release(args) {
|
|
90
92
|
});
|
91
93
|
}
|
92
94
|
}
|
93
|
-
|
94
|
-
|
95
|
+
const shouldCreateWorkspaceRelease = (0, changelog_1.shouldCreateGitHubRelease)(nxReleaseConfig.changelog.workspaceChangelog);
|
96
|
+
let hasPushedChanges = false;
|
97
|
+
let latestCommit;
|
98
|
+
if (shouldCreateWorkspaceRelease && changelogResult.workspaceChangelog) {
|
99
|
+
devkit_exports_1.output.logSingleLine(`Pushing to git remote`);
|
100
|
+
// Before we can create/update the release we need to ensure the commit exists on the remote
|
101
|
+
await (0, git_1.gitPush)({
|
102
|
+
dryRun: args.dryRun,
|
103
|
+
verbose: args.verbose,
|
104
|
+
});
|
105
|
+
hasPushedChanges = true;
|
106
|
+
devkit_exports_1.output.logSingleLine(`Creating GitHub Release`);
|
107
|
+
latestCommit = await (0, git_1.getCommitHash)('HEAD');
|
108
|
+
await (0, github_1.createOrUpdateGithubRelease)(changelogResult.workspaceChangelog.releaseVersion, changelogResult.workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
109
|
+
}
|
110
|
+
for (const releaseGroup of releaseGroups) {
|
111
|
+
const shouldCreateProjectReleases = (0, changelog_1.shouldCreateGitHubRelease)(releaseGroup.changelog);
|
112
|
+
if (shouldCreateProjectReleases && changelogResult.projectChangelogs) {
|
113
|
+
const projects = args.projects?.length
|
114
|
+
? // If the user has passed a list of projects, we need to use the filtered list of projects within the release group
|
115
|
+
Array.from(releaseGroupToFilteredProjects.get(releaseGroup))
|
116
|
+
: // Otherwise, we use the full list of projects within the release group
|
117
|
+
releaseGroup.projects;
|
118
|
+
const projectNodes = projects.map((name) => projectGraph.nodes[name]);
|
119
|
+
for (const project of projectNodes) {
|
120
|
+
const changelog = changelogResult.projectChangelogs[project.name];
|
121
|
+
if (!changelog) {
|
122
|
+
continue;
|
123
|
+
}
|
124
|
+
if (!hasPushedChanges) {
|
125
|
+
devkit_exports_1.output.logSingleLine(`Pushing to git remote`);
|
126
|
+
// Before we can create/update the release we need to ensure the commit exists on the remote
|
127
|
+
await (0, git_1.gitPush)({
|
128
|
+
dryRun: args.dryRun,
|
129
|
+
verbose: args.verbose,
|
130
|
+
});
|
131
|
+
hasPushedChanges = true;
|
132
|
+
}
|
133
|
+
devkit_exports_1.output.logSingleLine(`Creating GitHub Release`);
|
134
|
+
if (!latestCommit) {
|
135
|
+
latestCommit = await (0, git_1.getCommitHash)('HEAD');
|
136
|
+
}
|
137
|
+
await (0, github_1.createOrUpdateGithubRelease)(changelog.releaseVersion, changelog.contents, latestCommit, { dryRun: args.dryRun });
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
let hasNewVersion = false;
|
142
|
+
// null means that all projects are versioned together but there were no changes
|
143
|
+
if (versionResult.workspaceVersion !== null) {
|
144
|
+
hasNewVersion = Object.values(versionResult.projectsVersionData).some((version) => version.newVersion !== null);
|
145
|
+
}
|
146
|
+
let shouldPublish = !!args.yes && !args.skipPublish && hasNewVersion;
|
147
|
+
const shouldPromptPublishing = !args.yes && !args.skipPublish && !args.dryRun && hasNewVersion;
|
95
148
|
if (shouldPromptPublishing) {
|
96
149
|
shouldPublish = await promptForPublish();
|
97
150
|
}
|
@@ -48,7 +48,11 @@ export declare function gitTag({ tag, message, additionalArgs, dryRun, verbose,
|
|
48
48
|
verbose?: boolean;
|
49
49
|
logFn?: (message: string) => void;
|
50
50
|
}): Promise<string>;
|
51
|
-
export declare function gitPush(gitRemote
|
51
|
+
export declare function gitPush({ gitRemote, dryRun, verbose, }: {
|
52
|
+
gitRemote?: string;
|
53
|
+
dryRun?: boolean;
|
54
|
+
verbose?: boolean;
|
55
|
+
}): Promise<void>;
|
52
56
|
export declare function parseCommits(commits: RawGitCommit[]): GitCommit[];
|
53
57
|
export declare function parseGitCommit(commit: RawGitCommit): GitCommit | null;
|
54
58
|
export declare function getCommitHash(ref: string): Promise<string>;
|