@storm-software/git-tools 2.123.18 → 2.124.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/git.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import './chunk-Q3DQKTOI.js';
2
3
  import { run } from './chunk-G3YPGVPS.js';
3
4
  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
5
  import TOML from '@ltd/j-toml';
@@ -26,23 +27,23 @@ import _ from 'underscore';
26
27
  import updateSection from 'update-section';
27
28
  import { readCachedProjectGraph as readCachedProjectGraph$1, createProjectGraphAsync as createProjectGraphAsync$2, readProjectsConfigurationFromProjectGraph as readProjectsConfigurationFromProjectGraph$2, output, joinPathFragments } from '@nx/devkit';
28
29
  import axios from 'axios';
29
- import 'enquirer';
30
30
  import { homedir } from 'node:os';
31
- import { printAndFlushChanges } from 'nx/src/command-line/release/utils/print-changes';
32
31
  import { defaultCreateReleaseProvider, GithubRemoteReleaseClient } from 'nx/src/command-line/release/utils/remote-release-clients/github';
33
- import { noDiffInChangelogMessage, handleDuplicateGitTags, createCommitMessageValues } from 'nx/src/command-line/release/utils/shared';
34
32
  import { parse } from 'yaml';
33
+ import chalk from 'chalk';
34
+ import { printAndFlushChanges } from 'nx/src/command-line/release/utils/print-changes';
35
+ import { createGitTagValues, handleDuplicateGitTags, createCommitMessageValues, isPrerelease, shouldPreferDockerVersionForReleaseGroup, ReleaseVersion, noDiffInChangelogMessage } from 'nx/src/command-line/release/utils/shared';
36
+ import { interpolate } from 'nx/src/tasks-runner/utils';
35
37
  import { resolveConfig, format } from 'prettier';
38
+ import { execCommand } from 'nx/src/command-line/release/utils/exec-command.js';
39
+ import { getCommitHash, getLatestGitTagForPattern, getFirstGitCommit, gitPush, getGitDiff, parseCommits, gitAdd } from 'nx/src/command-line/release/utils/git';
40
+ import { prerelease, major } from 'semver';
36
41
  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
42
  import { readNxJson } from 'nx/src/config/nx-json';
40
43
  import { FsTree } from 'nx/src/generators/tree';
41
- import { execCommand } from 'nx/src/command-line/release/utils/exec-command.js';
42
- import { interpolate } from 'nx/src/tasks-runner/utils';
44
+ import { createFileMapUsingProjectGraph } from 'nx/src/project-graph/file-map-utils';
43
45
  import DefaultChangelogRenderer from 'nx/release/changelog-renderer';
44
46
  import { DEFAULT_CONVENTIONAL_COMMITS_CONFIG } from 'nx/src/command-line/release/config/conventional-commits';
45
- import { major } from 'semver';
46
47
 
