nx 19.8.0-canary.20240920-999abe9 → 19.8.1
Sign up to get free protection for your applications and to get access to all the features.
- package/.eslintrc.json +2 -1
- package/bin/nx.js +10 -2
- 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 +47 -21
- package/src/adapter/compat.d.ts +1 -1
- package/src/adapter/compat.js +1 -0
- package/src/command-line/activate-powerpack/activate-powerpack.js +3 -1
- package/src/command-line/add/add.js +4 -2
- package/src/command-line/connect/view-logs.js +1 -0
- package/src/command-line/exec/exec.js +6 -1
- package/src/command-line/format/format.js +3 -1
- package/src/command-line/graph/graph.js +1 -0
- package/src/command-line/init/implementation/angular/integrated-workspace.js +4 -1
- package/src/command-line/init/implementation/angular/legacy-angular-versions.js +5 -2
- package/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +3 -1
- package/src/command-line/init/implementation/dot-nx/nxw.js +1 -0
- package/src/command-line/init/implementation/react/check-for-uncommitted-changes.js +3 -1
- package/src/command-line/init/implementation/react/index.js +17 -5
- package/src/command-line/init/implementation/utils.js +5 -1
- package/src/command-line/init/init-v1.js +1 -0
- package/src/command-line/init/init-v2.js +2 -1
- package/src/command-line/migrate/command-object.js +4 -0
- package/src/command-line/migrate/migrate.js +1 -1
- 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/config/version-plans.js +3 -1
- package/src/command-line/release/release.js +6 -2
- package/src/command-line/release/utils/exec-command.js +1 -0
- package/src/command-line/release/utils/github.d.ts +14 -6
- package/src/command-line/release/utils/github.js +50 -24
- package/src/command-line/release/utils/launch-editor.js +6 -1
- package/src/command-line/release/version.js +6 -3
- package/src/command-line/report/report.d.ts +3 -1
- package/src/command-line/report/report.js +17 -2
- package/src/command-line/run/run.js +1 -0
- package/src/command-line/sync/sync.js +5 -4
- package/src/command-line/watch/watch.js +1 -0
- package/src/config/nx-json.d.ts +12 -1
- package/src/core/graph/main.js +1 -1
- package/src/core/graph/styles.js +1 -1
- package/src/daemon/client/client.d.ts +4 -1
- package/src/daemon/client/generate-help-output.js +1 -0
- package/src/daemon/server/sync-generators.d.ts +4 -1
- package/src/daemon/server/sync-generators.js +33 -15
- package/src/executors/run-commands/run-commands.impl.js +1 -0
- package/src/executors/run-script/run-script.impl.js +1 -0
- package/src/native/index.d.ts +1 -1
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +1 -1
- package/src/project-graph/file-utils.js +1 -0
- package/src/tasks-runner/cache.d.ts +3 -1
- package/src/tasks-runner/cache.js +12 -13
- package/src/tasks-runner/default-tasks-runner.js +1 -1
- package/src/tasks-runner/life-cycles/formatting-utils.d.ts +1 -1
- package/src/tasks-runner/life-cycles/formatting-utils.js +27 -15
- package/src/tasks-runner/life-cycles/task-history-life-cycle.js +3 -0
- package/src/tasks-runner/task-orchestrator.d.ts +3 -1
- package/src/tasks-runner/task-orchestrator.js +3 -2
- package/src/tasks-runner/tasks-schedule.js +1 -1
- package/src/utils/ab-testing.js +4 -1
- package/src/utils/child-process.js +5 -3
- package/src/utils/command-line-utils.js +7 -1
- package/src/utils/default-base.js +5 -2
- package/src/utils/git-utils.index-filter.js +2 -1
- package/src/utils/git-utils.js +4 -0
- package/src/utils/git-utils.tree-filter.js +3 -1
- package/src/utils/powerpack.d.ts +1 -1
- package/src/utils/powerpack.js +3 -8
- package/src/utils/sync-generators.d.ts +13 -3
- package/src/utils/sync-generators.js +99 -25
- package/src/utils/task-history.d.ts +2 -2
- package/src/utils/task-history.js +4 -1
@@ -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
|
}
|
@@ -191,7 +191,9 @@ function isReleaseType(value) {
|
|
191
191
|
}
|
192
192
|
async function getCommitForVersionPlanFile(rawVersionPlan, isVerbose) {
|
193
193
|
return new Promise((resolve) => {
|
194
|
-
(0, node_child_process_1.exec)(`git log --diff-filter=A --pretty=format:"%s|%h|%an|%ae|%b" -n 1 -- ${rawVersionPlan.absolutePath}`,
|
194
|
+
(0, node_child_process_1.exec)(`git log --diff-filter=A --pretty=format:"%s|%h|%an|%ae|%b" -n 1 -- ${rawVersionPlan.absolutePath}`, {
|
195
|
+
windowsHide: true,
|
196
|
+
}, (error, stdout, stderr) => {
|
195
197
|
if (error) {
|
196
198
|
if (isVerbose) {
|
197
199
|
console.error(`Error executing git command for ${rawVersionPlan.relativePath}: ${error.message}`);
|
@@ -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 {};
|
@@ -1,8 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.getGitHubRepoData = getGitHubRepoData;
|
4
4
|
exports.createOrUpdateGithubRelease = createOrUpdateGithubRelease;
|
5
|
-
exports.resolveGithubToken = resolveGithubToken;
|
6
5
|
exports.getGithubReleaseByTag = getGithubReleaseByTag;
|
7
6
|
exports.formatReferences = formatReferences;
|
8
7
|
const chalk = require("chalk");
|
@@ -12,22 +11,38 @@ const node_fs_1 = require("node:fs");
|
|
12
11
|
const node_os_1 = require("node:os");
|
13
12
|
const output_1 = require("../../../utils/output");
|
14
13
|
const path_1 = require("../../../utils/path");
|
14
|
+
const config_1 = require("../config/config");
|
15
15
|
const print_changes_1 = require("./print-changes");
|
16
16
|
const shared_1 = require("./shared");
|
17
17
|
// axios types and values don't seem to match
|
18
18
|
const _axios = require("axios");
|
19
19
|
const axios = _axios;
|
20
|
-
function
|
20
|
+
function getGitHubRepoData(remoteName = 'origin', createReleaseConfig) {
|
21
21
|
try {
|
22
22
|
const remoteUrl = (0, node_child_process_1.execSync)(`git remote get-url ${remoteName}`, {
|
23
23
|
encoding: 'utf8',
|
24
24
|
stdio: 'pipe',
|
25
25
|
}).trim();
|
26
|
+
// Use the default provider (github.com) if custom one is not specified or releases are disabled
|
27
|
+
let hostname = config_1.defaultCreateReleaseProvider.hostname;
|
28
|
+
let apiBaseUrl = config_1.defaultCreateReleaseProvider.apiBaseUrl;
|
29
|
+
if (createReleaseConfig !== false &&
|
30
|
+
typeof createReleaseConfig !== 'string') {
|
31
|
+
hostname = createReleaseConfig.hostname;
|
32
|
+
apiBaseUrl = createReleaseConfig.apiBaseUrl;
|
33
|
+
}
|
26
34
|
// Extract the 'user/repo' part from the URL
|
27
|
-
const
|
35
|
+
const escapedHostname = hostname.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
36
|
+
const regexString = `${escapedHostname}[/:]([\\w.-]+/[\\w.-]+)(\\.git)?`;
|
37
|
+
const regex = new RegExp(regexString);
|
28
38
|
const match = remoteUrl.match(regex);
|
29
39
|
if (match && match[1]) {
|
30
|
-
return
|
40
|
+
return {
|
41
|
+
hostname,
|
42
|
+
apiBaseUrl,
|
43
|
+
// Ensure any trailing .git is stripped
|
44
|
+
slug: match[1].replace(/\.git$/, ''),
|
45
|
+
};
|
31
46
|
}
|
32
47
|
else {
|
33
48
|
throw new Error(`Could not extract "user/repo" data from the resolved remote URL: ${remoteUrl}`);
|
@@ -37,9 +52,9 @@ function getGitHubRepoSlug(remoteName = 'origin') {
|
|
37
52
|
return null;
|
38
53
|
}
|
39
54
|
}
|
40
|
-
async function createOrUpdateGithubRelease(releaseVersion, changelogContents, latestCommit, { dryRun }) {
|
41
|
-
const
|
42
|
-
if (!
|
55
|
+
async function createOrUpdateGithubRelease(createReleaseConfig, releaseVersion, changelogContents, latestCommit, { dryRun }) {
|
56
|
+
const githubRepoData = getGitHubRepoData(undefined, createReleaseConfig);
|
57
|
+
if (!githubRepoData) {
|
43
58
|
output_1.output.error({
|
44
59
|
title: `Unable to create a GitHub release because the GitHub repo slug could not be determined.`,
|
45
60
|
bodyLines: [
|
@@ -48,9 +63,11 @@ async function createOrUpdateGithubRelease(releaseVersion, changelogContents, la
|
|
48
63
|
});
|
49
64
|
process.exit(1);
|
50
65
|
}
|
51
|
-
const token = await resolveGithubToken();
|
66
|
+
const token = await resolveGithubToken(githubRepoData.hostname);
|
52
67
|
const githubRequestConfig = {
|
53
|
-
repo:
|
68
|
+
repo: githubRepoData.slug,
|
69
|
+
hostname: githubRepoData.hostname,
|
70
|
+
apiBaseUrl: githubRepoData.apiBaseUrl,
|
54
71
|
token,
|
55
72
|
};
|
56
73
|
let existingGithubReleaseForVersion;
|
@@ -76,7 +93,7 @@ async function createOrUpdateGithubRelease(releaseVersion, changelogContents, la
|
|
76
93
|
throw err;
|
77
94
|
}
|
78
95
|
}
|
79
|
-
const logTitle = `https
|
96
|
+
const logTitle = `https://${githubRepoData.hostname}/${githubRepoData.slug}/releases/tag/${releaseVersion.gitTag}`;
|
80
97
|
if (existingGithubReleaseForVersion) {
|
81
98
|
console.error(`${chalk.white('UPDATE')} ${logTitle}${dryRun ? chalk.keyword('orange')(' [dry-run]') : ''}`);
|
82
99
|
}
|
@@ -215,7 +232,7 @@ async function syncGithubRelease(githubRequestConfig, release, existingGithubRel
|
|
215
232
|
};
|
216
233
|
}
|
217
234
|
}
|
218
|
-
async function resolveGithubToken() {
|
235
|
+
async function resolveGithubToken(hostname) {
|
219
236
|
// Try and resolve from the environment
|
220
237
|
const tokenFromEnv = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
221
238
|
if (tokenFromEnv) {
|
@@ -227,21 +244,25 @@ async function resolveGithubToken() {
|
|
227
244
|
const yamlContents = await node_fs_1.promises.readFile(ghCLIPath, 'utf8');
|
228
245
|
const { load } = require('@zkochan/js-yaml');
|
229
246
|
const ghCLIConfig = load(yamlContents);
|
230
|
-
if (ghCLIConfig[
|
247
|
+
if (ghCLIConfig[hostname]) {
|
231
248
|
// Web based session (the token is already embedded in the config)
|
232
|
-
if (ghCLIConfig[
|
233
|
-
return ghCLIConfig[
|
249
|
+
if (ghCLIConfig[hostname].oauth_token) {
|
250
|
+
return ghCLIConfig[hostname].oauth_token;
|
234
251
|
}
|
235
252
|
// SSH based session (we need to dynamically resolve a token using the CLI)
|
236
|
-
if (ghCLIConfig[
|
237
|
-
ghCLIConfig[
|
253
|
+
if (ghCLIConfig[hostname].user &&
|
254
|
+
ghCLIConfig[hostname].git_protocol === 'ssh') {
|
238
255
|
return (0, node_child_process_1.execSync)(`gh auth token`, {
|
239
256
|
encoding: 'utf8',
|
240
257
|
stdio: 'pipe',
|
258
|
+
windowsHide: true,
|
241
259
|
}).trim();
|
242
260
|
}
|
243
261
|
}
|
244
262
|
}
|
263
|
+
if (hostname !== 'github.com') {
|
264
|
+
console.log(`Warning: It was not possible to automatically resolve a GitHub token from your environment for hostname ${hostname}. If you set the GITHUB_TOKEN or GH_TOKEN environment variable, that will be used for GitHub API requests.`);
|
265
|
+
}
|
245
266
|
return null;
|
246
267
|
}
|
247
268
|
async function getGithubReleaseByTag(config, tag) {
|
@@ -250,7 +271,7 @@ async function getGithubReleaseByTag(config, tag) {
|
|
250
271
|
async function makeGithubRequest(config, url, opts = {}) {
|
251
272
|
return (await axios(url, {
|
252
273
|
...opts,
|
253
|
-
baseURL:
|
274
|
+
baseURL: config.apiBaseUrl,
|
254
275
|
headers: {
|
255
276
|
...opts.headers,
|
256
277
|
Authorization: config.token ? `Bearer ${config.token}` : undefined,
|
@@ -270,27 +291,32 @@ async function updateGithubRelease(config, id, body) {
|
|
270
291
|
});
|
271
292
|
}
|
272
293
|
function githubNewReleaseURL(config, release) {
|
273
|
-
|
294
|
+
// Parameters taken from https://github.com/isaacs/github/issues/1410#issuecomment-442240267
|
295
|
+
let url = `https://${config.hostname}/${config.repo}/releases/new?tag=${release.version}&title=${release.version}&body=${encodeURIComponent(release.body)}&target=${release.commit}`;
|
296
|
+
if (release.prerelease) {
|
297
|
+
url += '&prerelease=true';
|
298
|
+
}
|
299
|
+
return url;
|
274
300
|
}
|
275
301
|
const providerToRefSpec = {
|
276
302
|
github: { 'pull-request': 'pull', hash: 'commit', issue: 'issues' },
|
277
303
|
};
|
278
|
-
function formatReference(ref,
|
304
|
+
function formatReference(ref, repoData) {
|
279
305
|
const refSpec = providerToRefSpec['github'];
|
280
|
-
return `[${ref.value}](https
|
306
|
+
return `[${ref.value}](https://${repoData.hostname}/${repoData.slug}/${refSpec[ref.type]}/${ref.value.replace(/^#/, '')})`;
|
281
307
|
}
|
282
|
-
function formatReferences(references,
|
308
|
+
function formatReferences(references, repoData) {
|
283
309
|
const pr = references.filter((ref) => ref.type === 'pull-request');
|
284
310
|
const issue = references.filter((ref) => ref.type === 'issue');
|
285
311
|
if (pr.length > 0 || issue.length > 0) {
|
286
312
|
return (' (' +
|
287
313
|
[...pr, ...issue]
|
288
|
-
.map((ref) => formatReference(ref,
|
314
|
+
.map((ref) => formatReference(ref, repoData))
|
289
315
|
.join(', ') +
|
290
316
|
')');
|
291
317
|
}
|
292
318
|
if (references.length > 0) {
|
293
|
-
return ' (' + formatReference(references[0],
|
319
|
+
return ' (' + formatReference(references[0], repoData) + ')';
|
294
320
|
}
|
295
321
|
return '';
|
296
322
|
}
|
@@ -13,6 +13,7 @@ async function launchEditor(filePath) {
|
|
13
13
|
return new Promise((resolve, reject) => {
|
14
14
|
const editorProcess = (0, node_child_process_1.spawn)(cmd, [...args, filePath], {
|
15
15
|
stdio: 'inherit', // This will ensure the editor uses the current terminal
|
16
|
+
windowsHide: true,
|
16
17
|
});
|
17
18
|
editorProcess.on('exit', (code) => {
|
18
19
|
if (code === 0) {
|
@@ -26,7 +27,11 @@ async function launchEditor(filePath) {
|
|
26
27
|
}
|
27
28
|
function getGitConfig(key) {
|
28
29
|
try {
|
29
|
-
return (0, node_child_process_1.execSync)(`git config --get ${key}
|
30
|
+
return (0, node_child_process_1.execSync)(`git config --get ${key}`, {
|
31
|
+
windowsHide: true,
|
32
|
+
})
|
33
|
+
.toString()
|
34
|
+
.trim();
|
30
35
|
}
|
31
36
|
catch {
|
32
37
|
return null;
|
@@ -210,7 +210,7 @@ function createAPI(overrideReleaseConfig) {
|
|
210
210
|
runPreVersionCommand(releaseGroup.version.groupPreVersionCommand, {
|
211
211
|
dryRun: args.dryRun,
|
212
212
|
verbose: args.verbose,
|
213
|
-
});
|
213
|
+
}, releaseGroup);
|
214
214
|
const projectBatches = (0, batch_projects_by_generator_config_1.batchProjectsByGeneratorConfig)(projectGraph, releaseGroup,
|
215
215
|
// Batch based on all projects within the release group
|
216
216
|
releaseGroup.projects);
|
@@ -412,11 +412,13 @@ function resolveGeneratorData({ collectionName, generatorName, configGeneratorOp
|
|
412
412
|
throw err;
|
413
413
|
}
|
414
414
|
}
|
415
|
-
function runPreVersionCommand(preVersionCommand, { dryRun, verbose }) {
|
415
|
+
function runPreVersionCommand(preVersionCommand, { dryRun, verbose }, releaseGroup) {
|
416
416
|
if (!preVersionCommand) {
|
417
417
|
return;
|
418
418
|
}
|
419
|
-
output_1.output.logSingleLine(
|
419
|
+
output_1.output.logSingleLine(releaseGroup
|
420
|
+
? `Executing release group pre-version command for "${releaseGroup.name}"`
|
421
|
+
: `Executing pre-version command`);
|
420
422
|
if (verbose) {
|
421
423
|
console.log(`Executing the following pre-version command:`);
|
422
424
|
console.log(preVersionCommand);
|
@@ -434,6 +436,7 @@ function runPreVersionCommand(preVersionCommand, { dryRun, verbose }) {
|
|
434
436
|
maxBuffer: LARGE_BUFFER,
|
435
437
|
stdio,
|
436
438
|
env,
|
439
|
+
windowsHide: true,
|
437
440
|
});
|
438
441
|
}
|
439
442
|
catch (e) {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { PackageManager } from '../../utils/package-manager';
|
2
2
|
import { PackageJson } from '../../utils/package-json';
|
3
3
|
import { NxJsonConfiguration } from '../../config/nx-json';
|
4
|
+
import type { PowerpackLicense } from '@nx/powerpack-license';
|
4
5
|
export declare const packagesWeCareAbout: string[];
|
5
6
|
export declare const patternsWeIgnoreInCommunityReport: Array<string | RegExp>;
|
6
7
|
/**
|
@@ -15,7 +16,8 @@ export declare function reportHandler(): Promise<void>;
|
|
15
16
|
export interface ReportData {
|
16
17
|
pm: PackageManager;
|
17
18
|
pmVersion: string;
|
18
|
-
powerpackLicense:
|
19
|
+
powerpackLicense: PowerpackLicense | null;
|
20
|
+
powerpackError: Error | null;
|
19
21
|
powerpackPlugins: PackageJson[];
|
20
22
|
localPlugins: string[];
|
21
23
|
communityPlugins: PackageJson[];
|