nx 19.8.0-canary.20240920-999abe9 → 19.8.0
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/nx.wasm32-wasi.wasm +0 -0
@@ -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,14 +244,14 @@ 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',
|
@@ -242,6 +259,9 @@ async function resolveGithubToken() {
|
|
242
259
|
}
|
243
260
|
}
|
244
261
|
}
|
262
|
+
if (hostname !== 'github.com') {
|
263
|
+
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.`);
|
264
|
+
}
|
245
265
|
return null;
|
246
266
|
}
|
247
267
|
async function getGithubReleaseByTag(config, tag) {
|
@@ -250,7 +270,7 @@ async function getGithubReleaseByTag(config, tag) {
|
|
250
270
|
async function makeGithubRequest(config, url, opts = {}) {
|
251
271
|
return (await axios(url, {
|
252
272
|
...opts,
|
253
|
-
baseURL:
|
273
|
+
baseURL: config.apiBaseUrl,
|
254
274
|
headers: {
|
255
275
|
...opts.headers,
|
256
276
|
Authorization: config.token ? `Bearer ${config.token}` : undefined,
|
@@ -270,27 +290,32 @@ async function updateGithubRelease(config, id, body) {
|
|
270
290
|
});
|
271
291
|
}
|
272
292
|
function githubNewReleaseURL(config, release) {
|
273
|
-
|
293
|
+
// Parameters taken from https://github.com/isaacs/github/issues/1410#issuecomment-442240267
|
294
|
+
let url = `https://${config.hostname}/${config.repo}/releases/new?tag=${release.version}&title=${release.version}&body=${encodeURIComponent(release.body)}&target=${release.commit}`;
|
295
|
+
if (release.prerelease) {
|
296
|
+
url += '&prerelease=true';
|
297
|
+
}
|
298
|
+
return url;
|
274
299
|
}
|
275
300
|
const providerToRefSpec = {
|
276
301
|
github: { 'pull-request': 'pull', hash: 'commit', issue: 'issues' },
|
277
302
|
};
|
278
|
-
function formatReference(ref,
|
303
|
+
function formatReference(ref, repoData) {
|
279
304
|
const refSpec = providerToRefSpec['github'];
|
280
|
-
return `[${ref.value}](https
|
305
|
+
return `[${ref.value}](https://${repoData.hostname}/${repoData.slug}/${refSpec[ref.type]}/${ref.value.replace(/^#/, '')})`;
|
281
306
|
}
|
282
|
-
function formatReferences(references,
|
307
|
+
function formatReferences(references, repoData) {
|
283
308
|
const pr = references.filter((ref) => ref.type === 'pull-request');
|
284
309
|
const issue = references.filter((ref) => ref.type === 'issue');
|
285
310
|
if (pr.length > 0 || issue.length > 0) {
|
286
311
|
return (' (' +
|
287
312
|
[...pr, ...issue]
|
288
|
-
.map((ref) => formatReference(ref,
|
313
|
+
.map((ref) => formatReference(ref, repoData))
|
289
314
|
.join(', ') +
|
290
315
|
')');
|
291
316
|
}
|
292
317
|
if (references.length > 0) {
|
293
|
-
return ' (' + formatReference(references[0],
|
318
|
+
return ' (' + formatReference(references[0], repoData) + ')';
|
294
319
|
}
|
295
320
|
return '';
|
296
321
|
}
|
package/src/config/nx-json.d.ts
CHANGED
@@ -58,7 +58,14 @@ export interface NxReleaseChangelogConfiguration {
|
|
58
58
|
* NOTE: if createRelease is set on a group of projects, it will cause the default releaseTagPattern of
|
59
59
|
* "{projectName}@{version}" to be used for those projects, even when versioning everything together.
|
60
60
|
*/
|
61
|
-
createRelease?: 'github' |
|
61
|
+
createRelease?: false | 'github' | {
|
62
|
+
provider: 'github-enterprise-server';
|
63
|
+
hostname: string;
|
64
|
+
/**
|
65
|
+
* If not set, this will default to `https://${hostname}/api/v3`
|
66
|
+
*/
|
67
|
+
apiBaseUrl?: string;
|
68
|
+
};
|
62
69
|
/**
|
63
70
|
* This can either be set to a string value that will be written to the changelog file(s)
|
64
71
|
* at the workspace root and/or within project directories, or set to `false` to specify
|