47
48
  function parseCargoToml(cargoString) {
48
49
  if (!cargoString) {
@@ -1373,6 +1374,15 @@ function findFileName(filePath) {
1373
1374
  function findFilePath(filePath) {
1374
1375
  return filePath.replace(findFileName(filePath), "");
1375
1376
  }
1377
+ function createFileToProjectMap(projectFileMap) {
1378
+ const fileToProjectMap = {};
1379
+ for (const [projectName, projectFiles] of Object.entries(projectFileMap)) {
1380
+ for (const file of projectFiles) {
1381
+ fileToProjectMap[file.file] = projectName;
1382
+ }
1383
+ }
1384
+ return fileToProjectMap;
1385
+ }
1376
1386
  var start = "<!-- START doctoc -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->";
1377
1387
  var end = "<!-- END doctoc -->";
1378
1388
  var skipTag = "<!-- DOCTOC SKIP -->";
@@ -2381,7 +2391,7 @@ function generateChangelogTitle(version, project, workspaceConfig) {
2381
2391
  if (!workspaceConfig?.name || !project) {
2382
2392
  return version;
2383
2393
  }
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()})`;
2394
+ 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 < 10 ? `0${(/* @__PURE__ */ new Date()).getMonth() + 1}` : (/* @__PURE__ */ new Date()).getMonth() + 1}/${(/* @__PURE__ */ new Date()).getDate() < 10 ? `0${(/* @__PURE__ */ new Date()).getDate()}` : (/* @__PURE__ */ new Date()).getDate()}/${(/* @__PURE__ */ new Date()).getFullYear()})`;
2385
2395
  }
2386
2396
  function parseChangelogMarkdown(contents) {
2387
2397
  const CHANGELOG_RELEASE_HEAD_RE = new RegExp(
@@ -2410,11 +2420,321 @@ function parseChangelogMarkdown(contents) {
2410
2420
  releases
2411
2421
  };
2412
2422
  }
2423
+ function filterHiddenChanges(changes, conventionalCommitsConfig) {
2424
+ return changes.filter((change) => {
2425
+ const type = change.type;
2426
+ const typeConfig = conventionalCommitsConfig.types[type];
2427
+ if (!typeConfig) {
2428
+ return false;
2429
+ }
2430
+ return !typeConfig.changelog.hidden;
2431
+ });
2432
+ }
2433
+ async function generateChangelogForProjects({
2434
+ tree,
2435
+ args,
2436
+ changes,
2437
+ projectGraph,
2438
+ projectsVersionData,
2439
+ releaseGroup,
2440
+ projects,
2441
+ releaseConfig,
2442
+ projectToAdditionalDependencyBumps,
2443
+ workspaceConfig,
2444
+ ChangelogRendererClass
2445
+ }) {
2446
+ const config5 = releaseGroup.changelog;
2447
+ if (config5 === false) {
2448
+ return;
2449
+ }
2450
+ const dryRun = !!args.dryRun;
2451
+ const repoData = getGitHubRepoData(args.gitRemote, "github");
2452
+ if (!repoData) {
2453
+ throw new Error(
2454
+ `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.`
2455
+ );
2456
+ }
2457
+ const remoteReleaseClient = new StormGithubRemoteReleaseClient(
2458
+ repoData,
2459
+ {
2460
+ provider: "github",
2461
+ hostname: repoData.hostname,
2462
+ apiBaseUrl: repoData.apiBaseUrl
2463
+ },
2464
+ await resolveTokenData(repoData.hostname),
2465
+ workspaceConfig
2466
+ );
2467
+ const projectChangelogs = {};
2468
+ for (const project of projects) {
2469
+ let interpolatedTreePath = config5.file || "";
2470
+ if (interpolatedTreePath) {
2471
+ interpolatedTreePath = interpolate(interpolatedTreePath, {
2472
+ projectName: project.name,
2473
+ projectRoot: project.data.root,
2474
+ workspaceRoot: ""
2475
+ // within the tree, workspaceRoot is the root
2476
+ });
2477
+ }
2478
+ if (!projectsVersionData[project.name] || projectsVersionData[project.name]?.newVersion === null && !projectsVersionData[project.name]?.dockerVersion) {
2479
+ continue;
2480
+ }
2481
+ const preferDockerVersion = shouldPreferDockerVersionForReleaseGroup(releaseGroup);
2482
+ const releaseVersion = new ReleaseVersion({
2483
+ version: (preferDockerVersion === true || preferDockerVersion === "both") && projectsVersionData[project.name]?.dockerVersion ? projectsVersionData[project.name]?.dockerVersion : projectsVersionData[project.name]?.newVersion,
2484
+ releaseTagPattern: releaseGroup.releaseTag.pattern,
2485
+ projectName: project.name
2486
+ });
2487
+ if (interpolatedTreePath) {
2488
+ const prefix = dryRun ? "Previewing" : "Generating";
2489
+ output.log({
2490
+ title: `${prefix} an entry in ${interpolatedTreePath} for ${chalk.white(
2491
+ releaseVersion.gitTag
2492
+ )}`
2493
+ });
2494
+ }
2495
+ const changelogRenderer = new ChangelogRendererClass({
2496
+ changes,
2497
+ changelogEntryVersion: releaseVersion.rawVersion,
2498
+ project: project.name,
2499
+ entryWhenNoChanges: typeof config5.entryWhenNoChanges === "string" ? interpolate(config5.entryWhenNoChanges, {
2500
+ projectName: project.name,
2501
+ projectRoot: project.data.root,
2502
+ workspaceRoot: ""
2503
+ // within the tree, workspaceRoot is the root
2504
+ }) : false,
2505
+ changelogRenderOptions: config5.renderOptions,
2506
+ isVersionPlans: !!releaseGroup.versionPlans,
2507
+ conventionalCommitsConfig: releaseConfig.conventionalCommits,
2508
+ dependencyBumps: projectToAdditionalDependencyBumps.get(project.name),
2509
+ remoteReleaseClient,
2510
+ workspaceConfig
2511
+ });
2512
+ const contents = await changelogRenderer.render();
2513
+ const postGitTask = args.createRelease !== false && config5.createRelease ? remoteReleaseClient.createPostGitTask(
2514
+ releaseVersion,
2515
+ contents,
2516
+ dryRun
2517
+ ) : null;
2518
+ projectChangelogs[project.name] = {
2519
+ releaseVersion,
2520
+ contents,
2521
+ postGitTask
2522
+ };
2523
+ }
2524
+ for (const [projectName, projectChangelog] of Object.entries(
2525
+ projectChangelogs
2526
+ )) {
2527
+ if (!projectGraph.nodes[projectName]?.data.root) {
2528
+ writeWarning(
2529
+ `A changelog was generated for ${projectName}, but it could not be found in the project graph. Skipping writing changelog file.`,
2530
+ workspaceConfig
2531
+ );
2532
+ } else if (projectChangelog.contents) {
2533
+ const filePath = joinPaths(
2534
+ projectGraph.nodes[projectName].data.root,
2535
+ "CHANGELOG.md"
2536
+ );
2537
+ let currentContent;
2538
+ if (existsSync$1(filePath)) {
2539
+ currentContent = await readFile$1(filePath, "utf8");
2540
+ }
2541
+ writeDebug(
2542
+ `\u270D\uFE0F Writing changelog for project ${projectName} to ${filePath}`,
2543
+ workspaceConfig
2544
+ );
2545
+ const content = await generateChangelogContent(
2546
+ projectChangelog.releaseVersion,
2547
+ filePath,
2548
+ projectChangelog.contents,
2549
+ currentContent,
2550
+ projectName,
2551
+ workspaceConfig
2552
+ );
2553
+ tree.write(filePath, content);
2554
+ printAndFlushChanges(
2555
+ tree,
2556
+ !!args.dryRun,
2557
+ 3,
2558
+ false,
2559
+ noDiffInChangelogMessage,
2560
+ // Only print the change for the current changelog file at this point
2561
+ (f) => f.path === filePath
2562
+ );
2563
+ }
2564
+ }
2565
+ return projectChangelogs;
2566
+ }
2567
+ async function getCommits(fromSHA, toSHA) {
2568
+ const rawCommits = await getGitDiff(fromSHA, toSHA);
2569
+ return parseCommits(rawCommits);
2570
+ }
2571
+ async function filterProjectCommits({
2572
+ fromSHA,
2573
+ toSHA,
2574
+ projectPath
2575
+ }) {
2576
+ const allCommits = await getCommits(fromSHA, toSHA);
2577
+ return allCommits.filter(
2578
+ (c) => c.affectedFiles.find((f) => f.startsWith(projectPath))
2579
+ );
2580
+ }
2581
+ function commitChangesNonProjectFiles(commit, nonProjectFiles) {
2582
+ return nonProjectFiles.some(
2583
+ (fileData) => commit.affectedFiles.includes(fileData.file)
2584
+ );
2585
+ }
2586
+ function getProjectsAffectedByCommit(commit, fileToProjectMap) {
2587
+ const affectedProjects = /* @__PURE__ */ new Set();
2588
+ for (const file of commit.affectedFiles) {
2589
+ affectedProjects.add(fileToProjectMap[file]);
2590
+ }
2591
+ return Array.from(affectedProjects);
2592
+ }
2593
+ function extractPreid(version) {
2594
+ if (!isPrerelease(version)) {
2595
+ return void 0;
2596
+ }
2597
+ const preid = prerelease(version)?.[0];
2598
+ if (typeof preid === "string") {
2599
+ if (preid.trim() === "") {
2600
+ return void 0;
2601
+ }
2602
+ return preid;
2603
+ }
2604
+ if (typeof preid === "number") {
2605
+ return preid.toString();
2606
+ }
2607
+ return void 0;
2608
+ }
2609
+ async function gitTag({
2610
+ tag,
2611
+ message,
2612
+ additionalArgs,
2613
+ dryRun,
2614
+ verbose,
2615
+ logFn
2616
+ }) {
2617
+ logFn = logFn || console.log;
2618
+ const commandArgs = [
2619
+ "tag",
2620
+ // Create an annotated tag (recommended for releases here: https://git-scm.com/docs/git-tag)
2621
+ "--annotate",
2622
+ "--sign",
2623
+ tag,
2624
+ "--message",
2625
+ message || tag
2626
+ ];
2627
+ if (additionalArgs) {
2628
+ if (Array.isArray(additionalArgs)) {
2629
+ commandArgs.push(...additionalArgs);
2630
+ } else {
2631
+ commandArgs.push(...additionalArgs.split(" "));
2632
+ }
2633
+ }
2634
+ if (verbose) {
2635
+ logFn(
2636
+ dryRun ? `Would tag the current commit in git with the following command, but --dry-run was set:` : `Tagging the current commit in git with the following command:`
2637
+ );
2638
+ logFn(`git ${commandArgs.join(" ")}`);
2639
+ }
2640
+ if (dryRun) {
2641
+ return "";
2642
+ }
2643
+ try {
2644
+ return await execCommand("git", commandArgs);
2645
+ } catch (err) {
2646
+ throw new Error(`Unexpected error when creating tag ${tag}:
2647
+
2648
+ ${err}`);
2649
+ }
2650
+ }
2651
+ async function gitCommit({
2652
+ messages,
2653
+ additionalArgs,
2654
+ dryRun,
2655
+ verbose,
2656
+ logFn
2657
+ }) {
2658
+ logFn = logFn || console.log;
2659
+ const commandArgs = ["commit", "-S"];
2660
+ for (const message of messages) {
2661
+ commandArgs.push("--message", message);
2662
+ }
2663
+ if (additionalArgs) {
2664
+ if (Array.isArray(additionalArgs)) {
2665
+ commandArgs.push(...additionalArgs);
2666
+ } else {
2667
+ commandArgs.push(...additionalArgs.split(" "));
2668
+ }
2669
+ }
2670
+ if (verbose) {
2671
+ logFn(
2672
+ dryRun ? `Would commit all previously staged files in git with the following command, but --dry-run was set:` : `Committing files in git with the following command:`
2673
+ );
2674
+ logFn(`git ${commandArgs.join(" ")}`);
2675
+ }
2676
+ if (dryRun) {
2677
+ return;
2678
+ }
2679
+ let hasStagedFiles = false;
2680
+ try {
2681
+ await execCommand("git", ["diff-index", "--quiet", "HEAD", "--cached"]);
2682
+ } catch {
2683
+ hasStagedFiles = true;
2684
+ }
2685
+ if (!hasStagedFiles) {
2686
+ logFn("\nNo staged files found. Skipping commit.");
2687
+ return;
2688
+ }
2689
+ return execCommand("git", commandArgs);
2690
+ }
2691
+ async function commitChanges({
2692
+ changedFiles,
2693
+ deletedFiles,
2694
+ isDryRun,
2695
+ isVerbose: isVerbose2,
2696
+ gitCommitMessages,
2697
+ gitCommitArgs,
2698
+ logFn
2699
+ }) {
2700
+ logFn = logFn || console.log;
2701
+ if (!changedFiles?.length && !deletedFiles?.length) {
2702
+ throw new Error("Error: No changed files to commit");
2703
+ }
2704
+ logFn(`Committing changes with git`);
2705
+ await gitAdd({
2706
+ changedFiles,
2707
+ deletedFiles,
2708
+ dryRun: isDryRun,
2709
+ verbose: isVerbose2
2710
+ });
2711
+ if (isVerbose2) {
2712
+ console.log("");
2713
+ }
2714
+ await gitCommit({
2715
+ messages: gitCommitMessages || [],
2716
+ additionalArgs: gitCommitArgs,
2717
+ dryRun: isDryRun,
2718
+ verbose: isVerbose2
2719
+ });
2720
+ }
2721
+
2722
+ // src/utilities/omit.ts
2723
+ function omit(obj, keys) {
2724
+ const result = { ...obj };
2725
+ for (let i = 0; i < keys.length; i++) {
2726
+ const key = keys[i];
2727
+ if (key && key in result) {
2728
+ delete result[key];
2729
+ }
2730
+ }
2731
+ return result;
2732
+ }
2413
2733
 
2414
2734
  // src/release/github.ts
2415
2735
  var StormGithubRemoteReleaseClient = class extends GithubRemoteReleaseClient {
2416
- #remoteRepoData;
2417
- #workspaceConfig;
2736
+ repoData;
2737
+ workspaceConfig;
2418
2738
  /**
2419
2739
  * Creates an instance of {@link StormGithubRemoteReleaseClient}.
2420
2740
  *
@@ -2423,63 +2743,71 @@ var StormGithubRemoteReleaseClient = class extends GithubRemoteReleaseClient {
2423
2743
  * @param tokenData - Token data for authentication
2424
2744
  * @param workspaceConfig - The Storm workspace configuration object, which is loaded from the storm-workspace.json file.
2425
2745
  */
2426
- constructor(remoteRepoData, createReleaseConfig, tokenData, workspaceConfig) {
2427
- super(remoteRepoData, createReleaseConfig, tokenData);
2428
- this.#remoteRepoData = remoteRepoData;
2429
- this.#workspaceConfig = workspaceConfig;
2746
+ constructor(repoData, createReleaseConfig, tokenData, workspaceConfig) {
2747
+ super(repoData, createReleaseConfig, tokenData);
2748
+ this.repoData = repoData;
2749
+ this.workspaceConfig = workspaceConfig;
2430
2750
  }
2431
2751
  createPostGitTask(releaseVersion, changelogContents, dryRun) {
2432
2752
  return async (latestCommit) => {
2433
- if (!this.#workspaceConfig) {
2434
- this.#workspaceConfig = await getWorkspaceConfig();
2435
- }
2436
2753
  output.logSingleLine(`Creating GitHub Release`);
2437
- const name = releaseVersion.gitTag.includes("@") ? releaseVersion.gitTag.replace(new RegExp(`^@${this.#workspaceConfig.name}/`), "").replace(/@.*$/, "") : releaseVersion.gitTag;
2438
2754
  await this.createOrUpdateRelease(
2439
2755
  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 || ""}
2756
+ changelogContents,
2757
+ latestCommit,
2758
+ { dryRun }
2759
+ );
2760
+ };
2761
+ }
2762
+ async createOrUpdateRelease(releaseVersion, changelogContents, latestCommit, { dryRun }) {
2763
+ if (!this.workspaceConfig) {
2764
+ this.workspaceConfig = await getWorkspaceConfig();
2765
+ }
2766
+ const name = releaseVersion.gitTag.includes("@") ? releaseVersion.gitTag.replace(new RegExp(`^@${this.workspaceConfig.name}/`), "").replace(/@.*$/, "") : releaseVersion.gitTag;
2767
+ return super.createOrUpdateRelease(
2768
+ releaseVersion,
2769
+ `![${(typeof this.workspaceConfig.release.banner === "string" ? this.workspaceConfig.organization ? titleCase(
2770
+ typeof this.workspaceConfig.organization === "string" ? this.workspaceConfig.organization : this.workspaceConfig.organization.name
2771
+ ) : 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})
2772
+ ${this.workspaceConfig.release.header || ""}
2444
2773
 
2445
2774
  # ${name ? `${titleCase(name)} ` : ""}v${releaseVersion.rawVersion}
2446
2775
 
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}
2776
+ We at [${this.workspaceConfig.organization ? titleCase(
2777
+ typeof this.workspaceConfig.organization === "string" ? this.workspaceConfig.organization : this.workspaceConfig.organization.name
2778
+ ) : ""}](${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
2779
 
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}).
2780
+ 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
2781
 
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!
2782
+ 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
2783
 
2455
2784
  ## Release Notes
2456
2785
 
2457
2786
  ${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
- )}
2787
+ `## ${generateChangelogTitle(
2788
+ releaseVersion.rawVersion,
2789
+ name,
2790
+ this.workspaceConfig
2791
+ )}`,
2792
+ ""
2793
+ ).replaceAll(
2794
+ `# ${generateChangelogTitle(releaseVersion.rawVersion, name, this.workspaceConfig)}`,
2795
+ ""
2796
+ )}
2468
2797
 
2469
2798
  ---
2470
2799
 
2471
- ${this.#workspaceConfig.release.footer}
2800
+ ${this.workspaceConfig.release.footer}
2472
2801
  `,
2473
- latestCommit,
2474
- { dryRun }
2475
- );
2476
- };
2802
+ latestCommit,
2803
+ { dryRun }
2804
+ );
2477
2805
  }
2478
2806
  /**
2479
2807
  * Get remote repository data, attempting to resolve it if not already set.
2480
2808
  */
2481
2809
  getRemoteRepoData() {
2482
- if (!this.#remoteRepoData) {
2810
+ if (!this.repoData) {
2483
2811
  let githubRepoData = super.getRemoteRepoData();
2484
2812
  if (!githubRepoData) {
2485
2813
  githubRepoData = getGitHubRepoData();
@@ -2493,9 +2821,9 @@ ${this.#workspaceConfig.release.footer}
2493
2821
  process.exit(1);
2494
2822
  }
2495
2823
  }
2496
- this.#remoteRepoData = githubRepoData;
2824
+ this.repoData = githubRepoData;
2497
2825
  }
2498
- return this.#remoteRepoData;
2826
+ return this.repoData;
2499
2827
  }
2500
2828
  };
2501
2829
  function getGitHubRepoData(remoteName = "origin", createReleaseConfig = "github") {
@@ -2580,24 +2908,6 @@ async function makeGithubRequest(config5, url, opts = {}) {
2580
2908
  }
2581
2909
  });
2582
2910
  }
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
2911
  async function isUserAnOrganizationMember(userId, config5, remoteName = "origin") {
2602
2912
  try {
2603
2913
  const repoData = getGitHubRepoData(remoteName, "github");
@@ -2630,164 +2940,6 @@ async function isUserAnOrganizationMember(userId, config5, remoteName = "origin"
2630
2940
  return false;
2631
2941
  }
2632
2942
  }
2633
- function createGitTagValues(releaseGroups, releaseGroupToFilteredProjects, versionData) {
2634
- const tags = [];
2635
- for (const releaseGroup of releaseGroups) {
2636
- const releaseGroupProjectNames = Array.from(
2637
- releaseGroupToFilteredProjects.get(releaseGroup) ?? []
2638
- );
2639
- if (releaseGroup.projectsRelationship === "independent") {
2640
- for (const project of releaseGroupProjectNames) {
2641
- const projectVersionData = versionData[project];
2642
- if (projectVersionData?.newVersion) {
2643
- tags.push(
2644
- interpolate(releaseGroup.releaseTagPattern, {
2645
- version: projectVersionData.newVersion,
2646
- projectName: project
2647
- })
2648
- );
2649
- }
2650
- }
2651
- continue;
2652
- }
2653
- if (releaseGroupProjectNames.length > 0 && releaseGroupProjectNames[0]) {
2654
- const projectVersionData = versionData[releaseGroupProjectNames[0]];
2655
- if (projectVersionData?.newVersion) {
2656
- tags.push(
2657
- interpolate(releaseGroup.releaseTagPattern, {
2658
- version: projectVersionData.newVersion,
2659
- releaseGroupName: releaseGroup.name
2660
- })
2661
- );
2662
- }
2663
- }
2664
- }
2665
- return tags;
2666
- }
2667
- async function gitTag({
2668
- tag,
2669
- message,
2670
- additionalArgs,
2671
- dryRun,
2672
- verbose,
2673
- logFn
2674
- }) {
2675
- logFn = logFn || console.log;
2676
- const commandArgs = [
2677
- "tag",
2678
- // Create an annotated tag (recommended for releases here: https://git-scm.com/docs/git-tag)
2679
- "--annotate",
2680
- "--sign",
2681
- tag,
2682
- "--message",
2683
- message || tag
2684
- ];
2685
- if (additionalArgs) {
2686
- if (Array.isArray(additionalArgs)) {
2687
- commandArgs.push(...additionalArgs);
2688
- } else {
2689
- commandArgs.push(...additionalArgs.split(" "));
2690
- }
2691
- }
2692
- if (verbose) {
2693
- logFn(
2694
- dryRun ? `Would tag the current commit in git with the following command, but --dry-run was set:` : `Tagging the current commit in git with the following command:`
2695
- );
2696
- logFn(`git ${commandArgs.join(" ")}`);
2697
- }
2698
- if (dryRun) {
2699
- return "";
2700
- }
2701
- try {
2702
- return await execCommand("git", commandArgs);
2703
- } catch (err) {
2704
- throw new Error(`Unexpected error when creating tag ${tag}:
2705
-
2706
- ${err}`);
2707
- }
2708
- }
2709
- async function gitCommit({
2710
- messages,
2711
- additionalArgs,
2712
- dryRun,
2713
- verbose,
2714
- logFn
2715
- }) {
2716
- logFn = logFn || console.log;
2717
- const commandArgs = ["commit", "-S"];
2718
- for (const message of messages) {
2719
- commandArgs.push("--message", message);
2720
- }
2721
- if (additionalArgs) {
2722
- if (Array.isArray(additionalArgs)) {
2723
- commandArgs.push(...additionalArgs);
2724
- } else {
2725
- commandArgs.push(...additionalArgs.split(" "));
2726
- }
2727
- }
2728
- if (verbose) {
2729
- logFn(
2730
- dryRun ? `Would commit all previously staged files in git with the following command, but --dry-run was set:` : `Committing files in git with the following command:`
2731
- );
2732
- logFn(`git ${commandArgs.join(" ")}`);
2733
- }
2734
- if (dryRun) {
2735
- return;
2736
- }
2737
- let hasStagedFiles = false;
2738
- try {
2739
- await execCommand("git", ["diff-index", "--quiet", "HEAD", "--cached"]);
2740
- } catch {
2741
- hasStagedFiles = true;
2742
- }
2743
- if (!hasStagedFiles) {
2744
- logFn("\nNo staged files found. Skipping commit.");
2745
- return;
2746
- }
2747
- return execCommand("git", commandArgs);
2748
- }
2749
- async function commitChanges({
2750
- changedFiles,
2751
- deletedFiles,
2752
- isDryRun,
2753
- isVerbose: isVerbose2,
2754
- gitCommitMessages,
2755
- gitCommitArgs,
2756
- logFn
2757
- }) {
2758
- logFn = logFn || console.log;
2759
- if (!changedFiles?.length && !deletedFiles?.length) {
2760
- throw new Error("Error: No changed files to commit");
2761
- }
2762
- logFn(`Committing changes with git`);
2763
- await gitAdd({
2764
- changedFiles,
2765
- deletedFiles,
2766
- dryRun: isDryRun,
2767
- verbose: isVerbose2
2768
- });
2769
- if (isVerbose2) {
2770
- console.log("");
2771
- }
2772
- await gitCommit({
2773
- messages: gitCommitMessages || [],
2774
- additionalArgs: gitCommitArgs,
2775
- dryRun: isDryRun,
2776
- verbose: isVerbose2
2777
- });
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
- }
2791
2943
  var StormChangelogRenderer = class extends DefaultChangelogRenderer {
2792
2944
  /**
2793
2945
  * The Storm workspace configuration object, which is loaded from the storm-workspace.json file.
@@ -2805,15 +2957,13 @@ var StormChangelogRenderer = class extends DefaultChangelogRenderer {
2805
2957
  ...config5
2806
2958
  };
2807
2959
  super(resolvedConfig);
2808
- this.workspaceConfig = config5.changelogRenderOptions.workspaceConfig;
2960
+ this.workspaceConfig = config5.workspaceConfig;
2961
+ this.remoteReleaseClient = resolvedConfig.remoteReleaseClient;
2809
2962
  }
2810
2963
  async render() {
2811
2964
  if (!this.workspaceConfig) {
2812
2965
  this.workspaceConfig = await getWorkspaceConfig();
2813
2966
  }
2814
- this.remoteReleaseClient = await createGithubRemoteReleaseClient(
2815
- this.workspaceConfig
2816
- );
2817
2967
  return super.render();
2818
2968
  }
2819
2969
  preprocessChanges() {
@@ -3062,8 +3212,6 @@ var DEFAULT_RELEASE_CONFIG = {
3062
3212
  },
3063
3213
  releaseTag: { pattern: DEFAULT_RELEASE_TAG_PATTERN }
3064
3214
  };
3065
-
3066
- // src/release/release-client.ts
3067
3215
  function getReleaseGroupConfig(releaseConfig, workspaceConfig) {
3068
3216
  return !releaseConfig?.groups || Object.keys(releaseConfig.groups).length === 0 ? {} : Object.fromEntries(
3069
3217
  Object.entries(releaseConfig.groups).map(([name, group]) => {
@@ -3101,6 +3249,8 @@ function getReleaseGroupConfig(releaseConfig, workspaceConfig) {
3101
3249
  })
3102
3250
  );
3103
3251
  }
3252
+
3253
+ // src/release/release-client.ts
3104
3254
  var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3105
3255
  static async create(releaseConfig = {}, ignoreNxJsonConfig = false, workspaceConfig) {
3106
3256
  if (!workspaceConfig) {
@@ -3127,7 +3277,6 @@ var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3127
3277
  workspaceConfig
3128
3278
  );
3129
3279
  }
3130
- #releaseChangelog;
3131
3280
  /**
3132
3281
  * The release configuration used by this release client.
3133
3282
  */
@@ -3173,7 +3322,10 @@ var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3173
3322
  groups: getReleaseGroupConfig(releaseConfig, workspaceConfig)
3174
3323
  },
3175
3324
  {
3176
- groups: getReleaseGroupConfig(nxJson.release ?? {}, workspaceConfig)
3325
+ groups: getReleaseGroupConfig(
3326
+ nxJson.release ?? {},
3327
+ workspaceConfig
3328
+ )
3177
3329
  },
3178
3330
  omit(releaseConfig, ["groups"]),
3179
3331
  nxJson.release ? omit(nxJson.release, ["groups"]) : {},
@@ -3189,89 +3341,265 @@ var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3189
3341
  this.config = config5;
3190
3342
  this.workspaceConfig = workspaceConfig;
3191
3343
  this.tree = new FsTree(workspaceConfig.workspaceRoot, false);
3192
- this.#releaseChangelog = createAPI(config5, true);
3193
3344
  this.projectConfigurations = readProjectsConfigurationFromProjectGraph$2(projectGraph);
3194
3345
  }
3195
3346
  releaseChangelog = async (options) => {
3196
- const result = await this.#releaseChangelog({
3197
- ...options,
3198
- gitCommit: false,
3199
- gitTag: false
3200
- });
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"
3347
+ const to = options.to || "HEAD";
3348
+ const toSHA = await getCommitHash(to);
3349
+ const postGitTasks = [];
3350
+ let projectChangelogs = {};
3351
+ const projectsPreid = Object.fromEntries(
3352
+ Object.entries(options.versionData).map(([projectName, v]) => [
3353
+ projectName,
3354
+ v.newVersion ? extractPreid(v.newVersion) : void 0
3355
+ ])
3356
+ );
3357
+ const projectToAdditionalDependencyBumps = /* @__PURE__ */ new Map();
3358
+ for (const releaseGroup of options.releaseGraph.releaseGroups) {
3359
+ if (releaseGroup.projectsRelationship !== "independent") {
3360
+ continue;
3361
+ }
3362
+ for (const project of releaseGroup.projects) {
3363
+ if (!options.versionData[project] || options.versionData[project].newVersion === null) {
3364
+ continue;
3365
+ }
3366
+ const dependentProjects = (options.versionData[project].dependentProjects || []).map((dep) => {
3367
+ return {
3368
+ dependencyName: dep.source,
3369
+ newVersion: options.versionData[dep.source]?.newVersion ?? null
3370
+ };
3371
+ }).filter((b) => b.newVersion !== null);
3372
+ for (const dependent of dependentProjects) {
3373
+ const additionalDependencyBumpsForProject = projectToAdditionalDependencyBumps.has(dependent.dependencyName) ? projectToAdditionalDependencyBumps.get(dependent.dependencyName) : [];
3374
+ additionalDependencyBumpsForProject.push({
3375
+ dependencyName: project,
3376
+ newVersion: options.versionData[project].newVersion
3377
+ });
3378
+ projectToAdditionalDependencyBumps.set(
3379
+ dependent.dependencyName,
3380
+ additionalDependencyBumpsForProject
3381
+ );
3382
+ }
3383
+ }
3384
+ }
3385
+ const allProjectChangelogs = {};
3386
+ for (const releaseGroup of options.releaseGraph.releaseGroups) {
3387
+ const config5 = releaseGroup.changelog;
3388
+ if (config5 === false) {
3389
+ continue;
3390
+ }
3391
+ if (!options.releaseGraph.releaseGroupToFilteredProjects.has(releaseGroup)) {
3392
+ throw new Error(
3393
+ `No filtered projects found for release group ${releaseGroup.name}`
3394
+ );
3395
+ }
3396
+ const projects = options.projects?.length ? (
3397
+ // 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
3398
+ Array.from(
3399
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
3400
+ options.releaseGraph.releaseGroupToFilteredProjects.get(
3401
+ releaseGroup
3402
+ )
3403
+ ).flatMap((project) => {
3404
+ return [
3405
+ project,
3406
+ ...options.versionData[project]?.dependentProjects.map(
3407
+ (dep) => dep.source
3408
+ ) || []
3409
+ ];
3410
+ })
3411
+ ) : (
3412
+ // Otherwise, we use the full list of projects within the release group
3413
+ releaseGroup.projects
3414
+ );
3415
+ const projectNodes = projects.map((name) => this.projectGraph.nodes[name]);
3416
+ if (releaseGroup.projectsRelationship === "independent") {
3417
+ for (const project of projectNodes) {
3418
+ let changes = null;
3419
+ let fromRef = options.from || (await getLatestGitTagForPattern(
3420
+ releaseGroup.releaseTag.pattern,
3421
+ {
3422
+ projectName: project.name,
3423
+ releaseGroupName: releaseGroup.name
3424
+ },
3425
+ {
3426
+ checkAllBranchesWhen: releaseGroup.releaseTag.checkAllBranchesWhen,
3427
+ preid: projectsPreid[project.name],
3428
+ requireSemver: releaseGroup.releaseTag.requireSemver,
3429
+ strictPreid: releaseGroup.releaseTag.strictPreid
3430
+ }
3431
+ ))?.tag;
3432
+ let commits = void 0;
3433
+ if (!fromRef) {
3434
+ const firstCommit = await getFirstGitCommit();
3435
+ commits = await filterProjectCommits({
3436
+ fromSHA: firstCommit,
3437
+ toSHA,
3438
+ projectPath: project.data.root
3439
+ });
3440
+ fromRef = commits[0]?.shortHash;
3441
+ if (options.verbose) {
3442
+ console.log(
3443
+ `Determined --from ref for ${project.name} from the first commit in which it exists: ${fromRef}`
3214
3444
  );
3215
- let currentContent;
3216
- if (existsSync$1(filePath)) {
3217
- currentContent = await readFile$1(filePath, "utf8");
3445
+ }
3446
+ }
3447
+ if (!fromRef && !commits) {
3448
+ throw new Error(
3449
+ `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.releaseTag.pattern" property in nx.json to match the structure of your repository's git tags.`
3450
+ );
3451
+ }
3452
+ if (!commits) {
3453
+ commits = await filterProjectCommits({
3454
+ fromSHA: fromRef,
3455
+ toSHA,
3456
+ projectPath: project.data.root
3457
+ });
3458
+ }
3459
+ const { fileMap } = await createFileMapUsingProjectGraph(
3460
+ this.projectGraph
3461
+ );
3462
+ const fileToProjectMap = createFileToProjectMap(
3463
+ fileMap.projectFileMap
3464
+ );
3465
+ changes = filterHiddenChanges(
3466
+ commits.map((c) => ({
3467
+ type: c.type,
3468
+ scope: c.scope,
3469
+ description: c.description,
3470
+ body: c.body,
3471
+ isBreaking: c.isBreaking,
3472
+ githubReferences: c.references,
3473
+ authors: c.authors,
3474
+ shortHash: c.shortHash,
3475
+ revertedHashes: c.revertedHashes,
3476
+ affectedProjects: commitChangesNonProjectFiles(
3477
+ c,
3478
+ fileMap.nonProjectFiles
3479
+ ) ? "*" : getProjectsAffectedByCommit(c, fileToProjectMap)
3480
+ })),
3481
+ this.config.conventionalCommits
3482
+ );
3483
+ writeDebug(
3484
+ `Running changelog generation for the ${releaseGroup.name} release group`,
3485
+ this.workspaceConfig
3486
+ );
3487
+ projectChangelogs = await generateChangelogForProjects({
3488
+ tree: this.tree,
3489
+ args: options,
3490
+ changes,
3491
+ projectGraph: this.projectGraph,
3492
+ projectsVersionData: options.versionData,
3493
+ releaseGroup,
3494
+ projects: [project],
3495
+ releaseConfig: this.config,
3496
+ projectToAdditionalDependencyBumps,
3497
+ workspaceConfig: this.workspaceConfig,
3498
+ ChangelogRendererClass: StormChangelogRenderer
3499
+ });
3500
+ if (projectChangelogs) {
3501
+ for (const [projectName, projectChangelog] of Object.entries(
3502
+ projectChangelogs
3503
+ )) {
3504
+ if (projectChangelog.postGitTask) {
3505
+ postGitTasks.push(projectChangelog.postGitTask);
3218
3506
  }
3219
- writeDebug(
3220
- `\u270D\uFE0F Writing changelog for project ${project} to ${filePath}`,
3221
- this.workspaceConfig
3222
- );
3223
- const content = await generateChangelogContent(
3224
- changelog.releaseVersion,
3225
- filePath,
3226
- changelog.contents,
3227
- currentContent,
3228
- project,
3229
- this.workspaceConfig
3230
- );
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
3240
- );
3507
+ allProjectChangelogs[projectName] = projectChangelog;
3241
3508
  }
