@storm-software/git-tools 2.123.16 → 2.123.18

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.
Files changed (82) hide show
  1. package/README.md +1 -1
  2. package/bin/{chunk-SWXHQXUT.cjs → chunk-AU5PZKTN.cjs} +2 -0
  3. package/bin/chunk-AU5PZKTN.cjs.map +1 -0
  4. package/bin/{chunk-G3JMIIRF.cjs → chunk-EHPPIARR.cjs} +12 -17
  5. package/bin/chunk-EHPPIARR.cjs.map +1 -0
  6. package/bin/{chunk-L64XVBGM.cjs → chunk-FH5OSXAJ.cjs} +2 -0
  7. package/bin/chunk-FH5OSXAJ.cjs.map +1 -0
  8. package/bin/{chunk-S5PS23TL.js → chunk-G3YPGVPS.js} +2 -0
  9. package/bin/chunk-G3YPGVPS.js.map +1 -0
  10. package/bin/{chunk-AMSZ7DVW.js → chunk-Q3DQKTOI.js} +2 -0
  11. package/bin/chunk-Q3DQKTOI.js.map +1 -0
  12. package/bin/{chunk-K3LWFM6S.js → chunk-VBJB46HW.js} +13 -17
  13. package/bin/chunk-VBJB46HW.js.map +1 -0
  14. package/bin/git.cjs +642 -1563
  15. package/bin/git.cjs.map +1 -0
  16. package/bin/git.js +589 -1510
  17. package/bin/git.js.map +1 -0
  18. package/bin/post-checkout.cjs +16 -14
  19. package/bin/post-checkout.cjs.map +1 -0
  20. package/bin/post-checkout.js +5 -3
  21. package/bin/post-checkout.js.map +1 -0
  22. package/bin/post-commit.cjs +16 -14
  23. package/bin/post-commit.cjs.map +1 -0
  24. package/bin/post-commit.js +5 -3
  25. package/bin/post-commit.js.map +1 -0
  26. package/bin/post-merge.cjs +16 -14
  27. package/bin/post-merge.cjs.map +1 -0
  28. package/bin/post-merge.js +5 -3
  29. package/bin/post-merge.js.map +1 -0
  30. package/bin/pre-commit.cjs +14 -12
  31. package/bin/pre-commit.cjs.map +1 -0
  32. package/bin/pre-commit.js +4 -2
  33. package/bin/pre-commit.js.map +1 -0
  34. package/bin/pre-install.cjs +13 -11
  35. package/bin/pre-install.cjs.map +1 -0
  36. package/bin/pre-install.js +4 -2
  37. package/bin/pre-install.js.map +1 -0
  38. package/bin/pre-push.cjs +21 -19
  39. package/bin/pre-push.cjs.map +1 -0
  40. package/bin/pre-push.js +5 -3
  41. package/bin/pre-push.js.map +1 -0
  42. package/bin/prepare.cjs +11 -9
  43. package/bin/prepare.cjs.map +1 -0
  44. package/bin/prepare.js +4 -2
  45. package/bin/prepare.js.map +1 -0
  46. package/bin/version-warning.cjs +9 -7
  47. package/bin/version-warning.cjs.map +1 -0
  48. package/bin/version-warning.js +4 -2
  49. package/bin/version-warning.js.map +1 -0
  50. package/dist/chunk-3GGWHKRP.js +3 -6
  51. package/dist/chunk-4VPJA7YJ.cjs +9 -9
  52. package/dist/chunk-5XU2KBM6.js +1 -3
  53. package/dist/chunk-F7OO6L26.cjs +11 -16
  54. package/dist/chunk-JCEVFJCA.js +4 -14
  55. package/dist/chunk-KZRVQ5RZ.js +3 -11
  56. package/dist/chunk-NY53WLGC.cjs +16 -23
  57. package/dist/chunk-NZHEQPL3.cjs +82 -0
  58. package/dist/chunk-PKEX4GUO.js +75 -0
  59. package/dist/chunk-YBAE6I5L.cjs +3 -3
  60. package/dist/commit/minimal.cjs +11 -3
  61. package/dist/commit/minimal.js +3 -10
  62. package/dist/commit/monorepo.cjs +11 -3
  63. package/dist/commit/monorepo.js +4 -11
  64. package/dist/commitlint/minimal.cjs +4 -5
  65. package/dist/commitlint/minimal.js +3 -6
  66. package/dist/commitlint/monorepo.cjs +4 -5
  67. package/dist/commitlint/monorepo.js +3 -6
  68. package/dist/index.cjs +36 -14
  69. package/dist/index.d.cts +2 -2
  70. package/dist/index.d.ts +2 -2
  71. package/dist/index.js +5 -20
  72. package/dist/release/config.cjs +26 -6
  73. package/dist/release/config.d.cts +21 -242
  74. package/dist/release/config.d.ts +21 -242
  75. package/dist/release/config.js +5 -14
  76. package/dist/types.cjs +7 -3
  77. package/dist/types.d.cts +90 -94
  78. package/dist/types.d.ts +90 -94
  79. package/dist/types.js +1 -6
  80. package/package.json +12 -12
  81. package/dist/chunk-GOKUSEH3.cjs +0 -77
  82. package/dist/chunk-YCEUZFMU.js +0 -77
package/bin/git.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { run } from './chunk-S5PS23TL.js';
3
- import { getConfig, handleProcess, writeSuccess, exitWithSuccess, exitWithError, writeInfo, findWorkspaceRootSafe, writeFatal, getWorkspaceConfig, joinPaths, writeDebug, defu, isVerbose, writeWarning, writeTrace, STORM_DEFAULT_RELEASE_BANNER, __require } from './chunk-K3LWFM6S.js';
2
+ import { run } from './chunk-G3YPGVPS.js';
3
+ import { getConfig, handleProcess, writeSuccess, exitWithSuccess, exitWithError, writeInfo, findWorkspaceRootSafe, writeFatal, getWorkspaceConfig, joinPaths, writeDebug, isVerbose, writeWarning, defu, writeTrace, STORM_DEFAULT_RELEASE_BANNER } from './chunk-VBJB46HW.js';
4
4
  import TOML from '@ltd/j-toml';
5
5
  import { Command } from 'commander';
6
6
  import { select, confirm, input } from '@inquirer/prompts';
@@ -24,39 +24,25 @@ import anchor from 'anchor-markdown-header';
24
24
  import { Parser } from 'htmlparser2';
25
25
  import _ from 'underscore';
26
26
  import updateSection from 'update-section';
27
- import { readCachedProjectGraph as readCachedProjectGraph$1, createProjectGraphAsync as createProjectGraphAsync$2, output as output$1, joinPathFragments } from '@nx/devkit';
28
- import { createAPI as createAPI$2 } from 'nx/src/command-line/release/publish.js';
29
- import { createAPI as createAPI$1 } from 'nx/src/command-line/release/version.js';
30
- import { readNxJson } from 'nx/src/config/nx-json.js';
31
- import { prompt } from 'enquirer';
32
- import { createNxReleaseConfig, handleNxReleaseConfigError } from 'nx/src/command-line/release/config/config';
33
- import { deepMergeJson } from 'nx/src/command-line/release/config/deep-merge-json';
34
- import { filterReleaseGroups } from 'nx/src/command-line/release/config/filter-release-groups';
35
- import { readRawVersionPlans, setResolvedVersionPlansOnGroups } from 'nx/src/command-line/release/config/version-plans';
36
- import { getCommitHash, parseGitCommit, getLatestGitTagForPattern, getFirstGitCommit, getGitDiff, parseCommits, gitAdd, gitPush } from 'nx/src/command-line/release/utils/git';
37
- import { launchEditor } from 'nx/src/command-line/release/utils/launch-editor';
38
- import { printAndFlushChanges, printDiff } from 'nx/src/command-line/release/utils/print-changes';
39
- import { printConfigAndExit } from 'nx/src/command-line/release/utils/print-config';
27
+ import { readCachedProjectGraph as readCachedProjectGraph$1, createProjectGraphAsync as createProjectGraphAsync$2, readProjectsConfigurationFromProjectGraph as readProjectsConfigurationFromProjectGraph$2, output, joinPathFragments } from '@nx/devkit';
28
+ import axios from 'axios';
29
+ import 'enquirer';
30
+ import { homedir } from 'node:os';
31
+ import { printAndFlushChanges } from 'nx/src/command-line/release/utils/print-changes';
40
32
  import { defaultCreateReleaseProvider, GithubRemoteReleaseClient } from 'nx/src/command-line/release/utils/remote-release-clients/github';
41
- import { resolveNxJsonConfigErrorMessage } from 'nx/src/command-line/release/utils/resolve-nx-json-error-message';
42
- import { createCommitMessageValues, handleDuplicateGitTags, ReleaseVersion, noDiffInChangelogMessage } from 'nx/src/command-line/release/utils/shared';
43
- import { readNxJson as readNxJson$1 } from 'nx/src/config/nx-json';
44
- import { FsTree } from 'nx/src/generators/tree';
45
- import { createProjectFileMapUsingProjectGraph, createFileMapUsingProjectGraph } from 'nx/src/project-graph/file-map-utils';
46
- import { interpolate } from 'nx/src/tasks-runner/utils';
47
- import { isCI } from 'nx/src/utils/is-ci';
48
- import { output } from 'nx/src/utils/output';
49
- import { joinPathFragments as joinPathFragments$1 } from 'nx/src/utils/path';
50
- import { workspaceRoot } from 'nx/src/utils/workspace-root';
51
- import { valid, major } from 'semver';
52
- import { dirSync } from 'tmp';
33
+ import { noDiffInChangelogMessage, handleDuplicateGitTags, createCommitMessageValues } from 'nx/src/command-line/release/utils/shared';
34
+ import { parse } from 'yaml';
53
35
  import { resolveConfig, format } from 'prettier';
36
+ import { ReleaseClient } from 'nx/release';
37
+ import { createAPI } from 'nx/src/command-line/release/changelog';
38
+ import { getCommitHash, gitPush, gitAdd } from 'nx/src/command-line/release/utils/git';
39
+ import { readNxJson } from 'nx/src/config/nx-json';
40
+ import { FsTree } from 'nx/src/generators/tree';
54
41
  import { execCommand } from 'nx/src/command-line/release/utils/exec-command.js';
55
- import axios from 'axios';
42
+ import { interpolate } from 'nx/src/tasks-runner/utils';
56
43
  import DefaultChangelogRenderer from 'nx/release/changelog-renderer';
57
44
  import { DEFAULT_CONVENTIONAL_COMMITS_CONFIG } from 'nx/src/command-line/release/config/conventional-commits';
58
- import { homedir } from 'node:os';
59
- import { parse } from 'yaml';
45
+ import { major } from 'semver';
60
46
 
