nx 19.8.0-canary.20240920-999abe9 → 19.9.0-canary.20240921-a510b36
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +12 -12
- package/release/changelog-renderer/index.d.ts +3 -1
- package/release/changelog-renderer/index.js +8 -8
- package/schemas/nx-schema.json +21 -0
- package/src/command-line/release/changelog.js +16 -10
- package/src/command-line/release/config/config.d.ts +2 -1
- package/src/command-line/release/config/config.js +165 -20
- package/src/command-line/release/release.js +6 -2
- package/src/command-line/release/utils/github.d.ts +14 -6
- package/src/command-line/release/utils/github.js +49 -24
- package/src/config/nx-json.d.ts +8 -1
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/styles.js +1 -1
- package/src/native/index.d.ts +1 -1
- package/src/native/nx.wasm32-wasi.wasm +0 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "19.
|
3
|
+
"version": "19.9.0-canary.20240921-a510b36",
|
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": {
|
@@ -68,7 +68,7 @@
|
|
68
68
|
"yargs-parser": "21.1.1",
|
69
69
|
"node-machine-id": "1.1.12",
|
70
70
|
"ora": "5.3.0",
|
71
|
-
"@nrwl/tao": "19.
|
71
|
+
"@nrwl/tao": "19.9.0-canary.20240921-a510b36"
|
72
72
|
},
|
73
73
|
"peerDependencies": {
|
74
74
|
"@swc-node/register": "^1.8.0",
|
@@ -83,16 +83,16 @@
|
|
83
83
|
}
|
84
84
|
},
|
85
85
|
"optionalDependencies": {
|
86
|
-
"@nx/nx-darwin-x64": "19.
|
87
|
-
"@nx/nx-darwin-arm64": "19.
|
88
|
-
"@nx/nx-linux-x64-gnu": "19.
|
89
|
-
"@nx/nx-linux-x64-musl": "19.
|
90
|
-
"@nx/nx-win32-x64-msvc": "19.
|
91
|
-
"@nx/nx-linux-arm64-gnu": "19.
|
92
|
-
"@nx/nx-linux-arm64-musl": "19.
|
93
|
-
"@nx/nx-linux-arm-gnueabihf": "19.
|
94
|
-
"@nx/nx-win32-arm64-msvc": "19.
|
95
|
-
"@nx/nx-freebsd-x64": "19.
|
86
|
+
"@nx/nx-darwin-x64": "19.9.0-canary.20240921-a510b36",
|
87
|
+
"@nx/nx-darwin-arm64": "19.9.0-canary.20240921-a510b36",
|
88
|
+
"@nx/nx-linux-x64-gnu": "19.9.0-canary.20240921-a510b36",
|
89
|
+
"@nx/nx-linux-x64-musl": "19.9.0-canary.20240921-a510b36",
|
90
|
+
"@nx/nx-win32-x64-msvc": "19.9.0-canary.20240921-a510b36",
|
91
|
+
"@nx/nx-linux-arm64-gnu": "19.9.0-canary.20240921-a510b36",
|
92
|
+
"@nx/nx-linux-arm64-musl": "19.9.0-canary.20240921-a510b36",
|
93
|
+
"@nx/nx-linux-arm-gnueabihf": "19.9.0-canary.20240921-a510b36",
|
94
|
+
"@nx/nx-win32-arm64-msvc": "19.9.0-canary.20240921-a510b36",
|
95
|
+
"@nx/nx-freebsd-x64": "19.9.0-canary.20240921-a510b36"
|
96
96
|
},
|
97
97
|
"nx-migrations": {
|
98
98
|
"migrations": "./migrations.json",
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { ChangelogChange } from '../../src/command-line/release/changelog';
|
2
2
|
import { NxReleaseConfig } from '../../src/command-line/release/config/config';
|
3
3
|
import { GitCommit } from '../../src/command-line/release/utils/git';
|
4
|
-
import { RepoSlug } from '../../src/command-line/release/utils/github';
|
4
|
+
import { GithubRepoData, RepoSlug } from '../../src/command-line/release/utils/github';
|
5
5
|
import type { ProjectGraph } from '../../src/config/project-graph';
|
6
6
|
/**
|
7
7
|
* The ChangelogRenderOptions are specific to each ChangelogRenderer implementation, and are taken
|
@@ -30,6 +30,7 @@ export type DependencyBump = {
|
|
30
30
|
* @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
|
31
31
|
* @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
|
32
32
|
* @param {DependencyBump[]} config.dependencyBumps Optional list of additional dependency bumps that occurred as part of the release, outside of the commit data
|
33
|
+
* @param {GithubRepoData} config.repoData Resolved data for the current GitHub repository
|
33
34
|
*/
|
34
35
|
export type ChangelogRenderer = (config: {
|
35
36
|
projectGraph: ProjectGraph;
|
@@ -41,6 +42,7 @@ export type ChangelogRenderer = (config: {
|
|
41
42
|
changelogRenderOptions: DefaultChangelogRenderOptions;
|
42
43
|
dependencyBumps?: DependencyBump[];
|
43
44
|
repoSlug?: RepoSlug;
|
45
|
+
repoData?: GithubRepoData;
|
44
46
|
conventionalCommitsConfig: NxReleaseConfig['conventionalCommits'] | null;
|
45
47
|
}) => Promise<string> | string;
|
46
48
|
/**
|
@@ -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, changes, releaseVersion, project, entryWhenNoChanges, changelogRenderOptions, dependencyBumps, repoSlug, conventionalCommitsConfig, }) => {
|
13
|
+
const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion, project, entryWhenNoChanges, changelogRenderOptions, dependencyBumps, repoSlug, conventionalCommitsConfig, repoData, }) => {
|
14
14
|
const markdownLines = [];
|
15
15
|
// If the current range of changes contains both a commit and its revert, we strip them both from the final list. Changes from version plans are unaffected, as they have no hashes.
|
16
16
|
for (const change of changes) {
|
@@ -46,7 +46,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
46
46
|
if (relevantChanges[i].isBreaking) {
|
47
47
|
const change = relevantChanges[i];
|
48
48
|
additionalChangesForAuthorsSection.push(change);
|
49
|
-
const line = formatChange(change, changelogRenderOptions, isVersionPlans,
|
49
|
+
const line = formatChange(change, changelogRenderOptions, isVersionPlans, repoData);
|
50
50
|
breakingChanges.push(line);
|
51
51
|
relevantChanges.splice(i, 1);
|
52
52
|
}
|
@@ -89,7 +89,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
89
89
|
for (const scope of scopesSortedAlphabetically) {
|
90
90
|
const changes = changesGroupedByScope[scope];
|
91
91
|
for (const change of changes) {
|
92
|
-
const line = formatChange(change, changelogRenderOptions, isVersionPlans,
|
92
|
+
const line = formatChange(change, changelogRenderOptions, isVersionPlans, repoData);
|
93
93
|
markdownLines.push(line);
|
94
94
|
if (change.isBreaking) {
|
95
95
|
const breakingChangeExplanation = extractBreakingChangeExplanation(change.body);
|
@@ -132,7 +132,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
132
132
|
markdownLines.push('', `### ${changeTypes[type].changelog.title}`, '');
|
133
133
|
const changesInChronologicalOrder = group.reverse();
|
134
134
|
for (const change of changesInChronologicalOrder) {
|
135
|
-
const line = formatChange(change, changelogRenderOptions, isVersionPlans,
|
135
|
+
const line = formatChange(change, changelogRenderOptions, isVersionPlans, repoData);
|
136
136
|
markdownLines.push(line + '\n');
|
137
137
|
if (change.isBreaking) {
|
138
138
|
const breakingChangeExplanation = extractBreakingChangeExplanation(change.body);
|
@@ -176,7 +176,7 @@ const defaultChangelogRenderer = async ({ projectGraph, changes, releaseVersion,
|
|
176
176
|
}
|
177
177
|
}
|
178
178
|
// Try to map authors to github usernames
|
179
|
-
if (
|
179
|
+
if (repoData && changelogRenderOptions.mapAuthorsToGitHubUsernames) {
|
180
180
|
await Promise.all([..._authors.keys()].map(async (authorName) => {
|
181
181
|
const meta = _authors.get(authorName);
|
182
182
|
for (const email of meta.email) {
|
@@ -245,7 +245,7 @@ function groupBy(items, key) {
|
|
245
245
|
}
|
246
246
|
return groups;
|
247
247
|
}
|
248
|
-
function formatChange(change, changelogRenderOptions, isVersionPlans,
|
248
|
+
function formatChange(change, changelogRenderOptions, isVersionPlans, repoData) {
|
249
249
|
let description = change.description;
|
250
250
|
let extraLines = [];
|
251
251
|
let extraLinesStr = '';
|
@@ -267,8 +267,8 @@ function formatChange(change, changelogRenderOptions, isVersionPlans, repoSlug)
|
|
267
267
|
(!isVersionPlans && change.isBreaking ? '⚠️ ' : '') +
|
268
268
|
(!isVersionPlans && change.scope ? `**${change.scope.trim()}:** ` : '') +
|
269
269
|
description;
|
270
|
-
if (
|
271
|
-
changeLine += (0, github_1.formatReferences)(change.githubReferences,
|
270
|
+
if (repoData && changelogRenderOptions.commitReferences) {
|
271
|
+
changeLine += (0, github_1.formatReferences)(change.githubReferences, repoData);
|
272
272
|
}
|
273
273
|
if (extraLinesStr) {
|
274
274
|
changeLine += '\n\n' + extraLinesStr;
|
package/schemas/nx-schema.json
CHANGED
@@ -691,6 +691,9 @@
|
|
691
691
|
{
|
692
692
|
"type": "boolean",
|
693
693
|
"enum": [false]
|
694
|
+
},
|
695
|
+
{
|
696
|
+
"$ref": "#/definitions/CreateReleaseProviderConfiguration"
|
694
697
|
}
|
695
698
|
]
|
696
699
|
},
|
@@ -724,6 +727,24 @@
|
|
724
727
|
}
|
725
728
|
}
|
726
729
|
},
|
730
|
+
"CreateReleaseProviderConfiguration": {
|
731
|
+
"type": "object",
|
732
|
+
"properties": {
|
733
|
+
"provider": {
|
734
|
+
"type": "string",
|
735
|
+
"enum": ["github-enterprise-server"]
|
736
|
+
},
|
737
|
+
"hostname": {
|
738
|
+
"type": "string",
|
739
|
+
"description": "The hostname of the VCS provider instance, e.g. github.example.com"
|
740
|
+
},
|
741
|
+
"apiBaseUrl": {
|
742
|
+
"type": "string",
|
743
|
+
"description": "The base URL for the relevant VCS provider API. If not set, this will default to `https://${hostname}/api/v3`"
|
744
|
+
}
|
745
|
+
},
|
746
|
+
"required": ["provider", "hostname"]
|
747
|
+
},
|
727
748
|
"NxReleaseVersionPlansConfiguration": {
|
728
749
|
"type": "object",
|
729
750
|
"properties": {
|
@@ -242,7 +242,9 @@ function createAPI(overrideReleaseConfig) {
|
|
242
242
|
hasPushed = true;
|
243
243
|
}
|
244
244
|
output_1.output.logSingleLine(`Creating GitHub Release`);
|
245
|
-
await (0, github_1.createOrUpdateGithubRelease)(
|
245
|
+
await (0, github_1.createOrUpdateGithubRelease)(nxReleaseConfig.changelog.workspaceChangelog
|
246
|
+
? nxReleaseConfig.changelog.workspaceChangelog.createRelease
|
247
|
+
: config_1.defaultCreateReleaseProvider, workspaceChangelog.releaseVersion, workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
246
248
|
});
|
247
249
|
}
|
248
250
|
/**
|
@@ -401,7 +403,9 @@ function createAPI(overrideReleaseConfig) {
|
|
401
403
|
hasPushed = true;
|
402
404
|
}
|
403
405
|
output_1.output.logSingleLine(`Creating GitHub Release`);
|
404
|
-
await (0, github_1.createOrUpdateGithubRelease)(
|
406
|
+
await (0, github_1.createOrUpdateGithubRelease)(releaseGroup.changelog
|
407
|
+
? releaseGroup.changelog.createRelease
|
408
|
+
: config_1.defaultCreateReleaseProvider, projectChangelog.releaseVersion, projectChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
405
409
|
});
|
406
410
|
}
|
407
411
|
allProjectChangelogs[projectName] = projectChangelog;
|
@@ -516,7 +520,9 @@ function createAPI(overrideReleaseConfig) {
|
|
516
520
|
hasPushed = true;
|
517
521
|
}
|
518
522
|
output_1.output.logSingleLine(`Creating GitHub Release`);
|
519
|
-
await (0, github_1.createOrUpdateGithubRelease)(
|
523
|
+
await (0, github_1.createOrUpdateGithubRelease)(releaseGroup.changelog
|
524
|
+
? releaseGroup.changelog.createRelease
|
525
|
+
: config_1.defaultCreateReleaseProvider, projectChangelog.releaseVersion, projectChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
520
526
|
});
|
521
527
|
}
|
522
528
|
allProjectChangelogs[projectName] = projectChangelog;
|
@@ -730,14 +736,15 @@ async function generateChangelogForWorkspace({ tree, args, projectGraph, nxRelea
|
|
730
736
|
title: `${prefix} an entry in ${interpolatedTreePath} for ${chalk.white(releaseVersion.gitTag)}`,
|
731
737
|
});
|
732
738
|
}
|
733
|
-
const
|
739
|
+
const githubRepoData = (0, github_1.getGitHubRepoData)(gitRemote, config.createRelease);
|
734
740
|
let contents = await changelogRenderer({
|
735
741
|
projectGraph,
|
736
742
|
changes,
|
737
743
|
commits,
|
738
744
|
releaseVersion: releaseVersion.rawVersion,
|
739
745
|
project: null,
|
740
|
-
repoSlug:
|
746
|
+
repoSlug: githubRepoData?.slug,
|
747
|
+
repoData: githubRepoData,
|
741
748
|
entryWhenNoChanges: config.entryWhenNoChanges,
|
742
749
|
changelogRenderOptions: config.renderOptions,
|
743
750
|
conventionalCommitsConfig: nxReleaseConfig.conventionalCommits,
|
@@ -822,16 +829,15 @@ async function generateChangelogForProjects({ tree, args, projectGraph, changes,
|
|
822
829
|
title: `${prefix} an entry in ${interpolatedTreePath} for ${chalk.white(releaseVersion.gitTag)}`,
|
823
830
|
});
|
824
831
|
}
|
825
|
-
const
|
826
|
-
? (0, github_1.getGitHubRepoSlug)(gitRemote)
|
827
|
-
: undefined;
|
832
|
+
const githubRepoData = (0, github_1.getGitHubRepoData)(gitRemote, config.createRelease);
|
828
833
|
let contents = await changelogRenderer({
|
829
834
|
projectGraph,
|
830
835
|
changes,
|
831
836
|
commits,
|
832
837
|
releaseVersion: releaseVersion.rawVersion,
|
833
838
|
project: project.name,
|
834
|
-
repoSlug:
|
839
|
+
repoSlug: githubRepoData?.slug,
|
840
|
+
repoData: githubRepoData,
|
835
841
|
entryWhenNoChanges: typeof config.entryWhenNoChanges === 'string'
|
836
842
|
? (0, utils_1.interpolate)(config.entryWhenNoChanges, {
|
837
843
|
projectName: project.name,
|
@@ -937,7 +943,7 @@ function shouldCreateGitHubRelease(changelogConfig, createReleaseArg = undefined
|
|
937
943
|
if (createReleaseArg !== undefined) {
|
938
944
|
return createReleaseArg === 'github';
|
939
945
|
}
|
940
|
-
return (changelogConfig || {}).createRelease
|
946
|
+
return (changelogConfig || {}).createRelease !== false;
|
941
947
|
}
|
942
948
|
async function promptForGitHubRelease() {
|
943
949
|
try {
|
@@ -42,7 +42,7 @@ export type NxReleaseConfig = Omit<DeepRequired<NxJsonConfiguration['release'] &
|
|
42
42
|
};
|
43
43
|
}>, 'projects'>;
|
44
44
|
export interface CreateNxReleaseConfigError {
|
45
|
-
code: 'PROJECTS_AND_GROUPS_DEFINED' | 'RELEASE_GROUP_MATCHES_NO_PROJECTS' | 'RELEASE_GROUP_RELEASE_TAG_PATTERN_VERSION_PLACEHOLDER_MISSING_OR_EXCESSIVE' | 'PROJECT_MATCHES_MULTIPLE_GROUPS' | 'CONVENTIONAL_COMMITS_SHORTHAND_MIXED_WITH_OVERLAPPING_GENERATOR_OPTIONS' | 'GLOBAL_GIT_CONFIG_MIXED_WITH_GRANULAR_GIT_CONFIG';
|
45
|
+
code: 'PROJECTS_AND_GROUPS_DEFINED' | 'RELEASE_GROUP_MATCHES_NO_PROJECTS' | 'RELEASE_GROUP_RELEASE_TAG_PATTERN_VERSION_PLACEHOLDER_MISSING_OR_EXCESSIVE' | 'PROJECT_MATCHES_MULTIPLE_GROUPS' | 'CONVENTIONAL_COMMITS_SHORTHAND_MIXED_WITH_OVERLAPPING_GENERATOR_OPTIONS' | 'GLOBAL_GIT_CONFIG_MIXED_WITH_GRANULAR_GIT_CONFIG' | 'CANNOT_RESOLVE_CHANGELOG_RENDERER' | 'INVALID_CHANGELOG_CREATE_RELEASE_PROVIDER' | 'INVALID_CHANGELOG_CREATE_RELEASE_HOSTNAME' | 'INVALID_CHANGELOG_CREATE_RELEASE_API_BASE_URL';
|
46
46
|
data: Record<string, string | string[]>;
|
47
47
|
}
|
48
48
|
export declare function createNxReleaseConfig(projectGraph: ProjectGraph, projectFileMap: ProjectFileMap, userConfig?: NxJsonConfiguration['release']): Promise<{
|
@@ -50,4 +50,5 @@ export declare function createNxReleaseConfig(projectGraph: ProjectGraph, projec
|
|
50
50
|
nxReleaseConfig: NxReleaseConfig | null;
|
51
51
|
}>;
|
52
52
|
export declare function handleNxReleaseConfigError(error: CreateNxReleaseConfigError): Promise<never>;
|
53
|
+
export declare const defaultCreateReleaseProvider: any;
|
53
54
|
export {};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.IMPLICIT_DEFAULT_RELEASE_GROUP = void 0;
|
3
|
+
exports.defaultCreateReleaseProvider = exports.IMPLICIT_DEFAULT_RELEASE_GROUP = void 0;
|
4
4
|
exports.createNxReleaseConfig = createNxReleaseConfig;
|
5
5
|
exports.handleNxReleaseConfigError = handleNxReleaseConfigError;
|
6
6
|
/**
|
@@ -17,6 +17,7 @@ exports.handleNxReleaseConfigError = handleNxReleaseConfigError;
|
|
17
17
|
* and easy to consume config object for all the `nx release` command implementations.
|
18
18
|
*/
|
19
19
|
const node_path_1 = require("node:path");
|
20
|
+
const node_url_1 = require("node:url");
|
20
21
|
const fileutils_1 = require("../../../utils/fileutils");
|
21
22
|
const find_matching_projects_1 = require("../../../utils/find-matching-projects");
|
22
23
|
const output_1 = require("../../../utils/output");
|
@@ -368,7 +369,13 @@ async function createNxReleaseConfig(projectGraph, projectFileMap, userConfig =
|
|
368
369
|
}
|
369
370
|
releaseGroups[releaseGroupName] = finalReleaseGroup;
|
370
371
|
}
|
371
|
-
|
372
|
+
const configError = validateChangelogConfig(releaseGroups, rootChangelogConfig);
|
373
|
+
if (configError) {
|
374
|
+
return {
|
375
|
+
error: configError,
|
376
|
+
nxReleaseConfig: null,
|
377
|
+
};
|
378
|
+
}
|
372
379
|
return {
|
373
380
|
error: null,
|
374
381
|
nxReleaseConfig: {
|
@@ -547,6 +554,48 @@ async function handleNxReleaseConfigError(error) {
|
|
547
554
|
});
|
548
555
|
}
|
549
556
|
break;
|
557
|
+
case 'CANNOT_RESOLVE_CHANGELOG_RENDERER': {
|
558
|
+
const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)(['release']);
|
559
|
+
output_1.output.error({
|
560
|
+
title: `There was an error when resolving the configured changelog renderer at path: ${error.data.workspaceRelativePath}`,
|
561
|
+
bodyLines: [nxJsonMessage],
|
562
|
+
});
|
563
|
+
}
|
564
|
+
case 'INVALID_CHANGELOG_CREATE_RELEASE_PROVIDER':
|
565
|
+
{
|
566
|
+
const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)([
|
567
|
+
'release',
|
568
|
+
]);
|
569
|
+
output_1.output.error({
|
570
|
+
title: `Your "changelog.createRelease" config specifies an unsupported provider "${error.data.provider}". The supported providers are ${error.data.supportedProviders
|
571
|
+
.map((p) => `"${p}"`)
|
572
|
+
.join(', ')}`,
|
573
|
+
bodyLines: [nxJsonMessage],
|
574
|
+
});
|
575
|
+
}
|
576
|
+
break;
|
577
|
+
case 'INVALID_CHANGELOG_CREATE_RELEASE_HOSTNAME':
|
578
|
+
{
|
579
|
+
const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)([
|
580
|
+
'release',
|
581
|
+
]);
|
582
|
+
output_1.output.error({
|
583
|
+
title: `Your "changelog.createRelease" config specifies an invalid hostname "${error.data.hostname}". Please ensure you provide a valid hostname value, such as "example.com"`,
|
584
|
+
bodyLines: [nxJsonMessage],
|
585
|
+
});
|
586
|
+
}
|
587
|
+
break;
|
588
|
+
case 'INVALID_CHANGELOG_CREATE_RELEASE_API_BASE_URL':
|
589
|
+
{
|
590
|
+
const nxJsonMessage = await (0, resolve_nx_json_error_message_1.resolveNxJsonConfigErrorMessage)([
|
591
|
+
'release',
|
592
|
+
]);
|
593
|
+
output_1.output.error({
|
594
|
+
title: `Your "changelog.createRelease" config specifies an invalid apiBaseUrl "${error.data.apiBaseUrl}". Please ensure you provide a valid URL value, such as "https://example.com"`,
|
595
|
+
bodyLines: [nxJsonMessage],
|
596
|
+
});
|
597
|
+
}
|
598
|
+
break;
|
550
599
|
default:
|
551
600
|
throw new Error(`Unhandled error code: ${error.code}`);
|
552
601
|
}
|
@@ -678,42 +727,138 @@ function isProjectPublic(project, projectGraph, projectFileMap) {
|
|
678
727
|
return false;
|
679
728
|
}
|
680
729
|
}
|
681
|
-
|
730
|
+
/**
|
731
|
+
* We need to ensure that changelog renderers are resolvable up front so that we do not end up erroring after performing
|
732
|
+
* actions later, and we also make sure that any configured createRelease options are valid.
|
733
|
+
*
|
734
|
+
* For the createRelease config, we also set a default apiBaseUrl if applicable.
|
735
|
+
*/
|
736
|
+
function validateChangelogConfig(releaseGroups, rootChangelogConfig) {
|
682
737
|
/**
|
683
738
|
* If any form of changelog config is enabled, ensure that any provided changelog renderers are resolvable
|
684
739
|
* up front so that we do not end up erroring only after the versioning step has been completed.
|
685
740
|
*/
|
686
741
|
const uniqueRendererPaths = new Set();
|
687
742
|
if (rootChangelogConfig.workspaceChangelog &&
|
688
|
-
typeof rootChangelogConfig.workspaceChangelog !== 'boolean'
|
689
|
-
rootChangelogConfig.workspaceChangelog.renderer?.length) {
|
690
|
-
|
743
|
+
typeof rootChangelogConfig.workspaceChangelog !== 'boolean') {
|
744
|
+
if (rootChangelogConfig.workspaceChangelog.renderer?.length) {
|
745
|
+
uniqueRendererPaths.add(rootChangelogConfig.workspaceChangelog.renderer);
|
746
|
+
}
|
747
|
+
const createReleaseError = validateCreateReleaseConfig(rootChangelogConfig.workspaceChangelog);
|
748
|
+
if (createReleaseError) {
|
749
|
+
return createReleaseError;
|
750
|
+
}
|
691
751
|
}
|
692
752
|
if (rootChangelogConfig.projectChangelogs &&
|
693
|
-
typeof rootChangelogConfig.projectChangelogs !== 'boolean'
|
694
|
-
rootChangelogConfig.projectChangelogs.renderer?.length) {
|
695
|
-
|
753
|
+
typeof rootChangelogConfig.projectChangelogs !== 'boolean') {
|
754
|
+
if (rootChangelogConfig.projectChangelogs.renderer?.length) {
|
755
|
+
uniqueRendererPaths.add(rootChangelogConfig.projectChangelogs.renderer);
|
756
|
+
}
|
757
|
+
const createReleaseError = validateCreateReleaseConfig(rootChangelogConfig.projectChangelogs);
|
758
|
+
if (createReleaseError) {
|
759
|
+
return createReleaseError;
|
760
|
+
}
|
696
761
|
}
|
697
762
|
for (const group of Object.values(releaseGroups)) {
|
698
|
-
if (group.changelog &&
|
699
|
-
|
700
|
-
|
701
|
-
|
763
|
+
if (group.changelog && typeof group.changelog !== 'boolean') {
|
764
|
+
if (group.changelog.renderer?.length) {
|
765
|
+
uniqueRendererPaths.add(group.changelog.renderer);
|
766
|
+
}
|
767
|
+
const createReleaseError = validateCreateReleaseConfig(group.changelog);
|
768
|
+
if (createReleaseError) {
|
769
|
+
return createReleaseError;
|
770
|
+
}
|
702
771
|
}
|
703
772
|
}
|
704
773
|
if (!uniqueRendererPaths.size) {
|
705
|
-
return;
|
774
|
+
return null;
|
706
775
|
}
|
707
776
|
for (const rendererPath of uniqueRendererPaths) {
|
708
777
|
try {
|
709
778
|
(0, resolve_changelog_renderer_1.resolveChangelogRenderer)(rendererPath);
|
710
779
|
}
|
711
|
-
catch
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
780
|
+
catch {
|
781
|
+
return {
|
782
|
+
code: 'CANNOT_RESOLVE_CHANGELOG_RENDERER',
|
783
|
+
data: {
|
784
|
+
workspaceRelativePath: (0, node_path_1.relative)(workspace_root_1.workspaceRoot, rendererPath),
|
785
|
+
},
|
786
|
+
};
|
717
787
|
}
|
718
788
|
}
|
789
|
+
return null;
|
790
|
+
}
|
791
|
+
const supportedCreateReleaseProviders = [
|
792
|
+
{
|
793
|
+
name: 'github-enterprise-server',
|
794
|
+
defaultApiBaseUrl: 'https://__hostname__/api/v3',
|
795
|
+
},
|
796
|
+
];
|
797
|
+
// User opts into the default by specifying the string value 'github'
|
798
|
+
exports.defaultCreateReleaseProvider = {
|
799
|
+
provider: 'github',
|
800
|
+
hostname: 'github.com',
|
801
|
+
apiBaseUrl: 'https://api.github.com',
|
802
|
+
};
|
803
|
+
function validateCreateReleaseConfig(changelogConfig) {
|
804
|
+
const createRelease = changelogConfig.createRelease;
|
805
|
+
// Disabled: valid
|
806
|
+
if (!createRelease) {
|
807
|
+
return null;
|
808
|
+
}
|
809
|
+
// GitHub shorthand, expand to full object form, mark as valid
|
810
|
+
if (createRelease === 'github') {
|
811
|
+
changelogConfig.createRelease = exports.defaultCreateReleaseProvider;
|
812
|
+
return null;
|
813
|
+
}
|
814
|
+
// Object config, ensure that properties are valid
|
815
|
+
const supportedProvider = supportedCreateReleaseProviders.find((p) => p.name === createRelease.provider);
|
816
|
+
if (!supportedProvider) {
|
817
|
+
return {
|
818
|
+
code: 'INVALID_CHANGELOG_CREATE_RELEASE_PROVIDER',
|
819
|
+
data: {
|
820
|
+
provider: createRelease.provider,
|
821
|
+
supportedProviders: supportedCreateReleaseProviders.map((p) => p.name),
|
822
|
+
},
|
823
|
+
};
|
824
|
+
}
|
825
|
+
if (!isValidHostname(createRelease.hostname)) {
|
826
|
+
return {
|
827
|
+
code: 'INVALID_CHANGELOG_CREATE_RELEASE_HOSTNAME',
|
828
|
+
data: {
|
829
|
+
hostname: createRelease.hostname,
|
830
|
+
},
|
831
|
+
};
|
832
|
+
}
|
833
|
+
// user provided a custom apiBaseUrl, ensure it is valid (accounting for empty string case)
|
834
|
+
if (createRelease.apiBaseUrl ||
|
835
|
+
typeof createRelease.apiBaseUrl === 'string') {
|
836
|
+
if (!isValidUrl(createRelease.apiBaseUrl)) {
|
837
|
+
return {
|
838
|
+
code: 'INVALID_CHANGELOG_CREATE_RELEASE_API_BASE_URL',
|
839
|
+
data: {
|
840
|
+
apiBaseUrl: createRelease.apiBaseUrl,
|
841
|
+
},
|
842
|
+
};
|
843
|
+
}
|
844
|
+
}
|
845
|
+
else {
|
846
|
+
// Set default apiBaseUrl when not provided by the user
|
847
|
+
createRelease.apiBaseUrl = supportedProvider.defaultApiBaseUrl.replace('__hostname__', createRelease.hostname);
|
848
|
+
}
|
849
|
+
return null;
|
850
|
+
}
|
851
|
+
function isValidHostname(hostname) {
|
852
|
+
// Regular expression to match a valid hostname
|
853
|
+
const hostnameRegex = /^(?!:\/\/)(?=.{1,255}$)(?!.*\.$)(?!.*?\.\.)(?!.*?-$)(?!^-)([a-zA-Z0-9-]{1,63}\.?)+[a-zA-Z]{2,}$/;
|
854
|
+
return hostnameRegex.test(hostname);
|
855
|
+
}
|
856
|
+
function isValidUrl(str) {
|
857
|
+
try {
|
858
|
+
new node_url_1.URL(str);
|
859
|
+
return true;
|
860
|
+
}
|
861
|
+
catch {
|
862
|
+
return false;
|
863
|
+
}
|
719
864
|
}
|
@@ -168,7 +168,9 @@ function createAPI(overrideReleaseConfig) {
|
|
168
168
|
hasPushedChanges = true;
|
169
169
|
output_1.output.logSingleLine(`Creating GitHub Release`);
|
170
170
|
latestCommit = await (0, git_1.getCommitHash)('HEAD');
|
171
|
-
await (0, github_1.createOrUpdateGithubRelease)(
|
171
|
+
await (0, github_1.createOrUpdateGithubRelease)(nxReleaseConfig.changelog.workspaceChangelog
|
172
|
+
? nxReleaseConfig.changelog.workspaceChangelog.createRelease
|
173
|
+
: false, changelogResult.workspaceChangelog.releaseVersion, changelogResult.workspaceChangelog.contents, latestCommit, { dryRun: args.dryRun });
|
172
174
|
}
|
173
175
|
for (const releaseGroup of releaseGroups) {
|
174
176
|
const shouldCreateProjectReleases = (0, changelog_1.shouldCreateGitHubRelease)(releaseGroup.changelog);
|
@@ -197,7 +199,9 @@ function createAPI(overrideReleaseConfig) {
|
|
197
199
|
if (!latestCommit) {
|
198
200
|
latestCommit = await (0, git_1.getCommitHash)('HEAD');
|
199
201
|
}
|
200
|
-
await (0, github_1.createOrUpdateGithubRelease)(
|
202
|
+
await (0, github_1.createOrUpdateGithubRelease)(releaseGroup.changelog
|
203
|
+
? releaseGroup.changelog.createRelease
|
204
|
+
: false, changelog.releaseVersion, changelog.contents, latestCommit, { dryRun: args.dryRun });
|
201
205
|
}
|
202
206
|
}
|
203
207
|
}
|
@@ -1,11 +1,14 @@
|
|
1
|
+
import { NxReleaseChangelogConfiguration } from '../../../config/nx-json';
|
1
2
|
import { Reference } from './git';
|
2
3
|
import { ReleaseVersion } from './shared';
|
3
4
|
export type RepoSlug = `${string}/${string}`;
|
4
|
-
|
5
|
+
interface GithubRequestConfig {
|
5
6
|
repo: string;
|
7
|
+
hostname: string;
|
8
|
+
apiBaseUrl: string;
|
6
9
|
token: string | null;
|
7
10
|
}
|
8
|
-
|
11
|
+
interface GithubRelease {
|
9
12
|
id?: string;
|
10
13
|
tag_name: string;
|
11
14
|
target_commitish?: string;
|
@@ -14,10 +17,15 @@ export interface GithubRelease {
|
|
14
17
|
draft?: boolean;
|
15
18
|
prerelease?: boolean;
|
16
19
|
}
|
17
|
-
export
|
18
|
-
|
20
|
+
export interface GithubRepoData {
|
21
|
+
hostname: string;
|
22
|
+
slug: RepoSlug;
|
23
|
+
apiBaseUrl: string;
|
24
|
+
}
|
25
|
+
export declare function getGitHubRepoData(remoteName: string, createReleaseConfig: NxReleaseChangelogConfiguration['createRelease']): GithubRepoData | null;
|
26
|
+
export declare function createOrUpdateGithubRelease(createReleaseConfig: NxReleaseChangelogConfiguration['createRelease'], releaseVersion: ReleaseVersion, changelogContents: string, latestCommit: string, { dryRun }: {
|
19
27
|
dryRun: boolean;
|
20
28
|
}): Promise<void>;
|
21
|
-
export declare function resolveGithubToken(): Promise<string | null>;
|
22
29
|
export declare function getGithubReleaseByTag(config: GithubRequestConfig, tag: string): Promise<GithubRelease>;
|
23
|
-
export declare function formatReferences(references: Reference[],
|
30
|
+
export declare function formatReferences(references: Reference[], repoData: GithubRepoData): string;
|
31
|
+
export {};
|