3242
3509
  }
3243
- )
3244
- );
3245
- this.applyChangesAndExit(options, result);
3246
- }
3247
- return result;
3248
- };
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;
3510
+ }
3511
+ } else {
3512
+ let changes = [];
3513
+ let fromRef = options.from || (await getLatestGitTagForPattern(
3514
+ releaseGroup.releaseTag.pattern,
3515
+ {},
3516
+ {
3517
+ checkAllBranchesWhen: releaseGroup.releaseTag.checkAllBranchesWhen,
3518
+ preid: Object.keys(projectsPreid)[0] ? projectsPreid?.[Object.keys(projectsPreid)[0]] : void 0,
3519
+ requireSemver: releaseGroup.releaseTag.requireSemver,
3520
+ strictPreid: releaseGroup.releaseTag.strictPreid
3521
+ }
3522
+ ))?.tag;
3523
+ if (!fromRef) {
3524
+ fromRef = await getFirstGitCommit();
3525
+ if (options.verbose) {
3526
+ console.log(
3527
+ `Determined release group --from ref from the first commit in the workspace: ${fromRef}`
3528
+ );
3529
+ }
3530
+ }
3531
+ const fromSHA = await getCommitHash(fromRef);
3532
+ const { fileMap } = await createFileMapUsingProjectGraph(
3533
+ this.projectGraph
3534
+ );
3535
+ const fileToProjectMap = createFileToProjectMap(fileMap.projectFileMap);
3536
+ changes = filterHiddenChanges(
3537
+ (await getCommits(fromSHA, toSHA)).map((c) => ({
3538
+ type: c.type,
3539
+ scope: c.scope,
3540
+ description: c.description,
3541
+ body: c.body,
3542
+ isBreaking: c.isBreaking,
3543
+ githubReferences: c.references,
3544
+ authors: c.authors,
3545
+ shortHash: c.shortHash,
3546
+ revertedHashes: c.revertedHashes,
3547
+ affectedProjects: commitChangesNonProjectFiles(
3548
+ c,
3549
+ fileMap.nonProjectFiles
3550
+ ) ? "*" : getProjectsAffectedByCommit(c, fileToProjectMap)
3551
+ })),
3552
+ this.config.conventionalCommits
3553
+ );
3554
+ writeDebug(
3555
+ `Running changelog generation for the ${releaseGroup.name} release group`,
3556
+ this.workspaceConfig
3557
+ );
3558
+ projectChangelogs = await generateChangelogForProjects({
3559
+ tree: this.tree,
3560
+ args: options,
3561
+ changes,
3562
+ projectGraph: this.projectGraph,
3563
+ projectsVersionData: options.versionData,
3564
+ releaseGroup,
3565
+ projects: projectNodes,
3566
+ releaseConfig: this.config,
3567
+ projectToAdditionalDependencyBumps,
3568
+ workspaceConfig: this.workspaceConfig,
3569
+ ChangelogRendererClass: StormChangelogRenderer
3570
+ });
3571
+ if (projectChangelogs) {
3572
+ for (const [projectName, projectChangelog] of Object.entries(
3573
+ projectChangelogs
3574
+ )) {
3575
+ if (projectChangelog.postGitTask) {
3576
+ postGitTasks.push(projectChangelog.postGitTask);
3577
+ }
3578
+ allProjectChangelogs[projectName] = projectChangelog;
3579
+ }
3580
+ }
3256
3581
  }