61
47
  function parseCargoToml(cargoString) {
62
48
  if (!cargoString) {
@@ -923,10 +909,10 @@ async function lint(message, config5) {
923
909
  throw new Error(`Could not find rule implementation for ${name}`);
924
910
  }
925
911
  const executableRule = rule;
926
- const [valid3, message2] = await executableRule(parsed, when, value);
912
+ const [valid2, message2] = await executableRule(parsed, when, value);
927
913
  return {
928
914
  level,
929
- valid: valid3,
915
+ valid: valid2,
930
916
  name,
931
917
  message: message2
932
918
  };
@@ -940,9 +926,9 @@ async function lint(message, config5) {
940
926
  const warnings = results.filter(
941
927
  (result) => result.level === 1 /* Warning */ && !result.valid
942
928
  );
943
- const valid2 = errors.length === 0;
929
+ const valid = errors.length === 0;
944
930
  return {
945
- valid: valid2,
931
+ valid,
946
932
  errors,
947
933
  warnings,
948
934
  input: buildCommitMessage(parsed)
@@ -2395,7 +2381,7 @@ function generateChangelogTitle(version, project, workspaceConfig) {
2395
2381
  if (!workspaceConfig?.name || !project) {
2396
2382
  return version;
2397
2383
  }
2398
- return `[${version}](https://github.com/${typeof workspaceConfig.organization === "string" ? workspaceConfig.organization : workspaceConfig.organization?.name}/${workspaceConfig.name}/releases/tag/${project}%40${version}) (${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)})`;
2384
+ return `[${version}](https://github.com/${typeof workspaceConfig.organization === "string" ? workspaceConfig.organization : workspaceConfig.organization?.name}/${workspaceConfig.name}/releases/tag/${project}%40${version}) (${(/* @__PURE__ */ new Date()).getMonth() + 1}/${(/* @__PURE__ */ new Date()).getDate()}/${(/* @__PURE__ */ new Date()).getFullYear()})`;
2399
2385
  }
2400
2386
  function parseChangelogMarkdown(contents) {
2401
2387
  const CHANGELOG_RELEASE_HEAD_RE = new RegExp(
@@ -2424,6 +2410,226 @@ function parseChangelogMarkdown(contents) {
2424
2410
  releases
2425
2411
  };
2426
2412
  }
2413
+
2414
+ // src/release/github.ts
2415
+ var StormGithubRemoteReleaseClient = class extends GithubRemoteReleaseClient {
2416
+ #remoteRepoData;
2417
+ #workspaceConfig;
2418
+ /**
2419
+ * Creates an instance of {@link StormGithubRemoteReleaseClient}.
2420
+ *
2421
+ * @param remoteRepoData - Data about the remote repository
2422
+ * @param createReleaseConfig - Configuration for creating releases
2423
+ * @param tokenData - Token data for authentication
2424
+ * @param workspaceConfig - The Storm workspace configuration object, which is loaded from the storm-workspace.json file.
2425
+ */
2426
+ constructor(remoteRepoData, createReleaseConfig, tokenData, workspaceConfig) {
2427
+ super(remoteRepoData, createReleaseConfig, tokenData);
2428
+ this.#remoteRepoData = remoteRepoData;
2429
+ this.#workspaceConfig = workspaceConfig;
2430
+ }
2431
+ createPostGitTask(releaseVersion, changelogContents, dryRun) {
2432
+ return async (latestCommit) => {
2433
+ if (!this.#workspaceConfig) {
2434
+ this.#workspaceConfig = await getWorkspaceConfig();
2435
+ }
2436
+ output.logSingleLine(`Creating GitHub Release`);
2437
+ const name = releaseVersion.gitTag.includes("@") ? releaseVersion.gitTag.replace(new RegExp(`^@${this.#workspaceConfig.name}/`), "").replace(/@.*$/, "") : releaseVersion.gitTag;
2438
+ await this.createOrUpdateRelease(
2439
+ releaseVersion,
2440
+ `![${(typeof this.#workspaceConfig.release.banner === "string" ? this.#workspaceConfig.organization ? titleCase(
2441
+ typeof this.#workspaceConfig.organization === "string" ? this.#workspaceConfig.organization : this.#workspaceConfig.organization.name
2442
+ ) : void 0 : this.#workspaceConfig.release.banner.alt) || "Release banner header"}](${typeof this.#workspaceConfig.release.banner === "string" ? this.#workspaceConfig.release.banner : this.#workspaceConfig.release.banner?.url})
2443
+ ${this.#workspaceConfig.release.header || ""}
2444
+
2445
+ # ${name ? `${titleCase(name)} ` : ""}v${releaseVersion.rawVersion}
2446
+
2447
+ We at [${this.#workspaceConfig.organization ? titleCase(
2448
+ typeof this.#workspaceConfig.organization === "string" ? this.#workspaceConfig.organization : this.#workspaceConfig.organization.name
2449
+ ) : ""}](${this.#workspaceConfig.homepage}) are very excited to announce the v${releaseVersion.rawVersion} release of the ${name ? this.#workspaceConfig.name ? `${titleCase(this.#workspaceConfig.name)} - ${titleCase(name)}` : titleCase(name) : this.#workspaceConfig.name ? titleCase(this.#workspaceConfig.name) : "Storm Software"} project! \u{1F680}
2450
+
2451
+ These changes are released under the ${this.#workspaceConfig.license.includes("license") ? this.#workspaceConfig.license : `${this.#workspaceConfig.license} license`}. You can find more details on [our licensing page](${this.#workspaceConfig.licensing}). You can find guides, API references, and other documentation around this release (and much more) on [our documentation site](${this.#workspaceConfig.docs}).
2452
+
2453
+ If you have any questions or comments, feel free to reach out to the team on [Discord](${this.#workspaceConfig.socials.discord}) or [our contact page](${this.#workspaceConfig.contact}). Please help us spread the word by giving [this repository](https://github.com/${typeof this.#workspaceConfig.organization === "string" ? this.#workspaceConfig.organization : this.#workspaceConfig.organization?.name}/${this.#workspaceConfig.name}) a star \u2B50 on GitHub or [posting on X (Twitter)](https://x.com/intent/tweet?text=Check%20out%20the%20latest%20@${this.#workspaceConfig.socials.twitter}%20release%20${name ? `${titleCase(name)?.replaceAll(" ", "%20")}%20` : ""}v${releaseVersion.rawVersion}%20%F0%9F%9A%80%0D%0A%0D%0Ahttps://github.com/${typeof this.#workspaceConfig.organization === "string" ? this.#workspaceConfig.organization : this.#workspaceConfig.organization?.name}/${this.#workspaceConfig.name}/releases/tag/${releaseVersion.gitTag}) about this release!
2454
+
2455
+ ## Release Notes
2456
+
2457
+ ${changelogContents.replaceAll(
2458
+ `## ${generateChangelogTitle(
2459
+ releaseVersion.rawVersion,
2460
+ name,
2461
+ this.#workspaceConfig
2462
+ )}`,
2463
+ ""
2464
+ ).replaceAll(
2465
+ `# ${generateChangelogTitle(releaseVersion.rawVersion, name, this.#workspaceConfig)}`,
2466
+ ""
2467
+ )}
2468
+
2469
+ ---
2470
+
2471
+ ${this.#workspaceConfig.release.footer}
2472
+ `,
2473
+ latestCommit,
2474
+ { dryRun }
2475
+ );
2476
+ };
2477
+ }
2478
+ /**
2479
+ * Get remote repository data, attempting to resolve it if not already set.
2480
+ */
2481
+ getRemoteRepoData() {
2482
+ if (!this.#remoteRepoData) {
2483
+ let githubRepoData = super.getRemoteRepoData();
2484
+ if (!githubRepoData) {
2485
+ githubRepoData = getGitHubRepoData();
2486
+ if (!githubRepoData) {
2487
+ output.error({
2488
+ title: `Unable to create a GitHub release because the GitHub repo slug could not be determined.`,
2489
+ bodyLines: [
2490
+ `Please ensure you have a valid GitHub remote configured. You can run \`git remote -v\` to list your current remotes.`
2491
+ ]
2492
+ });
2493
+ process.exit(1);
2494
+ }
2495
+ }
2496
+ this.#remoteRepoData = githubRepoData;
2497
+ }
2498
+ return this.#remoteRepoData;
2499
+ }
2500
+ };
2501
+ function getGitHubRepoData(remoteName = "origin", createReleaseConfig = "github") {
2502
+ try {
2503
+ const remoteUrl = execSync(`git remote get-url ${remoteName}`, {
2504
+ encoding: "utf8",
2505
+ stdio: "pipe"
2506
+ }).trim();
2507
+ let hostname = defaultCreateReleaseProvider.hostname;
2508
+ let apiBaseUrl = defaultCreateReleaseProvider.apiBaseUrl;
2509
+ if (createReleaseConfig && typeof createReleaseConfig !== "string") {
2510
+ hostname = createReleaseConfig.hostname;
2511
+ apiBaseUrl = createReleaseConfig.apiBaseUrl;
2512
+ }
2513
+ const escapedHostname = hostname.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2514
+ const regexString = `${escapedHostname}[/:]([\\w.-]+/[\\w.-]+)(\\.git)?`;
2515
+ const regex = new RegExp(regexString);
2516
+ const match = remoteUrl?.match(regex);
2517
+ if (match && match[1]) {
2518
+ return {
2519
+ hostname,
2520
+ apiBaseUrl,
2521
+ // Ensure any trailing .git is stripped
2522
+ slug: match[1].replace(/\.git$/, "")
2523
+ };
2524
+ } else {
2525
+ throw new Error(
2526
+ `Could not extract "user/repo" data from the resolved remote URL: ${remoteUrl}`
2527
+ );
2528
+ }
2529
+ } catch (error) {
2530
+ output.error({
2531
+ title: `Failed to get GitHub repo data`,
2532
+ bodyLines: [error.message]
2533
+ });
2534
+ return void 0;
2535
+ }
2536
+ }
2537
+ async function resolveTokenData(hostname) {
2538
+ const tokenFromEnv = process.env.STORM_BOT_GITHUB_TOKEN || process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
2539
+ if (tokenFromEnv) {
2540
+ return { token: tokenFromEnv, headerName: "Authorization" };
2541
+ }
2542
+ const ghCLIPath = joinPathFragments(
2543
+ process.env.XDG_CONFIG_HOME || joinPathFragments(homedir(), ".config"),
2544
+ "gh",
2545
+ "hosts.yml"
2546
+ );
2547
+ if (existsSync$1(ghCLIPath)) {
2548
+ const yamlContents = await promises.readFile(ghCLIPath, "utf8");
2549
+ const ghCLIConfig = parse(yamlContents);
2550
+ if (ghCLIConfig[hostname]) {
2551
+ if (ghCLIConfig[hostname].oauth_token) {
2552
+ return ghCLIConfig[hostname].oauth_token;
2553
+ }
2554
+ if (ghCLIConfig[hostname].user && ghCLIConfig[hostname].git_protocol === "ssh") {
2555
+ const token = execSync(`gh auth token`, {
2556
+ encoding: "utf8",
2557
+ stdio: "pipe",
2558
+ windowsHide: false
2559
+ }).trim();
2560
+ return { token, headerName: "Authorization" };
2561
+ }
2562
+ }
2563
+ }
2564
+ if (hostname !== "github.com") {
2565
+ console.log(
2566
+ `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.`
2567
+ );
2568
+ }
2569
+ throw new Error(
2570
+ `Unable to resolve a GitHub token for hostname ${hostname}. Please set the GITHUB_TOKEN or GH_TOKEN environment variable, or ensure you have an active session via the official gh CLI tool (https://cli.github.com).`
2571
+ );
2572
+ }
2573
+ async function makeGithubRequest(config5, url, opts = {}) {
2574
+ return await axios(url, {
2575
+ ...opts,
2576
+ baseURL: config5.apiBaseUrl,
2577
+ headers: {
2578
+ ...opts.headers,
2579
+ Authorization: config5.token ? `Bearer ${config5.token}` : void 0
2580
+ }
2581
+ });
2582
+ }
2583
+ async function createGithubRemoteReleaseClient(workspaceConfig, remoteName = "origin") {
2584
+ const repoData = getGitHubRepoData(remoteName, "github");
2585
+ if (!repoData) {
2586
+ throw new Error(
2587
+ `Unable to create a remote release client because the GitHub repo slug could not be determined. Please ensure you have a valid GitHub remote configured.`
2588
+ );
2589
+ }
2590
+ return new StormGithubRemoteReleaseClient(
2591
+ repoData,
2592
+ {
2593
+ provider: "github",
2594
+ hostname: repoData.hostname,
2595
+ apiBaseUrl: repoData.apiBaseUrl
2596
+ },
2597
+ await resolveTokenData(repoData.hostname),
2598
+ workspaceConfig
2599
+ );
2600
+ }
2601
+ async function isUserAnOrganizationMember(userId, config5, remoteName = "origin") {
2602
+ try {
2603
+ const repoData = getGitHubRepoData(remoteName, "github");
2604
+ if (!repoData) {
2605
+ throw new Error(
2606
+ `Unable to validate GitHub actor because the GitHub repo slug could not be determined. Please ensure you have a valid GitHub remote configured.`
2607
+ );
2608
+ }
2609
+ const tokenData = await resolveTokenData(repoData.hostname);
2610
+ if (!tokenData.token) {
2611
+ throw new Error(
2612
+ `Unable to validate GitHub actor because no token was provided. Please set the GITHUB_TOKEN or GH_TOKEN environment variable, or ensure you have an active session via the official gh CLI tool (https://cli.github.com).`
2613
+ );
2614
+ }
2615
+ const result = await makeGithubRequest(
2616
+ {
2617
+ repo: repoData.slug,
2618
+ hostname: repoData.hostname,
2619
+ apiBaseUrl: repoData.apiBaseUrl,
2620
+ token: tokenData?.token || null
2621
+ },
2622
+ `/orgs/${typeof config5.organization === "string" ? config5.organization : config5.organization?.name}/members/${userId}`,
2623
+ {}
2624
+ );
2625
+ if (result.status !== 204) {
2626
+ return false;
2627
+ }
2628
+ return true;
2629
+ } catch {
2630
+ return false;
2631
+ }
2632
+ }
2427
2633
  function createGitTagValues(releaseGroups, releaseGroupToFilteredProjects, versionData) {
2428
2634
  const tags = [];
2429
2635
  for (const releaseGroup of releaseGroups) {
@@ -2570,30 +2776,45 @@ async function commitChanges({
2570
2776
  verbose: isVerbose2
2571
2777
  });
2572
2778
  }
2779
+
2780
+ // src/utilities/omit.ts
2781
+ function omit(obj, keys) {
2782
+ const result = { ...obj };
2783
+ for (let i = 0; i < keys.length; i++) {
2784
+ const key = keys[i];
2785
+ if (key && key in result) {
2786
+ delete result[key];
2787
+ }
2788
+ }
2789
+ return result;
2790
+ }
2573
2791
  var StormChangelogRenderer = class extends DefaultChangelogRenderer {
2574
2792
  /**
2575
2793
  * The Storm workspace configuration object, which is loaded from the storm-workspace.json file.
2576
2794
  */
2577
- workspaceConfig = null;
2578
- /**
2579
- * The configuration object for the ChangelogRenderer, which includes the changes, version, project, and other options.
2580
- */
2581
- config;
2795
+ workspaceConfig;
2582
2796
  /**
2583
2797
  * A ChangelogRenderer class takes in the determined changes and other relevant metadata and returns a string, or a Promise of a string of changelog contents (usually markdown).
2584
2798
  *
2585
2799
  * @param config - The configuration object for the ChangelogRenderer
2586
2800
  */
2587
2801
  constructor(config5) {
2588
- super(config5);
2589
- this.config = {
2590
- ...config5,
2591
- repoData: config5.remoteReleaseClient.getRemoteRepoData()
2802
+ const resolvedConfig = {
2803
+ entryWhenNoChanges: false,
2804
+ conventionalCommitsConfig: DEFAULT_CONVENTIONAL_COMMITS_CONFIG,
2805
+ ...config5
2592
2806
  };
2807
+ super(resolvedConfig);
2808
+ this.workspaceConfig = config5.changelogRenderOptions.workspaceConfig;
2593
2809
  }
2594
2810
  async render() {
2595
- this.workspaceConfig = await getWorkspaceConfig();
2596
- return await super.render();
2811
+ if (!this.workspaceConfig) {
2812
+ this.workspaceConfig = await getWorkspaceConfig();
2813
+ }
2814
+ this.remoteReleaseClient = await createGithubRemoteReleaseClient(
2815
+ this.workspaceConfig
2816
+ );
2817
+ return super.render();
2597
2818
  }
2598
2819
  preprocessChanges() {
2599
2820
  this.relevantChanges = [...this.changes];
@@ -2672,7 +2893,7 @@ var StormChangelogRenderer = class extends DefaultChangelogRenderer {
2672
2893
  renderDependencyBumps() {
2673
2894
  const markdownLines = ["", "### Updated Dependencies", ""];
2674
2895
  this.dependencyBumps?.forEach(({ dependencyName, newVersion }) => {
2675
- const markdownLine = `- Updated ${dependencyName} to ${newVersion}`;
2896
+ const markdownLine = `- Updated **${dependencyName}** to **v${newVersion}**`;
2676
2897
  if (!markdownLines.includes(markdownLine)) {
2677
2898
  markdownLines.push(markdownLine);
2678
2899
  }
@@ -2702,7 +2923,7 @@ var StormChangelogRenderer = class extends DefaultChangelogRenderer {
2702
2923
  }
2703
2924
  }
2704
2925
  }
2705
- if (this.config.repoData && this.changelogRenderOptions.mapAuthorsToGitHubUsernames) {
2926
+ if (this.changelogRenderOptions.mapAuthorsToGitHubUsernames) {
2706
2927
  await Promise.all(
2707
2928
  [..._authors.keys()].map(async (authorName) => {
2708
2929
  const meta = _authors.get(authorName);
@@ -2759,7 +2980,7 @@ var StormChangelogRenderer = class extends DefaultChangelogRenderer {
2759
2980
  extraLinesStr = extraLines.filter((l) => l.trim().length > 0).map((l) => `${indentation}${l}`).join("\n");
2760
2981
  }
2761
2982
  let changeLine = "- " + (!this.isVersionPlans && change.scope ? `**${change.scope.trim()}:** ` : "") + description;
2762
- if (this.config.repoData && change.githubReferences) {
2983
+ if (change.githubReferences) {
2763
2984
  changeLine += this.remoteReleaseClient.formatReferences(
2764
2985
  change.githubReferences
2765
2986
  );
@@ -2770,1481 +2991,359 @@ var StormChangelogRenderer = class extends DefaultChangelogRenderer {
2770
2991
  return changeLine;
2771
2992
  }
2772
2993
  };
2773
- function getGitHubRepoData(remoteName = "origin", createReleaseConfig) {
2774
- try {
2775
- const remoteUrl = execSync(`git remote get-url ${remoteName}`, {
2776
- encoding: "utf8",
2777
- stdio: "pipe"
2778
- }).trim();
2779
- let hostname = defaultCreateReleaseProvider.hostname;
2780
- let apiBaseUrl = defaultCreateReleaseProvider.apiBaseUrl;
2781
- if (createReleaseConfig && typeof createReleaseConfig !== "string") {
2782
- hostname = createReleaseConfig.hostname;
2783
- apiBaseUrl = createReleaseConfig.apiBaseUrl;
2784
- }
2785
- const escapedHostname = hostname.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2786
- const regexString = `${escapedHostname}[/:]([\\w.-]+/[\\w.-]+)(\\.git)?`;
2787
- const regex = new RegExp(regexString);
2788
- const match = remoteUrl?.match(regex);
2789
- if (match && match[1]) {
2790
- return {
2791
- hostname,
2792
- apiBaseUrl,
2793
- // Ensure any trailing .git is stripped
2794
- slug: match[1].replace(/\.git$/, "")
2795
- };
2796
- } else {
2797
- throw new Error(
2798
- `Could not extract "user/repo" data from the resolved remote URL: ${remoteUrl}`
2799
- );
2800
- }
2801
- } catch (error) {
2802
- output$1.error({
2803
- title: `Failed to get GitHub repo data`,
2804
- bodyLines: [error.message]
2805
- });
2806
- return void 0;
2807
- }
2808
- }
2809
- async function createOrUpdateGithubRelease(createReleaseConfig, releaseVersion, changelogContents, latestCommit, { dryRun }) {
2810
- const githubRepoData = getGitHubRepoData(void 0, createReleaseConfig);
2811
- if (!githubRepoData) {
2812
- output$1.error({
2813
- title: `Unable to create a GitHub release because the GitHub repo slug could not be determined.`,
2814
- bodyLines: [
2815
- `Please ensure you have a valid GitHub remote configured. You can run \`git remote -v\` to list your current remotes.`
2816
- ]
2817
- });
2818
- process.exit(1);
2819
- }
2820
- const tokenData = await resolveTokenData(githubRepoData.hostname);
2821
- const githubRequestConfig = {
2822
- repo: githubRepoData.slug,
2823
- hostname: githubRepoData.hostname,
2824
- apiBaseUrl: githubRepoData.apiBaseUrl,
2825
- token: tokenData?.token || null
2826
- };
2827
- let existingGithubReleaseForVersion;
2828
- try {
2829
- existingGithubReleaseForVersion = await getGithubReleaseByTag(
2830
- githubRequestConfig,
2831
- releaseVersion.gitTag
2832
- );
2833
- } catch (err) {
2834
- if (err.response?.status === 401) {
2835
- output$1.error({
2836
- title: `Unable to resolve data via the GitHub API. You can use any of the following options to resolve this:`,
2837
- bodyLines: [
2838
- "- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid GitHub token with `repo` scope",
2839
- "- Have an active session via the official gh CLI tool (https://cli.github.com) in your current terminal"
2840
- ]
2841
- });
2842
- process.exit(1);
2843
- }
2844
- if (err.response?.status === 404) ; else {
2845
- throw err;
2994
+
2995
+ // src/release/config.ts
2996
+ var DEFAULT_CONVENTIONAL_COMMITS_CONFIG2 = {
2997
+ questions: DEFAULT_MONOREPO_COMMIT_QUESTIONS,
2998
+ types: DEFAULT_COMMIT_TYPES
2999
+ };
3000
+ var DEFAULT_RELEASE_TAG_PATTERN = "{projectName}@{version}";
3001
+ var DEFAULT_RELEASE_GROUP_CONFIG = {
3002
+ projectsRelationship: "independent",
3003
+ changelog: {
3004
+ createRelease: "github",
3005
+ entryWhenNoChanges: false,
3006
+ file: false,
3007
+ renderOptions: {
3008
+ authors: false,
3009
+ commitReferences: true,
3010
+ versionTitleDate: true
2846
3011
  }
2847
- }
2848
- const logTitle = `https://${githubRepoData.hostname}/${githubRepoData.slug}/releases/tag/${releaseVersion.gitTag}`;
2849
- if (existingGithubReleaseForVersion) {
2850
- console.error(`UPDATE ${logTitle}${dryRun ? " [dry-run]" : ""}`);
2851
- } else {
2852
- console.error(`CREATE ${logTitle}${dryRun ? " [dry-run]" : ""}`);
2853
- }
2854
- console.log("");
2855
- printDiff(
2856
- existingGithubReleaseForVersion?.body ? existingGithubReleaseForVersion.body : "",
2857
- changelogContents,
2858
- 3,
2859
- noDiffInChangelogMessage
2860
- );
2861
- if (!dryRun) {
2862
- await createOrUpdateGithubReleaseInternal(
2863
- githubRequestConfig,
3012
+ },
3013
+ version: {
3014
+ currentVersionResolver: "git-tag",
3015
+ specifierSource: "conventional-commits",
3016
+ groupPreVersionCommand: "pnpm build"
3017
+ },
3018
+ releaseTag: { pattern: DEFAULT_RELEASE_TAG_PATTERN }
3019
+ };
3020
+ var DEFAULT_JS_RELEASE_GROUP_CONFIG = {
3021
+ ...DEFAULT_RELEASE_GROUP_CONFIG,
3022
+ projects: ["packages/*"],
3023
+ version: {
3024
+ ...DEFAULT_RELEASE_GROUP_CONFIG.version,
3025
+ versionActions: "@storm-software/workspace-tools/release/js-version-actions",
3026
+ versionActionsOptions: {
3027
+ currentVersionResolver: "git-tag",
3028
+ specifierSource: "conventional-commits"
3029
+ },
3030
+ manifestRootsToUpdate: [
3031
+ "{projectRoot}",
2864
3032
  {
2865
- version: releaseVersion.gitTag,
2866
- prerelease: releaseVersion.isPrerelease,
2867
- body: changelogContents,
2868
- commit: latestCommit
2869
- },
2870
- existingGithubReleaseForVersion
2871
- );
3033
+ path: "dist/{projectRoot}",
3034
+ preserveLocalDependencyProtocols: false
3035
+ }
3036
+ ]
2872
3037
  }
2873
- }
2874
- async function createOrUpdateGithubReleaseInternal(githubRequestConfig, release, existingGithubReleaseForVersion) {
2875
- const result = await syncGithubRelease(
2876
- githubRequestConfig,
2877
- release,
2878
- existingGithubReleaseForVersion
2879
- );
2880
- if (result.status === "manual") {
2881
- if (result.error) {
2882
- process.exitCode = 1;
2883
- if (result.error.response?.data) {
2884
- output$1.error({
2885
- title: `A GitHub API Error occurred when creating/updating the release`,
2886
- bodyLines: [
2887
- `GitHub Error: ${JSON.stringify(result.error.response.data)}`,
2888
- `---`,
2889
- `Request Data:`,
2890
- `Repo: ${githubRequestConfig.repo}`,
2891
- `Token: ${githubRequestConfig.token}`,
2892
- `Body: ${JSON.stringify(result.requestData)}`
2893
- ]
2894
- });
2895
- } else {
2896
- console.log(result.error);
2897
- console.error(
2898
- `An unknown error occurred while trying to create a release on GitHub, please report this on https://github.com/nrwl/nx (NOTE: make sure to redact your GitHub token from the error message!)`
2899
- );
2900
- }
2901
- }
2902
- const shouldContinueInGitHub = await promptForContinueInGitHub();
2903
- if (!shouldContinueInGitHub) {
2904
- return;
2905
- }
2906
- const open = __require("open");
2907
- await open(result.url).then(() => {
2908
- console.info(
2909
- `
2910
- Follow up in the browser to manually create the release:
2911
-
2912
- ` + result.url + `
2913
- `
2914
- );
2915
- }).catch(() => {
2916
- console.info(
2917
- `Open this link to manually create a release:
2918
- ` + result.url + "\n"
2919
- );
2920
- });
2921
- if (result.error) {
2922
- console.error(result.error);
2923
- process.exitCode = 1;
2924
- }
2925
- await open(result.url).then(() => {
2926
- console.info(
2927
- `Follow up in the browser to manually create the release.`
2928
- );
2929
- }).catch(() => {
2930
- console.info(
2931
- `Open this link to manually create a release:
2932
- ` + result.url + "\n"
2933
- );
2934
- });
2935
- }
2936
- }
2937
- async function promptForContinueInGitHub() {
2938
- try {
2939
- const reply = await prompt([
2940
- {
2941
- name: "open",
2942
- message: "Do you want to finish creating the release manually in your browser?",
2943
- type: "autocomplete",
2944
- choices: [
2945
- {
2946
- name: "Yes",
2947
- hint: "It will pre-populate the form for you"
2948
- },
2949
- {
2950
- name: "No"
2951
- }
2952
- ],
2953
- initial: 0
2954
- }
2955
- ]);
2956
- return reply.open === "Yes";
2957
- } catch {
2958
- process.stdout.write("\x1B[?25h");
2959
- process.exit(1);
3038
+ };
3039
+ var DEFAULT_RUST_RELEASE_GROUP_CONFIG = {
3040
+ ...DEFAULT_RELEASE_GROUP_CONFIG,
3041
+ projects: ["crates/*"],
3042
+ version: {
3043
+ ...DEFAULT_RELEASE_GROUP_CONFIG.version,
3044
+ versionActions: "@storm-software/workspace-tools/release/rust-version-actions",
3045
+ versionActionsOptions: {
3046
+ currentVersionResolver: "git-tag",
3047
+ specifierSource: "conventional-commits"
3048
+ },
3049
+ manifestRootsToUpdate: ["{projectRoot}"]
2960
3050
  }
2961
- }
2962
- async function syncGithubRelease(githubRequestConfig, release, existingGithubReleaseForVersion) {
2963
- const ghRelease = {
2964
- tag_name: release.version,
2965
- name: release.version,
2966
- body: release.body,
2967
- prerelease: release.prerelease,
2968
- // legacy specifies that the latest release should be determined based on the release creation date and higher semantic version.
2969
- make_latest: "legacy"
2970
- };
2971
- try {
2972
- const newGhRelease = await (existingGithubReleaseForVersion ? updateGithubRelease(
2973
- githubRequestConfig,
2974
- existingGithubReleaseForVersion.id,
2975
- ghRelease
2976
- ) : createGithubRelease(githubRequestConfig, {
2977
- ...ghRelease,
2978
- target_commitish: release.commit
2979
- }));
2980
- return {
2981
- status: existingGithubReleaseForVersion ? "updated" : "created",
2982
- id: newGhRelease.id,
2983
- url: newGhRelease.html_url
2984
- };
2985
- } catch (error) {
2986
- if (process.env.CI) {
2987
- console.error(
2988
- `An error occurred while trying to create a release on GitHub, please report this on https://github.com/storm-software/storm-ops (NOTE: make sure to redact your GitHub token from the error message!): ${typeof error?.message === "string" ? error?.message : `
3051
+ };
3052
+ var DEFAULT_RELEASE_CONFIG = {
3053
+ conventionalCommits: DEFAULT_CONVENTIONAL_COMMITS_CONFIG2,
3054
+ groups: {
3055
+ packages: DEFAULT_JS_RELEASE_GROUP_CONFIG,
3056
+ crates: DEFAULT_RUST_RELEASE_GROUP_CONFIG
3057
+ },
3058
+ changelog: {
3059
+ automaticFromRef: true,
3060
+ workspaceChangelog: false,
3061
+ projectChangelogs: true
3062
+ },
3063
+ releaseTag: { pattern: DEFAULT_RELEASE_TAG_PATTERN }
3064
+ };
2989
3065
 
2990
- ${error}`}`
2991
- );
2992
- throw new Error(
2993
- "`An error occurred while trying to create a release on GitHub in a CI environment",
3066
+ // src/release/release-client.ts
3067
+ function getReleaseGroupConfig(releaseConfig, workspaceConfig) {
3068
+ return !releaseConfig?.groups || Object.keys(releaseConfig.groups).length === 0 ? {} : Object.fromEntries(
3069
+ Object.entries(releaseConfig.groups).map(([name, group]) => {
3070
+ const config5 = defu(
3071
+ {
3072
+ ...omit(DEFAULT_RELEASE_GROUP_CONFIG, ["changelog"]),
3073
+ ...group
3074
+ },
2994
3075
  {
2995
- cause: error
3076
+ changelog: {
3077
+ ...DEFAULT_RELEASE_GROUP_CONFIG.changelog,
3078
+ renderer: StormChangelogRenderer,
3079
+ renderOptions: {
3080
+ ...DEFAULT_RELEASE_GROUP_CONFIG.changelog.renderOptions,
3081
+ workspaceConfig
3082
+ }
3083
+ }
2996
3084
  }
2997
3085
  );
2998
- }
2999
- return {
3000
- status: "manual",
3001
- error,
3002
- url: githubNewReleaseURL(githubRequestConfig, release),
3003
- requestData: ghRelease
3004
- };
3005
- }
3006
- }
3007
- async function resolveTokenData(hostname) {
3008
- const tokenFromEnv = process.env.STORM_BOT_GITHUB_TOKEN || process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
3009
- if (tokenFromEnv) {
3010
- return { token: tokenFromEnv, headerName: "Authorization" };
3011
- }
3012
- const ghCLIPath = joinPathFragments(
3013
- process.env.XDG_CONFIG_HOME || joinPathFragments(homedir(), ".config"),
3014
- "gh",
3015
- "hosts.yml"
3016
- );
3017
- if (existsSync$1(ghCLIPath)) {
3018
- const yamlContents = await promises.readFile(ghCLIPath, "utf8");
3019
- const ghCLIConfig = parse(yamlContents);
3020
- if (ghCLIConfig[hostname]) {
3021
- if (ghCLIConfig[hostname].oauth_token) {
3022
- return ghCLIConfig[hostname].oauth_token;
3023
- }
3024
- if (ghCLIConfig[hostname].user && ghCLIConfig[hostname].git_protocol === "ssh") {
3025
- const token = execSync(`gh auth token`, {
3026
- encoding: "utf8",
3027
- stdio: "pipe",
3028
- windowsHide: false
3029
- }).trim();
3030
- return { token, headerName: "Authorization" };
3086
+ if (workspaceConfig?.workspaceRoot) {
3087
+ if (config5.changelog?.renderer && typeof config5.changelog?.renderer === "string" && config5.changelog?.renderer?.toString().startsWith("./")) {
3088
+ config5.changelog.renderer = joinPaths(
3089
+ workspaceConfig.workspaceRoot,
3090
+ config5.changelog.renderer
3091
+ );
3092
+ }
3093
+ if (config5.version?.versionActions && config5.version.versionActions.startsWith("./")) {
3094
+ config5.version.versionActions = joinPaths(
3095
+ workspaceConfig.workspaceRoot,
3096
+ config5.version?.versionActions
3097
+ );
3098
+ }
3031
3099
  }
3032
- }
3033
- }
3034
- if (hostname !== "github.com") {
3035
- console.log(
3036
- `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.`
3037
- );
3038
- }
3039
- throw new Error(
3040
- `Unable to resolve a GitHub token for hostname ${hostname}. Please set the GITHUB_TOKEN or GH_TOKEN environment variable, or ensure you have an active session via the official gh CLI tool (https://cli.github.com).`
3100
+ return [name, config5];
3101
+ })
3041
3102
  );
3042
3103
  }
3043
- async function getGithubReleaseByTag(config5, tag) {
3044
- return (await makeGithubRequest(
3045
- config5,
3046
- `/repos/${config5.repo}/releases/tags/${tag}`,
3047
- {}
3048
- )).data;
3049
- }
3050
- async function makeGithubRequest(config5, url, opts = {}) {
3051
- return await axios(url, {
3052
- ...opts,
3053
- baseURL: config5.apiBaseUrl,
3054
- headers: {
3055
- ...opts.headers,
3056
- Authorization: config5.token ? `Bearer ${config5.token}` : void 0
3104
+ var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3105
+ static async create(releaseConfig = {}, ignoreNxJsonConfig = false, workspaceConfig) {
3106
+ if (!workspaceConfig) {
3107
+ workspaceConfig = await getWorkspaceConfig();
3057
3108
  }
3058
- });
3059
- }
3060
- async function createGithubRelease(config5, body) {
3061
- return (await makeGithubRequest(config5, `/repos/${config5.repo}/releases`, {
3062
- method: "POST",
3063
- data: body
3064
- })).data;
3065
- }
3066
- async function updateGithubRelease(config5, id, body) {
3067
- return (await makeGithubRequest(config5, `/repos/${config5.repo}/releases/${id}`, {
3068
- method: "PATCH",
3069
- data: body
3070
- })).data;
3071
- }
3072
- function githubNewReleaseURL(config5, release) {
3073
- let url = `https://${config5.hostname}/${config5.repo}/releases/new?tag=${release.version}&title=${release.version}&body=${encodeURIComponent(release.body)}&target=${release.commit}`;
3074
- if (release.prerelease) {
3075
- url += "&prerelease=true";
3076
- }
3077
- return url;
3078
- }
3079
- async function createGithubRemoteReleaseClient(remoteName = "origin") {
3080
- const repoData = getGitHubRepoData(remoteName, "github");
3081
- if (!repoData) {
3082
- throw new Error(
3083
- `Unable to create a remote release client because the GitHub repo slug could not be determined. Please ensure you have a valid GitHub remote configured.`
3084
- );
3085
- }
3086
- return new GithubRemoteReleaseClient(
3087
- repoData,
3088
- {
3089
- provider: "github",
3090
- hostname: repoData.hostname,
3091
- apiBaseUrl: repoData.apiBaseUrl
3092
- },
3093
- await resolveTokenData(repoData.hostname)
3094
- );
3095
- }
3096
- async function isUserAnOrganizationMember(userId, config5, remoteName = "origin") {
3097
- try {
3098
- const repoData = getGitHubRepoData(remoteName, "github");
3099
- if (!repoData) {
3100
- throw new Error(
3101
- `Unable to validate GitHub actor because the GitHub repo slug could not be determined. Please ensure you have a valid GitHub remote configured.`
3102
- );
3109
+ let projectGraph;
3110
+ try {
3111
+ projectGraph = readCachedProjectGraph$1();
3112
+ } catch {
3113
+ projectGraph = await createProjectGraphAsync$2({
3114
+ exitOnError: true,
3115
+ resetDaemonClient: true
3116
+ });
3103
3117
  }
3104
- const tokenData = await resolveTokenData(repoData.hostname);
3105
- if (!tokenData.token) {
3118
+ if (!projectGraph) {
3106
3119
  throw new Error(
3107
- `Unable to validate GitHub actor because no token was provided. Please set the GITHUB_TOKEN or GH_TOKEN environment variable, or ensure you have an active session via the official gh CLI tool (https://cli.github.com).`
3120
+ "Failed to load the project graph. Please run `nx reset`, then run the `storm-git commit` command again."
3108
3121
  );
3109
3122
  }
3110
- const result = await makeGithubRequest(
3111
- {
3112
- repo: repoData.slug,
3113
- hostname: repoData.hostname,
3114
- apiBaseUrl: repoData.apiBaseUrl,
3115
- token: tokenData?.token || null
3116
- },
3117
- `/orgs/${typeof config5.organization === "string" ? config5.organization : config5.organization?.name}/members/${userId}`,
3118
- {}
3119
- );
3120
- if (result.status !== 204) {
3121
- return false;
3122
- }
3123
- return true;
3124
- } catch {
3125
- return false;
3126
- }
3127
- }
3128
-
3129
- // src/release/changelog.ts
3130
- function createAPI(overrideReleaseConfig) {
3131
- return async function releaseChangelog(args) {
3132
- const workspaceConfig = await getWorkspaceConfig();
3133
- const projectGraph = await createProjectGraphAsync$1({ exitOnError: true });
3134
- const nxJson = readNxJson$1();
3135
- const userProvidedReleaseConfig = deepMergeJson(
3136
- nxJson.release ?? {},
3137
- overrideReleaseConfig ?? {}
3138
- );
3139
- const { error: configError, nxReleaseConfig } = await createNxReleaseConfig(
3140
- projectGraph,
3141
- await createProjectFileMapUsingProjectGraph(projectGraph),
3142
- userProvidedReleaseConfig
3143
- );
3144
- if (configError) {
3145
- return await handleNxReleaseConfigError(configError, false);
3146
- }
3147
- if (args.printConfig) {
3148
- return printConfigAndExit({
3149
- userProvidedReleaseConfig,
3150
- nxReleaseConfig,
3151
- isDebug: args.printConfig === "debug"
3152
- });
3153
- }
3154
- if ((args.gitCommit === void 0 || args.gitTag === void 0 || args.stageChanges === void 0) && userProvidedReleaseConfig.git) {
3155
- const nxJsonMessage = await resolveNxJsonConfigErrorMessage([
3156
- "release",
3157
- "git"
3158
- ]);
3159
- output.error({
3160
- title: `The "release.git" property in nx.json may not be used with the "nx release changelog" subcommand or programmatic API. Instead, configure git options for subcommands directly with "release.version.git" and "release.changelog.git".`,
3161
- bodyLines: [nxJsonMessage]
3162
- });
3163
- process.exit(1);
3164
- }
3165
- const {
3166
- error: filterError,
3167
- filterLog,
3168
- releaseGroups,
3169
- releaseGroupToFilteredProjects
3170
- } = filterReleaseGroups(
3123
+ return new _StormReleaseClient(
3171
3124
  projectGraph,
3172
- nxReleaseConfig,
3173
- args.projects,
3174
- args.groups
3175
- );
3176
- if (filterError) {
3177
- output.error(filterError);
3178
- process.exit(1);
3179
- }
3180
- if (filterLog && process.env.NX_RELEASE_INTERNAL_SUPPRESS_FILTER_LOG !== "true") {
3181
- output.note(filterLog);
3182
- }
3183
- const rawVersionPlans = await readRawVersionPlans();
3184
- await setResolvedVersionPlansOnGroups(
3185
- rawVersionPlans,
3186
- releaseGroups,
3187
- Object.keys(projectGraph.nodes),
3188
- !!args.verbose
3189
- );
3190
- if (args.deleteVersionPlans === void 0) {
3191
- args.deleteVersionPlans = true;
3192
- }
3193
- const changelogGenerationEnabled = !!nxReleaseConfig?.changelog?.workspaceChangelog || nxReleaseConfig?.groups && Object.values(nxReleaseConfig?.groups).some((g) => g.changelog);
3194
- if (!changelogGenerationEnabled) {
3195
- output.warn({
3196
- title: `Changelogs are disabled. No changelog entries will be generated`,
3197
- bodyLines: [
3198
- `To explicitly enable changelog generation, configure "release.changelog.workspaceChangelog" or "release.changelog.projectChangelogs" in nx.json.`
3199
- ]
3200
- });
3201
- return {};
3202
- }
3203
- const tree = new FsTree(workspaceRoot, !!args.verbose);
3204
- const useAutomaticFromRef = nxReleaseConfig?.changelog?.automaticFromRef || args.firstRelease;
3205
- const { workspaceChangelogVersion, projectsVersionData } = resolveChangelogVersions(
3206
- args,
3207
- releaseGroups,
3208
- releaseGroupToFilteredProjects
3125
+ releaseConfig,
3126
+ ignoreNxJsonConfig,
3127
+ workspaceConfig
3209
3128
  );
3210
- const to = args.to || "HEAD";
3211
- const toSHA = await getCommitHash(to);
3212
- const headSHA = to === "HEAD" ? toSHA : await getCommitHash("HEAD");
3213
- const autoCommitEnabled = args.gitCommit ?? nxReleaseConfig.changelog?.git.commit;
3214
- if (autoCommitEnabled && headSHA !== toSHA) {
3215
- throw new Error(
3216
- `You are attempting to recreate the changelog for an old release (Head: "${headSHA}", To: "${toSHA}", From: "${args.from}"), but you have enabled auto-commit mode. Please disable auto-commit mode by updating your nx.json, or passing --git-commit=false`
3217
- );
3129
+ }
3130
+ #releaseChangelog;
3131
+ /**
3132
+ * The release configuration used by this release client.
3133
+ */
3134
+ config;
3135
+ /**
3136
+ * The workspace configuration used by this release client.
3137
+ */
3138
+ workspaceConfig;
3139
+ /**
3140
+ * The project graph of the workspace.
3141
+ */
3142
+ projectGraph;
3143
+ /**
3144
+ * The project configurations of the workspace.
3145
+ */
3146
+ projectConfigurations;
3147
+ /**
3148
+ * The file system tree used by this release client.
3149
+ */
3150
+ tree;
3151
+ /**
3152
+ * Creates an instance of {@link StormReleaseClient}.
3153
+ *
3154
+ * @param projectGraph - The project graph of the workspace.
3155
+ * @param releaseConfig - Release configuration to use for the current release client. By default, it will be combined with any configuration in `nx.json`, but you can choose to use it as the sole source of truth by setting {@link ignoreNxJsonConfig} to true.
3156
+ * @param ignoreNxJsonConfig - Whether to ignore the nx.json configuration and use only the provided {@link releaseConfig}. Default is false.
3157
+ * @param workspaceConfig - Optional Storm workspace configuration object for logging purposes.
3158
+ */
3159
+ constructor(projectGraph, releaseConfig, ignoreNxJsonConfig, workspaceConfig) {
3160
+ let nxJson;
3161
+ if (!ignoreNxJsonConfig && existsSync$1(joinPaths(workspaceConfig.workspaceRoot, "nx.json"))) {
3162
+ nxJson = readNxJson();
3218
3163
  }
3219
- const commitMessage = args.gitCommitMessage || nxReleaseConfig.changelog?.git?.commitMessage;
3220
- const commitMessageValues = createCommitMessageValues(
3221
- releaseGroups,
3222
- releaseGroupToFilteredProjects,
3223
- projectsVersionData,
3224
- commitMessage
3225
- );
3226
- const gitTagValues = args.gitTag ?? nxReleaseConfig.changelog?.git.tag ? createGitTagValues(
3227
- releaseGroups,
3228
- releaseGroupToFilteredProjects,
3229
- projectsVersionData
3230
- ) : [];
3231
- handleDuplicateGitTags(gitTagValues);
3232
- const postGitTasks = [];
3233
- let workspaceChangelogChanges = [];
3234
- let workspaceChangelogCommits = [];
3235
- const versionPlansEnabledForWorkspaceChangelog = releaseGroups[0]?.resolvedVersionPlans;
3236
- if (versionPlansEnabledForWorkspaceChangelog) {
3237
- if (releaseGroups.length === 1) {
3238
- const releaseGroup = releaseGroups[0];
3239
- if (releaseGroup?.projectsRelationship === "fixed") {
3240
- const versionPlans = releaseGroup?.resolvedVersionPlans;
3241
- workspaceChangelogChanges = versionPlans.flatMap((vp) => {
3242
- const releaseType = versionPlanSemverReleaseTypeToChangelogType(
3243
- vp.groupVersionBump
3244
- );
3245
- let githubReferences = [];
3246
- let author = void 0;
3247
- const parsedCommit = vp.commit ? parseGitCommit(vp.commit, true) : null;
3248
- if (parsedCommit) {
3249
- githubReferences = parsedCommit.references;
3250
- author = parsedCommit.author;
3251
- }
3252
- if (!author) {
3253
- return [];
3254
- }
3255
- const changes = !vp.triggeredByProjects ? {
3256
- type: releaseType.type,
3257
- scope: "",
3258
- description: vp.message,
3259
- body: "",
3260
- isBreaking: releaseType.isBreaking,
3261
- githubReferences,
3262
- // TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
3263
- authors: [author],
3264
- affectedProjects: "*"
3265
- } : vp.triggeredByProjects.map((project) => {
3266
- return {
3267
- type: releaseType.type,
3268
- scope: project,
3269
- description: vp.message,
3270
- body: "",
3271
- isBreaking: releaseType.isBreaking,
3272
- githubReferences,
3273
- // TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
3274
- authors: [author],
3275
- affectedProjects: [project]
3276
- };
3277
- });
3278
- return changes;
3279
- }).filter(Boolean);
3280
- }
3281
- }
3282
- } else {
3283
- let workspaceChangelogFromRef = args.from || (await getLatestGitTagForPattern(
3284
- nxReleaseConfig.releaseTagPattern,
3285
- {},
3286
- {
3287
- checkAllBranchesWhen: nxReleaseConfig.releaseTagPatternCheckAllBranchesWhen,
3288
- // preid:
3289
- // workspacePreid ??
3290
- // projectsPreid?.[Object.keys(projectsPreid)[0]],
3291
- releaseTagPatternRequireSemver: nxReleaseConfig.releaseTagPatternRequireSemver,
3292
- releaseTagPatternStrictPreid: nxReleaseConfig.releaseTagPatternStrictPreid
3293
- }
3294
- ))?.tag;
3295
- if (!workspaceChangelogFromRef) {
3296
- if (useAutomaticFromRef) {
3297
- workspaceChangelogFromRef = await getFirstGitCommit();
3298
- if (args.verbose) {
3299
- console.log(
3300
- `Determined workspace --from ref from the first commit in the workspace: ${workspaceChangelogFromRef}`
3301
- );
3164
+ const config5 = defu(
3165
+ {
3166
+ changelog: {
3167
+ renderOptions: {
3168
+ workspaceConfig
3302
3169
  }
3303
- } else {
3304
- throw new Error(
3305
- `Unable to determine the previous git tag. If this is the first release of your workspace, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`
3306
- );
3307
3170
  }
3308
- }
3309
- const workspaceChangelogFromSHA = await getCommitHash(
3310
- workspaceChangelogFromRef
3311
- );
3312
- workspaceChangelogCommits = await getCommits(
3313
- workspaceChangelogFromSHA,
3314
- toSHA
3315
- );
3316
- workspaceChangelogChanges = filterHiddenChanges(
3317
- workspaceChangelogCommits.map((c) => {
3318
- return {
3319
- type: c.type,
3320
- scope: c.scope,
3321
- description: c.description,
3322
- body: c.body,
3323
- isBreaking: c.isBreaking,
3324
- githubReferences: c.references,
3325
- authors: [c.author],
3326
- shortHash: c.shortHash,
3327
- revertedHashes: c.revertedHashes,
3328
- affectedProjects: "*"
3329
- };
3330
- }),
3331
- nxReleaseConfig.conventionalCommits
3332
- );
3333
- }
3334
- const workspaceChangelog = await generateChangelogForWorkspace({
3335
- tree,
3336
- args,
3337
- nxReleaseConfig,
3338
- workspaceChangelogVersion,
3339
- changes: workspaceChangelogChanges,
3340
- // TODO: remove this after the changelog renderer is refactored to remove coupling with git commits
3341
- commits: filterHiddenCommits(
3342
- workspaceChangelogCommits,
3343
- nxReleaseConfig.conventionalCommits
3344
- )
3171
+ },
3172
+ {
3173
+ groups: getReleaseGroupConfig(releaseConfig, workspaceConfig)
3174
+ },
3175
+ {
3176
+ groups: getReleaseGroupConfig(nxJson.release ?? {}, workspaceConfig)
3177
+ },
3178
+ omit(releaseConfig, ["groups"]),
3179
+ nxJson.release ? omit(nxJson.release, ["groups"]) : {},
3180
+ omit(DEFAULT_RELEASE_CONFIG, ["groups"])
3181
+ );
3182
+ super(config5, true);
3183
+ writeDebug(
3184
+ "Executing release with the following configuration",
3185
+ workspaceConfig
3186
+ );
3187
+ writeDebug(config5, workspaceConfig);
3188
+ this.projectGraph = projectGraph;
3189
+ this.config = config5;
3190
+ this.workspaceConfig = workspaceConfig;
3191
+ this.tree = new FsTree(workspaceConfig.workspaceRoot, false);
3192
+ this.#releaseChangelog = createAPI(config5, true);
3193
+ this.projectConfigurations = readProjectsConfigurationFromProjectGraph$2(projectGraph);
3194
+ }
3195
+ releaseChangelog = async (options) => {
3196
+ const result = await this.#releaseChangelog({
3197
+ ...options,
3198
+ gitCommit: false,
3199
+ gitTag: false
3345
3200
  });
3346
- if (workspaceChangelog && shouldCreateGitHubRelease(
3347
- nxReleaseConfig.changelog?.workspaceChangelog,
3348
- args.createRelease
3349
- )) {
3350
- postGitTasks.push(async (latestCommit) => {
3351
- const contents = formatGithubReleaseNotes(
3352
- workspaceChangelog.releaseVersion,
3353
- workspaceChangelog.contents,
3354
- null,
3355
- workspaceConfig
3356
- );
3357
- output.logSingleLine(`Creating GitHub Release
3358
-
3359
- ${contents}`);
3360
- await createOrUpdateGithubRelease(
3361
- nxReleaseConfig.changelog?.workspaceChangelog ? nxReleaseConfig.changelog?.workspaceChangelog.createRelease : defaultCreateReleaseProvider,
3362
- workspaceChangelog.releaseVersion,
3363
- contents,
3364
- latestCommit,
3365
- { dryRun: !!args.dryRun }
3366
- );
3367
- });
3368
- } else {
3369
- output.logSingleLine(
3370
- `Skipping GitHub Release for workspace changelog as it is disabled in the release group configuration`
3371
- );
3372
- }
3373
- const projectToAdditionalDependencyBumps = /* @__PURE__ */ new Map();
3374
- for (const releaseGroup of releaseGroups) {
3375
- if (releaseGroup.projectsRelationship !== "independent") {
3376
- continue;
3377
- }
3378
- for (const project of releaseGroup.projects) {
3379
- if (!projectsVersionData[project]?.newVersion) {
3380
- continue;
3381
- }
3382
- const dependentProjects = (projectsVersionData[project].dependentProjects || []).map((dep) => {
3383
- return {
3384
- dependencyName: dep.source,
3385
- newVersion: projectsVersionData[dep.source]?.newVersion
3386
- };
3387
- }).filter((b) => b.newVersion !== null);
3388
- for (const dependent of dependentProjects) {
3389
- const additionalDependencyBumpsForProject = (projectToAdditionalDependencyBumps.has(dependent.dependencyName) ? projectToAdditionalDependencyBumps.get(dependent.dependencyName) : []) ?? [];
3390
- additionalDependencyBumpsForProject.push({
3391
- dependencyName: project,
3392
- newVersion: projectsVersionData[project].newVersion
3393
- });
3394
- projectToAdditionalDependencyBumps.set(
3395
- dependent.dependencyName,
3396
- additionalDependencyBumpsForProject
3397
- );
3398
- }
3399
- }
3400
- }
3401
- const allProjectChangelogs = {};
3402
- for (const releaseGroup of releaseGroups) {
3403
- const config5 = releaseGroup.changelog;
3404
- if (config5 === false) {
3405
- continue;
3406
- }
3407
- const projects = args.projects?.length ? (
3408
- // If the user has passed a list of projects, we need to use the filtered list of projects within the release group, plus any dependents
3409
- Array.from(releaseGroupToFilteredProjects.get(releaseGroup)).flatMap(
3410
- (project) => {
3411
- return [
3412
- project,
3413
- ...projectsVersionData[project]?.dependentProjects.map(
3414
- (dep) => dep.source
3415
- ) || []
3416
- ];
3417
- }
3418
- )
3419
- ) : (
3420
- // Otherwise, we use the full list of projects within the release group
3421
- releaseGroup.projects
3422
- );
3423
- const projectNodes = projects.map((name) => projectGraph.nodes[name]);
3424
- if (releaseGroup.projectsRelationship === "independent") {
3425
- for (const project of projectNodes) {
3426
- let changes = null;
3427
- let commits = void 0;
3428
- if (releaseGroup.resolvedVersionPlans) {
3429
- changes = releaseGroup.resolvedVersionPlans.filter((vp) => vp.projectVersionBumps[project.name]).map((vp) => {
3430
- const bumpForProject = vp.projectVersionBumps[project.name];
3431
- const releaseType = versionPlanSemverReleaseTypeToChangelogType(bumpForProject);
3432
- let githubReferences = [];
3433
- let authors = [];
3434
- const parsedCommit = vp.commit ? parseGitCommit(vp.commit, true) : null;
3435
- if (parsedCommit) {
3436
- githubReferences = parsedCommit.references;
3437
- authors = [parsedCommit.author];
3438
- }
3439
- return {
3440
- type: releaseType.type,
3441
- scope: project.name,
3442
- description: vp.message,
3443
- body: "",
3444
- isBreaking: releaseType.isBreaking,
3445
- affectedProjects: Object.keys(vp.projectVersionBumps),
3446
- githubReferences,
3447
- authors
3448
- };
3449
- }).filter(Boolean);
3450
- } else {
3451
- let fromRef = args.from || (await getLatestGitTagForPattern(
3452
- releaseGroup.releaseTagPattern,
3453
- {
3454
- projectName: project.name,
3455
- releaseGroupName: releaseGroup.name
3456
- },
3457
- releaseGroup.releaseTagPatternCheckAllBranchesWhen
3458
- ))?.tag;
3459
- if (!fromRef && useAutomaticFromRef) {
3460
- const firstCommit = await getFirstGitCommit();
3461
- const allCommits = await getCommits(firstCommit, toSHA);
3462
- const commitsForProject = allCommits.filter(
3463
- (c) => c.affectedFiles.find((f) => f.startsWith(project.data.root))
3201
+ if (result.projectChangelogs) {
3202
+ await Promise.all(
3203
+ Object.entries(result.projectChangelogs).map(
3204
+ async ([project, changelog]) => {
3205
+ if (!this.projectGraph.nodes[project]?.data.root) {
3206
+ writeWarning(
3207
+ `A changelog was generated for ${project}, but it could not be found in the project graph. Skipping writing changelog file.`,
3208
+ this.workspaceConfig
3209
+ );
3210
+ } else if (changelog.contents) {
3211
+ const filePath = joinPaths(
3212
+ this.projectGraph.nodes[project].data.root,
3213
+ "CHANGELOG.md"
3464
3214
  );
3465
- fromRef = commitsForProject[0]?.shortHash;
3466
- if (args.verbose) {
3467
- console.log(
3468
- `Determined --from ref for ${project.name} from the first commit in which it exists: ${fromRef}`
3469
- );
3215
+ let currentContent;
3216
+ if (existsSync$1(filePath)) {
3217
+ currentContent = await readFile$1(filePath, "utf8");
3470
3218
  }
3471
- commits = commitsForProject;
3472
- }
3473
- if (!fromRef && !commits) {
3474
- throw new Error(
3475
- `Unable to determine the previous git tag. If this is the first release of your workspace, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`
3219
+ writeDebug(
3220
+ `\u270D\uFE0F Writing changelog for project ${project} to ${filePath}`,
3221
+ this.workspaceConfig
3476
3222
  );
3477
- }
3478
- if (!commits) {
3479
- commits = await getCommits(fromRef, toSHA);
3480
- }
3481
- const { fileMap } = await createFileMapUsingProjectGraph(projectGraph);
3482
- const fileToProjectMap = createFileToProjectMap(
3483
- fileMap.projectFileMap
3484
- );
3485
- changes = filterHiddenChanges(
3486
- commits.map((c) => ({
3487
- type: c.type,
3488
- scope: c.scope,
3489
- description: c.description,
3490
- body: c.body,
3491
- isBreaking: c.isBreaking,
3492
- githubReferences: c.references,
3493
- // TODO: Implement support for Co-authored-by and adding multiple authors
3494
- authors: [c.author],
3495
- shortHash: c.shortHash,
3496
- revertedHashes: c.revertedHashes,
3497
- affectedProjects: commitChangesNonProjectFiles(
3498
- c,
3499
- fileMap.nonProjectFiles
3500
- ) ? "*" : getProjectsAffectedByCommit(c, fileToProjectMap)
3501
- })),
3502
- nxReleaseConfig.conventionalCommits
3503
- );
3504
- }
3505
- const projectChangelogs = await generateChangelogForProjects({
3506
- tree,
3507
- args,
3508
- changes,
3509
- projectsVersionData,
3510
- releaseGroup,
3511
- projects: [project],
3512
- nxReleaseConfig,
3513
- projectToAdditionalDependencyBumps
3514
- });
3515
- for (const [projectName, projectChangelog] of Object.entries(
3516
- projectChangelogs
3517
- )) {
3518
- if (projectChangelogs && shouldCreateGitHubRelease(
3519
- releaseGroup.changelog,
3520
- args.createRelease
3521
- )) {
3522
- postGitTasks.push(async (latestCommit) => {
3523
- const contents = formatGithubReleaseNotes(
3524
- projectChangelog.releaseVersion,
3525
- projectChangelog.contents,
3526
- projectName,
3527
- workspaceConfig
3528
- );
3529
- output.logSingleLine(`Creating GitHub Release
3530
-
3531
- ${contents}`);
3532
- await createOrUpdateGithubRelease(
3533
- releaseGroup.changelog ? releaseGroup.changelog.createRelease : defaultCreateReleaseProvider,
3534
- projectChangelog.releaseVersion,
3535
- contents,
3536
- latestCommit,
3537
- { dryRun: !!args.dryRun }
3538
- );
3539
- });
3540
- } else {
3541
- output.logSingleLine(
3542
- `Skipping GitHub Release for ${projectName} as it is disabled in the release group configuration`
3223
+ const content = await generateChangelogContent(
3224
+ changelog.releaseVersion,
3225
+ filePath,
3226
+ changelog.contents,
3227
+ currentContent,
3228
+ project,
3229
+ this.workspaceConfig
3543
3230
  );
3544
- }
3545
- allProjectChangelogs[projectName] = projectChangelog;
3546
- }
3547
- }
3548
- } else {
3549
- let changes = [];
3550
- let commits = [];
3551
- if (releaseGroup.resolvedVersionPlans) {
3552
- changes = releaseGroup.resolvedVersionPlans.flatMap((vp) => {
3553
- const releaseType = versionPlanSemverReleaseTypeToChangelogType(
3554
- vp.groupVersionBump
3555
- );
3556
- let githubReferences = [];
3557
- let author = void 0;
3558
- const parsedCommit = vp.commit ? parseGitCommit(vp.commit, true) : null;
3559
- if (parsedCommit) {
3560
- githubReferences = parsedCommit.references;
3561
- author = parsedCommit.author;
3562
- }
3563
- const changes2 = !vp.triggeredByProjects ? {
3564
- type: releaseType.type,
3565
- scope: "",
3566
- description: vp.message,
3567
- body: "",
3568
- isBreaking: releaseType.isBreaking,
3569
- githubReferences,
3570
- // TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
3571
- authors: [author],
3572
- affectedProjects: "*"
3573
- } : vp.triggeredByProjects.map((project) => {
3574
- return {
3575
- type: releaseType.type,
3576
- scope: project,
3577
- description: vp.message,
3578
- body: "",
3579
- isBreaking: releaseType.isBreaking,
3580
- githubReferences,
3581
- // TODO(JamesHenry): Implement support for Co-authored-by and adding multiple authors
3582
- authors: [author],
3583
- affectedProjects: [project]
3584
- };
3585
- });
3586
- return changes2;
3587
- }).filter(Boolean);
3588
- } else {
3589
- let fromRef = args.from || (await getLatestGitTagForPattern(
3590
- releaseGroup.releaseTagPattern,
3591
- {},
3592
- releaseGroup.releaseTagPatternCheckAllBranchesWhen
3593
- ))?.tag;
3594
- if (!fromRef) {
3595
- if (useAutomaticFromRef) {
3596
- fromRef = await getFirstGitCommit();
3597
- if (args.verbose) {
3598
- console.log(
3599
- `Determined release group --from ref from the first commit in the workspace: ${fromRef}`
3600
- );
3601
- }
3602
- } else {
3603
- throw new Error(
3604
- `Unable to determine the previous git tag. If this is the first release of your release group, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTagPattern" property in nx.json to match the structure of your repository's git tags.`
3231
+ this.tree.write(filePath, content);
3232
+ printAndFlushChanges(
3233
+ this.tree,
3234
+ !!options.dryRun,
3235
+ 3,
3236
+ false,
3237
+ noDiffInChangelogMessage,
3238
+ // Only print the change for the current changelog file at this point
3239
+ (f) => f.path === filePath
3605
3240
  );
3606
3241
  }
3607
3242
  }
3608
- const fromSHA = await getCommitHash(fromRef);
3609
- const { fileMap } = await createFileMapUsingProjectGraph(projectGraph);
3610
- const fileToProjectMap = createFileToProjectMap(
3611
- fileMap.projectFileMap
3612
- );
3613
- commits = await getCommits(fromSHA, toSHA);
3614
- changes = filterHiddenChanges(
3615
- commits.map((c) => ({
3616
- type: c.type,
3617
- scope: c.scope,
3618
- description: c.description,
3619
- body: c.body,
3620
- isBreaking: c.isBreaking,
3621
- githubReferences: c.references,
3622
- // TODO: Implement support for Co-authored-by and adding multiple authors
3623
- authors: [c.author],
3624
- shortHash: c.shortHash,
3625
- revertedHashes: c.revertedHashes,
3626
- affectedProjects: commitChangesNonProjectFiles(
3627
- c,
3628
- fileMap.nonProjectFiles
3629
- ) ? "*" : getProjectsAffectedByCommit(c, fileToProjectMap)
3630
- })),
3631
- nxReleaseConfig.conventionalCommits
3632
- );
3633
- }
3634
- const projectChangelogs = await generateChangelogForProjects({
3635
- tree,
3636
- args,
3637
- changes,
3638
- projectsVersionData,
3639
- releaseGroup,
3640
- projects: projectNodes,
3641
- nxReleaseConfig,
3642
- projectToAdditionalDependencyBumps
3643
- });
3644
- for (const [projectName, projectChangelog] of Object.entries(
3645
- projectChangelogs
3646
- )) {
3647
- if (projectChangelogs && shouldCreateGitHubRelease(
3648
- releaseGroup.changelog,
3649
- args.createRelease
3650
- )) {
3651
- postGitTasks.push(async (latestCommit) => {
3652
- output.logSingleLine(`Creating GitHub Release`);
3653
- await createOrUpdateGithubRelease(
3654
- releaseGroup.changelog ? releaseGroup.changelog.createRelease : defaultCreateReleaseProvider,
3655
- projectChangelog.releaseVersion,
3656
- projectChangelog.contents,
3657
- latestCommit,
3658
- { dryRun: !!args.dryRun }
3659
- );
3660
- });
3661
- } else {
3662
- output.logSingleLine(
3663
- `Skipping GitHub Release for ${projectName} as it is disabled in the release group configuration`
3664
- );
3665
- }
3666
- allProjectChangelogs[projectName] = projectChangelog;
3667
- }
3668
- }
3243
+ )
3244
+ );
3245
+ this.applyChangesAndExit(options, result);
3669
3246
  }
3670
- await applyChangesAndExit(
3671
- args,
3672
- nxReleaseConfig,
3673
- tree,
3674
- toSHA,
3675
- postGitTasks,
3676
- commitMessageValues,
3677
- gitTagValues,
3678
- releaseGroups
3679
- );
3680
- return {
3681
- workspaceChangelog,
3682
- projectChangelogs: allProjectChangelogs
3683
- };
3247
+ return result;
3684
3248
  };
3685
- }
3686
- function resolveChangelogVersions(args, releaseGroups, releaseGroupToFilteredProjects) {
3687
- if (!args.version && !args.versionData) {
3688
- throw new Error(
3689
- `You must provide a version string and/or a versionData object.`
3690
- );
3691
- }
3692
- if (args.version && !valid(args.version)) {
3693
- throw new Error(
3694
- `The given version "${args.version}" is not a valid semver version. Please provide your version in the format "1.0.0", "1.0.0-beta.1" etc`
3695
- );
3696
- }
3697
- const versionData = releaseGroups.reduce(
3698
- (versionData2, releaseGroup) => {
3699
- const releaseGroupProjectNames = Array.from(
3700
- releaseGroupToFilteredProjects.get(releaseGroup)
3701
- );
3702
- for (const projectName of releaseGroupProjectNames) {
3703
- if (!args.versionData) {
3704
- versionData2[projectName] = {
3705
- newVersion: args.version,
3706
- currentVersion: "",
3707
- // not relevant within changelog/commit generation
3708
- dependentProjects: []
3709
- // not relevant within changelog/commit generation
3710
- };
3711
- continue;
3712
- }
3713
- if (!args.versionData[projectName]) {
3714
- throw new Error(
3715
- `The provided versionData object does not contain a version for project "${projectName}". This suggests a filtering mismatch between the version and changelog command invocations.`
3716
- );
3717
- }
3249
+ checkChangelogFilesEnabled() {
3250
+ if (this.config.changelog?.workspaceChangelog && (this.config.changelog?.workspaceChangelog === true || this.config.changelog?.workspaceChangelog.file)) {
3251
+ return true;
3252
+ }
3253
+ for (const releaseGroup of Object.values(this.config.groups)) {
3254
+ if (releaseGroup.changelog && releaseGroup.changelog !== true && releaseGroup.changelog.file) {
3255
+ return true;
3718
3256
  }
3719
- return versionData2;
3720
- },
3721
- args.versionData || {}
3722
- );
3723
- return {
3724
- workspaceChangelogVersion: args.version,
3725
- projectsVersionData: versionData
3726
- };
3727
- }
3728
- async function applyChangesAndExit(args, nxReleaseConfig, tree, toSHA, postGitTasks, commitMessageValues, gitTagValues, releaseGroups) {
3729
- let latestCommit = toSHA;
3730
- const changes = tree.listChanges();
3731
- const changelogFilesEnabled = checkChangelogFilesEnabled(nxReleaseConfig);
3732
- if (changelogFilesEnabled && !changes.length) {
3733
- output.warn({
3734
- title: `No changes detected for changelogs`,
3735
- bodyLines: [
3736
- `No changes were detected for any changelog files, so no changelog entries will be generated.`
3737
- ]
3738
- });
3739
- if (!postGitTasks.length) {
3740
- return;
3741
3257
  }
3742
- if (isCI()) {
3258
+ return false;
3259
+ }
3260
+ isCI = () => {
3261
+ if (process.env.CI === "false") {
3262
+ return false;
3263
+ }
3264
+ return process.env.CI || process.env.TF_BUILD === "true" || process.env.GITHUB_ACTIONS === "true" || process.env.BUILDKITE === "true" || process.env.CIRCLECI === "true" || process.env.CIRRUS_CI === "true" || process.env.TRAVIS === "true" || !!process.env["bamboo.buildKey"] || !!process.env["bamboo_buildKey"] || !!process.env.CODEBUILD_BUILD_ID || !!process.env.GITLAB_CI || !!process.env.HEROKU_TEST_RUN_ID || !!process.env.BUILD_ID || !!process.env.BUILD_NUMBER || !!process.env.BUILD_BUILDID || !!process.env.TEAMCITY_VERSION || !!process.env.JENKINS_URL || !!process.env.HUDSON_URL;
3265
+ };
3266
+ applyChangesAndExit = async (options, result) => {
3267
+ const postGitTasks = Object.values(result.projectChangelogs || {}).map((project) => project.postGitTask).filter(Boolean);
3268
+ const to = options.to || "HEAD";
3269
+ let latestCommit = await getCommitHash(to);
3270
+ const gitTagValues = options.gitTag ?? this.config.changelog?.git?.tag ? createGitTagValues(
3271
+ options.releaseGraph.releaseGroups,
3272
+ options.releaseGraph.releaseGroupToFilteredProjects,
3273
+ options.versionData
3274
+ ) : [];
3275
+ handleDuplicateGitTags(gitTagValues);
3276
+ const commitMessageValues = createCommitMessageValues(
3277
+ options.releaseGraph.releaseGroups,
3278
+ options.releaseGraph.releaseGroupToFilteredProjects,
3279
+ options.versionData,
3280
+ options.gitCommitMessage || this.config.changelog?.git?.commitMessage || "release(monorepo): Publish workspace release updates"
3281
+ );
3282
+ const changes = this.tree.listChanges();
3283
+ if (this.checkChangelogFilesEnabled() && !changes.length) {
3743
3284
  output.warn({
3744
- title: `Skipped GitHub release creation because no changes were detected for any changelog files.`
3285
+ title: `No changes detected for changelogs`,
3286
+ bodyLines: [
3287
+ `No changes were detected for any changelog files, so no changelog entries will be generated.`
3288
+ ]
3745
3289
  });
3290
+ if (!postGitTasks.length) {
3291
+ return;
3292
+ }
3293
+ for (const postGitTask of postGitTasks) {
3294
+ await postGitTask(latestCommit);
3295
+ }
3746
3296
  return;
3747
3297
  }
3748
- const shouldCreateGitHubReleaseAnyway = await promptForGitHubRelease();
3749
- if (!shouldCreateGitHubReleaseAnyway) {
3750
- return;
3751
- }
3752
- for (const postGitTask of postGitTasks) {
3753
- await postGitTask(latestCommit);
3754
- }
3755
- return;
3756
- }
3757
- const changedFiles = changes.map((f) => f.path);
3758
- let deletedFiles = [];
3759
- if (args.deleteVersionPlans) {
3760
- const planFiles = /* @__PURE__ */ new Set();
3761
- releaseGroups.forEach((group) => {
3762
- if (group.resolvedVersionPlans) {
3763
- group.resolvedVersionPlans.forEach((plan) => {
3764
- if (!args.dryRun) {
3765
- rmSync(plan.absolutePath, { recursive: true, force: true });
3766
- if (args.verbose) {
3767
- console.log(`Removing ${plan.relativePath}`);
3768
- }
3769
- } else {
3770
- if (args.verbose) {
3771
- console.log(
3772
- `Would remove ${plan.relativePath}, but --dry-run was set`
3773
- );
3774
- }
3775
- }
3776
- planFiles.add(plan.relativePath);
3777
- });
3778
- }
3779
- });
3780
- deletedFiles = Array.from(planFiles);
3781
- }
3782
- if (args.gitCommit ?? nxReleaseConfig.changelog?.git.commit) {
3298
+ const changedFiles = changes.map((f) => f.path);
3783
3299
  await commitChanges({
3784
3300
  changedFiles,
3785
- deletedFiles,
3786
- isDryRun: !!args.dryRun,
3787
- isVerbose: !!args.verbose,
3301
+ deletedFiles: [],
3302
+ isDryRun: !!options.dryRun,
3303
+ isVerbose: !!options.verbose,
3788
3304
  gitCommitMessages: commitMessageValues,
3789
- gitCommitArgs: args.gitCommitArgs ?? nxReleaseConfig.changelog?.git.commitArgs
3305
+ gitCommitArgs: options.gitCommitArgs || this.config.changelog?.git?.commitArgs
3790
3306
  });
3791
3307
  latestCommit = await getCommitHash("HEAD");
3792
- } else if ((args.stageChanges ?? nxReleaseConfig.changelog?.git.stageChanges) && changes.length) {
3793
- writeDebug(`Staging changed files with git`);
3794
- await gitAdd({
3795
- changedFiles,
3796
- deletedFiles,
3797
- dryRun: args.dryRun,
3798
- verbose: args.verbose
3799
- });
3800
- }
3801
- if (args.gitTag ?? nxReleaseConfig.changelog?.git.tag) {
3802
- writeDebug(`Tagging commit with git`);
3308
+ output.logSingleLine(`Tagging commit with git`);
3803
3309
  for (const tag of gitTagValues) {
3804
3310
  await gitTag({
3805
3311
  tag,
3806
- message: args.gitTagMessage || nxReleaseConfig.changelog?.git.tagMessage,
3807
- additionalArgs: args.gitTagArgs || nxReleaseConfig.changelog?.git.tagArgs,
3808
- dryRun: args.dryRun,
3809
- verbose: args.verbose
3810
- });
3811
- }
3812
- }
3813
- if (args.gitPush ?? nxReleaseConfig.changelog?.git.push) {
3814
- writeDebug(`Pushing to git remote "${args.gitRemote}"`);
3815
- await gitPush({
3816
- gitRemote: args.gitRemote,
3817
- dryRun: args.dryRun,
3818
- verbose: args.verbose
3819
- });
3820
- }
3821
- for (const postGitTask of postGitTasks) {
3822
- await postGitTask(latestCommit);
3823
- }
3824
- return;
3825
- }
3826
- async function generateChangelogForWorkspace({
3827
- tree,
3828
- args,
3829
- nxReleaseConfig,
3830
- workspaceChangelogVersion,
3831
- changes
3832
- }) {
3833
- const workspaceConfig = await getWorkspaceConfig();
3834
- if (!workspaceConfig) {
3835
- throw new Error(
3836
- `Unable to determine the Storm workspace config. Please ensure that your storm-workspace.json file is present and valid.`
3837
- );
3838
- }
3839
- const config5 = nxReleaseConfig.changelog?.workspaceChangelog;
3840
- if (config5 === false) {
3841
- return;
3842
- }
3843
- if (workspaceChangelogVersion === null) {
3844
- return;
3845
- }
3846
- if (!config5) {
3847
- throw new Error(
3848
- `Workspace changelog is enabled but no configuration was provided. Please provide a workspaceChangelog object in your nx.json`
3849
- );
3850
- }
3851
- if (Object.entries(nxReleaseConfig.groups ?? {}).length > 1) {
3852
- output.warn({
3853
- title: `Workspace changelog is enabled, but you have multiple release groups configured. This is not supported, so workspace changelog will be disabled.`,
3854
- bodyLines: [
3855
- `A single workspace version cannot be determined when defining multiple release groups because versions can differ between each group.`,
3856
- `Project level changelogs can be enabled with the "release.changelog.projectChangelogs" property.`
3857
- ]
3858
- });
3859
- return;
3860
- }
3861
- if (Object.values(nxReleaseConfig.groups ?? {})[0]?.projectsRelationship === "independent") {
3862
- output.warn({
3863
- title: `Workspace changelog is enabled, but you have configured an independent projects relationship. This is not supported, so workspace changelog will be disabled.`,
3864
- bodyLines: [
3865
- `A single workspace version cannot be determined when using independent projects because versions can differ between each project.`,
3866
- `Project level changelogs can be enabled with the "release.changelog.projectChangelogs" property.`
3867
- ]
3868
- });
3869
- return;
3870
- }
3871
- const interactive = args.interactive === "all" || args.interactive === "workspace";
3872
- const dryRun = !!args.dryRun;
3873
- const gitRemote = args.gitRemote;
3874
- let interpolatedTreePath = config5.file || "";
3875
- if (interpolatedTreePath) {
3876
- interpolatedTreePath = interpolate(interpolatedTreePath, {
3877
- projectName: "",
3878
- // n/a for the workspace changelog
3879
- projectRoot: "",
3880
- // n/a for the workspace changelog
3881
- workspaceRoot: ""
3882
- // within the tree, workspaceRoot is the root
3883
- });
3884
- }
3885
- const releaseVersion = new ReleaseVersion({
3886
- version: workspaceChangelogVersion,
3887
- releaseTagPattern: nxReleaseConfig.releaseTagPattern
3888
- });
3889
- if (interpolatedTreePath) {
3890
- const prefix = dryRun ? "Previewing" : "Generating";
3891
- output.log({
3892
- title: `${prefix} an entry in ${interpolatedTreePath} for ${releaseVersion.gitTag}`
3893
- });
3894
- }
3895
- const remoteReleaseClient = await createGithubRemoteReleaseClient(gitRemote);
3896
- const changelogRenderer = new StormChangelogRenderer({
3897
- changes,
3898
- changelogEntryVersion: releaseVersion.rawVersion,
3899
- project: null,
3900
- isVersionPlans: false,
3901
- entryWhenNoChanges: config5.entryWhenNoChanges,
3902
- changelogRenderOptions: config5.renderOptions,
3903
- conventionalCommitsConfig: nxReleaseConfig.conventionalCommits,
3904
- remoteReleaseClient
3905
- });
3906
- let contents = await changelogRenderer.render();
3907
- if (interactive) {
3908
- const tmpDir = dirSync().name;
3909
- const changelogPath = joinPathFragments$1(
3910
- tmpDir,
3911
- // Include the tree path in the name so that it is easier to identify which changelog file is being edited
3912
- `PREVIEW__${interpolatedTreePath.replace(/\//g, "_")}`
3913
- );
3914
- writeFileSync(changelogPath, contents);
3915
- await launchEditor(changelogPath);
3916
- contents = readFileSync(changelogPath, "utf8");
3917
- }
3918
- if (interpolatedTreePath) {
3919
- tree.write(
3920
- interpolatedTreePath,
3921
- await generateChangelogContent(
3922
- releaseVersion,
3923
- interpolatedTreePath,
3924
- contents,
3925
- tree.exists(interpolatedTreePath) ? tree.read(interpolatedTreePath)?.toString() : "",
3926
- null,
3927
- workspaceConfig
3928
- )
3929
- );
3930
- printAndFlushChanges(tree, !!dryRun, 3, false, noDiffInChangelogMessage);
3931
- }
3932
- return {
3933
- releaseVersion,
3934
- contents
3935
- };
3936
- }
3937
- async function generateChangelogForProjects({
3938
- tree,
3939
- args,
3940
- changes,
3941
- projectsVersionData,
3942
- releaseGroup,
3943
- projects,
3944
- nxReleaseConfig,
3945
- projectToAdditionalDependencyBumps
3946
- }) {
3947
- const workspaceConfig = await getWorkspaceConfig();
3948
- if (!workspaceConfig) {
3949
- throw new Error(
3950
- `Unable to determine the Storm workspace config. Please ensure that your storm-workspace.json file is present and valid.`
3951
- );
3952
- }
3953
- const config5 = releaseGroup.changelog;
3954
- if (config5 === false) {
3955
- return;
3956
- }
3957
- const interactive = args.interactive === "all" || args.interactive === "projects";
3958
- const dryRun = !!args.dryRun;
3959
- const gitRemote = args.gitRemote;
3960
- const projectChangelogs = {};
3961
- for (const project of projects) {
3962
- let interpolatedTreePath = config5.file || "";
3963
- if (interpolatedTreePath) {
3964
- interpolatedTreePath = interpolate(interpolatedTreePath, {
3965
- projectName: project.name,
3966
- projectRoot: project.data.root,
3967
- workspaceRoot: ""
3312
+ message: options.gitTagMessage || this.config.changelog?.git?.tagMessage,
3313
+ additionalArgs: options.gitTagArgs || this.config.changelog?.git?.tagArgs,
3314
+ dryRun: options.dryRun,
3315
+ verbose: options.verbose
3968
3316
  });
3969
3317
  }
3970
- const newVersion = projectsVersionData[project.name]?.newVersion;
3971
- if (!newVersion) {
3972
- continue;
3973
- }
3974
- const releaseVersion = new ReleaseVersion({
3975
- version: newVersion,
3976
- releaseTagPattern: releaseGroup.releaseTagPattern,
3977
- projectName: project.name
3978
- });
3979
- if (interpolatedTreePath) {
3980
- const prefix = dryRun ? "Previewing" : "Generating";
3981
- output.log({
3982
- title: `${prefix} an entry in ${interpolatedTreePath} for ${releaseVersion.gitTag}`
3983
- });
3984
- const remoteReleaseClient = await createGithubRemoteReleaseClient(gitRemote);
3985
- const changelogRenderer = new StormChangelogRenderer({
3986
- changes,
3987
- changelogEntryVersion: releaseVersion.rawVersion,
3988
- project: project.name,
3989
- entryWhenNoChanges: typeof config5.entryWhenNoChanges === "string" ? interpolate(config5.entryWhenNoChanges, {
3990
- projectName: project.name,
3991
- projectRoot: project.data.root,
3992
- workspaceRoot: ""
3993
- }) : false,
3994
- changelogRenderOptions: config5.renderOptions,
3995
- isVersionPlans: !!releaseGroup.versionPlans,
3996
- conventionalCommitsConfig: releaseGroup.versionPlans ? null : nxReleaseConfig.conventionalCommits,
3997
- dependencyBumps: projectToAdditionalDependencyBumps.get(project.name),
3998
- remoteReleaseClient
3999
- });
4000
- let contents = await changelogRenderer.render();
4001
- output.log({
4002
- title: `Changelog renderer for ${project.name} rendered the following content:
4003
-
4004
- ${contents}`.trim()
3318
+ if (options.gitPush ?? this.config.changelog?.git?.push) {
3319
+ output.logSingleLine(
3320
+ `Pushing to git remote "${options.gitRemote ?? "origin"}"`
3321
+ );
3322
+ await gitPush({
3323
+ gitRemote: options.gitRemote,
3324
+ dryRun: options.dryRun,
3325
+ verbose: options.verbose,
3326
+ additionalArgs: options.gitPushArgs || this.config.changelog?.git?.pushArgs
4005
3327
  });
4006
- if (interactive) {
4007
- const tmpDir = dirSync().name;
4008
- const changelogPath = joinPathFragments$1(
4009
- tmpDir,
4010
- // Include the tree path in the name so that it is easier to identify which changelog file is being edited
4011
- `PREVIEW__${interpolatedTreePath.replace(/\//g, "_")}`
4012
- );
4013
- writeFileSync(changelogPath, contents);
4014
- await launchEditor(changelogPath);
4015
- contents = readFileSync(changelogPath, "utf8");
4016
- }
4017
- if (interpolatedTreePath) {
4018
- tree.write(
4019
- interpolatedTreePath,
4020
- await generateChangelogContent(
4021
- releaseVersion,
4022
- interpolatedTreePath,
4023
- contents,
4024
- tree.exists(interpolatedTreePath) ? tree.read(interpolatedTreePath)?.toString() : "",
4025
- project.name,
4026
- workspaceConfig
4027
- )
4028
- );
4029
- printAndFlushChanges(
4030
- tree,
4031
- !!dryRun,
4032
- 3,
4033
- false,
4034
- noDiffInChangelogMessage,
4035
- // Only print the change for the current changelog file at this point
4036
- (f) => f.path === interpolatedTreePath
4037
- );
4038
- }
4039
- projectChangelogs[project.name] = {
4040
- releaseVersion,
4041
- contents
4042
- };
4043
- }
4044
- }
4045
- return projectChangelogs;
4046
- }
4047
- function checkChangelogFilesEnabled(nxReleaseConfig) {
4048
- if (nxReleaseConfig.changelog?.workspaceChangelog && nxReleaseConfig.changelog?.workspaceChangelog.file) {
4049
- return true;
4050
- }
4051
- return Object.values(nxReleaseConfig.groups ?? {}).some(
4052
- (releaseGroup) => typeof releaseGroup?.changelog === "boolean" && releaseGroup.changelog || releaseGroup?.changelog?.file
4053
- );
4054
- }
4055
- async function getCommits(fromSHA, toSHA) {
4056
- const rawCommits = await getGitDiff(fromSHA, toSHA);
4057
- return parseCommits(rawCommits);
4058
- }
4059
- function filterHiddenChanges(changes, conventionalCommitsConfig) {
4060
- return changes.filter((change) => {
4061
- const type = change.type;
4062
- const typeConfig = conventionalCommitsConfig.types[type];
4063
- if (!typeConfig) {
4064
- return false;
4065
- }
4066
- return !typeConfig.changelog.hidden;
4067
- });
4068
- }
4069
- function filterHiddenCommits(commits, conventionalCommitsConfig) {
4070
- if (!commits) {
4071
- return [];
4072
- }
4073
- return commits.filter((commit) => {
4074
- const type = commit.type;
4075
- const typeConfig = conventionalCommitsConfig.types[type];
4076
- if (!typeConfig) {
4077
- return false;
4078
- }
4079
- return !typeConfig.changelog.hidden;
4080
- });
4081
- }
4082
- function shouldCreateGitHubRelease(changelogConfig, createReleaseArg = void 0) {
4083
- if (createReleaseArg !== void 0) {
4084
- return createReleaseArg === "github";
4085
- }
4086
- if (changelogConfig === false) {
4087
- return false;
4088
- }
4089
- return changelogConfig.createRelease !== false;
4090
- }
4091
- async function promptForGitHubRelease() {
4092
- try {
4093
- const result = await prompt([
4094
- {
4095
- name: "confirmation",
4096
- message: "Do you want to create a GitHub release anyway?",
4097
- type: "confirm"
4098
- }
4099
- ]);
4100
- return result.confirmation;
4101
- } catch (e) {
4102
- return false;
4103
- }
4104
- }
4105
- function getProjectsAffectedByCommit(commit, fileToProjectMap) {
4106
- const affectedProjects = /* @__PURE__ */ new Set();
4107
- for (const file of commit.affectedFiles) {
4108
- affectedProjects.add(fileToProjectMap[file]);
4109
- }
4110
- return Array.from(affectedProjects);
4111
- }
4112
- function commitChangesNonProjectFiles(commit, nonProjectFiles) {
4113
- return nonProjectFiles.some(
4114
- (fileData) => commit.affectedFiles.includes(fileData.file)
4115
- );
4116
- }
4117
- function createFileToProjectMap(projectFileMap) {
4118
- const fileToProjectMap = {};
4119
- for (const [projectName, projectFiles] of Object.entries(projectFileMap)) {
4120
- for (const file of projectFiles) {
4121
- fileToProjectMap[file.file] = projectName;
4122
- }
4123
- }
4124
- return fileToProjectMap;
4125
- }
4126
- function versionPlanSemverReleaseTypeToChangelogType(bump) {
4127
- switch (bump) {
4128
- case "premajor":
4129
- case "major":
4130
- return { type: "feat", isBreaking: true };
4131
- case "preminor":
4132
- case "minor":
4133
- return { type: "feat", isBreaking: false };
4134
- case "prerelease":
4135
- case "prepatch":
4136
- case "patch":
4137
- return { type: "fix", isBreaking: false };
4138
- default:
4139
- throw new Error(`Invalid semver bump type: ${bump}`);
4140
- }
4141
- }
4142
- function formatGithubReleaseNotes(releaseVersion, content, projectName, workspaceConfig) {
4143
- if (!workspaceConfig) {
4144
- return content;
4145
- }
4146
- return `![${(typeof workspaceConfig.release.banner === "string" ? workspaceConfig.organization ? titleCase(
4147
- typeof workspaceConfig.organization === "string" ? workspaceConfig.organization : workspaceConfig.organization.name
4148
- ) : void 0 : workspaceConfig.release.banner.alt) || "Release banner header"}](${typeof workspaceConfig.release.banner === "string" ? workspaceConfig.release.banner : workspaceConfig.release.banner?.url})
4149
- ${workspaceConfig.release.header || ""}
4150
-
4151
- # ${projectName ? `${titleCase(projectName)} ` : ""}v${releaseVersion.rawVersion}
4152
-
4153
- We at [${workspaceConfig.organization ? titleCase(
4154
- typeof workspaceConfig.organization === "string" ? workspaceConfig.organization : workspaceConfig.organization.name
4155
- ) : ""}](${workspaceConfig.homepage}) are very excited to announce the v${releaseVersion.rawVersion} release of the ${projectName ? workspaceConfig.name ? `${titleCase(workspaceConfig.name)} - ${titleCase(projectName)}` : titleCase(projectName) : workspaceConfig.name ? titleCase(workspaceConfig.name) : "Storm Software"} project! \u{1F680}
4156
-
4157
- These changes are released under the ${workspaceConfig.license.includes("license") ? workspaceConfig.license : `${workspaceConfig.license} license`}. You can find more details on [our licensing page](${workspaceConfig.licensing}). You can find guides, API references, and other documentation around this release (and much more) on [our documentation site](${workspaceConfig.docs}).
4158
-
4159
- If you have any questions or comments, feel free to reach out to the team on [Discord](${workspaceConfig.socials.discord}) or [our contact page](${workspaceConfig.contact}). Please help us spread the word by giving [this repository](https://github.com/${typeof workspaceConfig.organization === "string" ? workspaceConfig.organization : workspaceConfig.organization?.name}/${workspaceConfig.name}) a star \u2B50 on GitHub or [posting on X (Twitter)](https://x.com/intent/tweet?text=Check%20out%20the%20latest%20@${workspaceConfig.socials.twitter}%20release%20${projectName ? `${titleCase(projectName)?.replaceAll(" ", "%20")}%20` : ""}v${releaseVersion.rawVersion}%20%F0%9F%9A%80%0D%0A%0D%0Ahttps://github.com/${typeof workspaceConfig.organization === "string" ? workspaceConfig.organization : workspaceConfig.organization?.name}/${workspaceConfig.name}/releases/tag/${releaseVersion.gitTag}) about this release!
4160
-
4161
- ## Release Notes
4162
-
4163
- ${content.replaceAll(
4164
- `## ${generateChangelogTitle(
4165
- releaseVersion.rawVersion,
4166
- projectName,
4167
- workspaceConfig
4168
- )}`,
4169
- ""
4170
- ).replaceAll(
4171
- `# ${generateChangelogTitle(releaseVersion.rawVersion, projectName, workspaceConfig)}`,
4172
- ""
4173
- )}
4174
-
4175
- ---
4176
-
4177
- ${workspaceConfig.release.footer}
4178
- `;
4179
- }
4180
-
4181
- // src/release/config.ts
4182
- var DEFAULT_CONVENTIONAL_COMMITS_CONFIG2 = {
4183
- questions: DEFAULT_MONOREPO_COMMIT_QUESTIONS,
4184
- types: DEFAULT_COMMIT_TYPES
4185
- };
4186
- var DEFAULT_RELEASE_GROUP_CONFIG = {
4187
- projectsRelationship: "independent",
4188
- releaseTagPattern: "{projectName}@{version}",
4189
- changelog: {
4190
- git: {
4191
- tag: true
4192
- },
4193
- createRelease: "github",
4194
- entryWhenNoChanges: false,
4195
- file: "{projectRoot}/CHANGELOG.md",
4196
- renderOptions: {
4197
- authors: false,
4198
- commitReferences: true,
4199
- versionTitleDate: true
4200
- }
4201
- },
4202
- version: {
4203
- groupPreVersionCommand: "pnpm build",
4204
- useLegacyVersioning: true,
4205
- currentVersionResolver: "git-tag",
4206
- specifierSource: "conventional-commits",
4207
- generator: "@storm-software/workspace-tools:release-version",
4208
- generatorOptions: {
4209
- currentVersionResolver: "git-tag",
4210
- specifierSource: "conventional-commits"
4211
- }
4212
- }
4213
- };
4214
- var DEFAULT_RELEASE_CONFIG = {
4215
- conventionalCommits: DEFAULT_CONVENTIONAL_COMMITS_CONFIG2,
4216
- changelog: {
4217
- git: {
4218
- tag: true
4219
- },
4220
- automaticFromRef: true,
4221
- workspaceChangelog: false,
4222
- projectChangelogs: {
4223
- createRelease: "github",
4224
- entryWhenNoChanges: false,
4225
- file: "{projectRoot}/CHANGELOG.md",
4226
- renderOptions: {
4227
- authors: false,
4228
- commitReferences: true,
4229
- versionTitleDate: true
4230
- }
4231
3328
  }
4232
- },
4233
- version: {
4234
- preVersionCommand: "pnpm build",
4235
- useLegacyVersioning: true,
4236
- currentVersionResolver: "git-tag",
4237
- specifierSource: "conventional-commits",
4238
- generator: "@storm-software/workspace-tools:release-version",
4239
- generatorOptions: {
4240
- currentVersionResolver: "git-tag",
4241
- specifierSource: "conventional-commits"
3329
+ for (const postGitTask of postGitTasks) {
3330
+ await postGitTask(latestCommit);
4242
3331
  }
4243
- }
3332
+ return;
3333
+ };
4244
3334
  };
4245
3335
 
4246
3336
  // src/release/run.ts
4247
- var runRelease = async (config5, options) => {
3337
+ var runRelease = async (config5, {
3338
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3339
+ project,
3340
+ head,
3341
+ base,
3342
+ dryRun = false,
3343
+ skipPublish = false,
3344
+ ignoreNxJsonConfig = false,
3345
+ ...releaseConfig
3346
+ }) => {
4248
3347
  if (!process.env.GITHUB_ACTOR) {
4249
3348
  throw new Error("The `GITHUB_ACTOR` environment variable is not set.");
4250
3349
  }
@@ -4266,11 +3365,15 @@ var runRelease = async (config5, options) => {
4266
3365
  process.env.NODE_AUTH_TOKEN = process.env.NPM_TOKEN;
4267
3366
  process.env.NPM_AUTH_TOKEN = process.env.NPM_TOKEN;
4268
3367
  process.env.NPM_CONFIG_PROVENANCE = "true";
4269
- writeDebug("Creating workspace Project Graph data...", config5);
4270
- const nxJson = readNxJson();
3368
+ writeDebug("Creating Storm release client...", config5);
3369
+ const releaseClient = await StormReleaseClient.create(
3370
+ releaseConfig,
3371
+ ignoreNxJsonConfig,
3372
+ config5
3373
+ );
4271
3374
  writeDebug("Reading in the workspaces release configuration", config5);
4272
- const to = options.head || process.env.NX_HEAD;
4273
- const from = options.base || process.env.NX_BASE;
3375
+ const to = head || process.env.NX_HEAD;
3376
+ const from = base || process.env.NX_BASE;
4274
3377
  writeDebug(
4275
3378
  `Using the following Git SHAs to determine the release content:
4276
3379
  - From: ${from}
@@ -4278,50 +3381,25 @@ var runRelease = async (config5, options) => {
4278
3381
  `,
4279
3382
  config5
4280
3383
  );
4281
- if (nxJson.release?.groups) {
4282
- nxJson.release.groups = Object.keys(nxJson.release.groups).reduce(
4283
- (ret, groupName) => {
4284
- const groupConfig = nxJson.release?.groups?.[groupName];
4285
- ret[groupName] = defu(groupConfig, DEFAULT_RELEASE_GROUP_CONFIG);
4286
- return ret;
4287
- },
4288
- {}
4289
- );
4290
- }
4291
- const nxReleaseConfig = defu(
4292
- nxJson.release,
4293
- DEFAULT_RELEASE_CONFIG
4294
- );
4295
- writeInfo(
4296
- "Using the following `nx.json` release configuration values",
4297
- config5
4298
- );
4299
- writeInfo(nxReleaseConfig, config5);
4300
- const releaseVersion = createAPI$1(nxReleaseConfig);
4301
- const releaseChangelog = createAPI(nxReleaseConfig);
4302
- const releasePublish = createAPI$2(nxReleaseConfig);
4303
3384
  writeDebug("Determining the current release versions...", config5);
4304
- const { workspaceVersion, projectsVersionData } = await releaseVersion({
4305
- dryRun: false,
3385
+ const { workspaceVersion, projectsVersionData, releaseGraph } = await releaseClient.releaseVersion({
3386
+ dryRun,
4306
3387
  verbose: isVerbose(config5.logLevel),
4307
3388
  preid: config5.preid,
4308
- deleteVersionPlans: false,
4309
3389
  stageChanges: true,
4310
3390
  gitCommit: false
4311
3391
  });
4312
- await releaseChangelog({
4313
- ...options,
4314
- version: nxReleaseConfig?.projectsRelationship !== "fixed" ? void 0 : workspaceVersion,
3392
+ await releaseClient.releaseChangelog({
3393
+ version: releaseConfig?.projectsRelationship === "fixed" ? workspaceVersion : void 0,
4315
3394
  versionData: projectsVersionData,
4316
- dryRun: false,
3395
+ dryRun,
4317
3396
  verbose: isVerbose(config5.logLevel),
4318
3397
  to,
4319
3398
  from,
4320
- gitCommit: true,
4321
- gitCommitMessage: "release(monorepo): Publish workspace release updates"
3399
+ releaseGraph
4322
3400
  });
4323
3401
  writeDebug("Tagging commit with git", config5);
4324
- if (options.skipPublish) {
3402
+ if (skipPublish) {
4325
3403
  writeWarning(
4326
3404
  "Skipping publishing packages since `skipPublish` was provided as `true` in the release options.",
4327
3405
  config5
@@ -4338,9 +3416,8 @@ ${changedProjects.map((changedProject) => ` - ${changedProject}`).join("\n")}
4338
3416
  config5
4339
3417
  );
4340
3418
  await updatePackageManifests(projectsVersionData, config5);
4341
- const result = await releasePublish({
4342
- ...options,
4343
- dryRun: !!options.dryRun,
3419
+ const result = await releaseClient.releasePublish({
3420
+ dryRun,
4344
3421
  verbose: isVerbose(config5.logLevel)
4345
3422
  });
4346
3423
  const failedProjects = Object.keys(result).filter(
@@ -4572,3 +3649,5 @@ void (async () => {
4572
3649
  process.exit(1);
4573
3650
  }
4574
3651
  })();
3652
+ //# sourceMappingURL=git.js.map
3653
+ //# sourceMappingURL=git.js.map