3257
3582
  }
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;
3583
+ writeDebug(
3584
+ `Generated changelogs for ${Object.keys(allProjectChangelogs).length} projects:
3585
+ ${Object.keys(allProjectChangelogs).map((p) => ` - ${p}`).join("\n")}
3586
+ `,
3587
+ this.workspaceConfig
3588
+ );
3589
+ await this.applyChangesAndExit(options, postGitTasks);
3590
+ return {
3591
+ workspaceChangelog: void 0,
3592
+ projectChangelogs: allProjectChangelogs
3593
+ };
3265
3594
  };
3266
- applyChangesAndExit = async (options, result) => {
3267
- const postGitTasks = Object.values(result.projectChangelogs || {}).map((project) => project.postGitTask).filter(Boolean);
3595
+ applyChangesAndExit = async (options, postGitTasks) => {
3268
3596
  const to = options.to || "HEAD";
3269
3597
  let latestCommit = await getCommitHash(to);
3270
- const gitTagValues = options.gitTag ?? this.config.changelog?.git?.tag ? createGitTagValues(
3598
+ const gitTagValues = createGitTagValues(
3271
3599
  options.releaseGraph.releaseGroups,
3272
3600
  options.releaseGraph.releaseGroupToFilteredProjects,
3273
3601
  options.versionData
3274
- ) : [];
3602
+ );
3275
3603
  handleDuplicateGitTags(gitTagValues);
3276
3604
  const commitMessageValues = createCommitMessageValues(
3277
3605
  options.releaseGraph.releaseGroups,
@@ -3280,13 +3608,11 @@ var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3280
3608
  options.gitCommitMessage || this.config.changelog?.git?.commitMessage || "release(monorepo): Publish workspace release updates"
3281
3609
  );
3282
3610
  const changes = this.tree.listChanges();
3283
- if (this.checkChangelogFilesEnabled() && !changes.length) {
3284
- output.warn({
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
- ]
3289
- });
3611
+ if (!changes.length) {
3612
+ writeWarning(
3613
+ "No changes were detected for any changelog files, so no changelog entries will be generated.",
3614
+ this.workspaceConfig
3615
+ );
3290
3616
  if (!postGitTasks.length) {
3291
3617
  return;
3292
3618
  }
@@ -3305,7 +3631,10 @@ var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3305
3631
  gitCommitArgs: options.gitCommitArgs || this.config.changelog?.git?.commitArgs
3306
3632
  });
3307
3633
  latestCommit = await getCommitHash("HEAD");
3308
- output.logSingleLine(`Tagging commit with git`);
3634
+ writeDebug(
3635
+ `Creating git tags: ${gitTagValues.join(", ")}`,
3636
+ this.workspaceConfig
3637
+ );
3309
3638
  for (const tag of gitTagValues) {
3310
3639
  await gitTag({
3311
3640
  tag,
@@ -3315,17 +3644,16 @@ var StormReleaseClient = class _StormReleaseClient extends ReleaseClient {
3315
3644
  verbose: options.verbose
3316
3645
  });
3317
3646
  }
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
3327
- });
3328
- }
3647
+ writeDebug(
3648
+ `Pushing to git remote "${options.gitRemote ?? "origin"}"`,
3649
+ this.workspaceConfig
3650
+ );
3651
+ await gitPush({
3652
+ gitRemote: options.gitRemote,
3653
+ dryRun: options.dryRun,
3654
+ verbose: options.verbose,
3655
+ additionalArgs: options.gitPushArgs || this.config.changelog?.git?.pushArgs
3656
+ });
3329
3657
  for (const postGitTask of postGitTasks) {
3330
3658
  await postGitTask(latestCommit);
3331
3659
  }