relizy 1.4.4 → 1.4.6

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/dist/cli.mjs CHANGED
@@ -5,7 +5,7 @@ import process from 'node:process';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { printBanner, logger } from '@maz-ui/node';
7
7
  import { Command } from 'commander';
8
- import { aq as isInCI, ar as getCIName, b as bump, c as changelog, g as publish, e as providerRelease, h as social, p as prComment, r as release } from './shared/relizy.D5bCkAG-.mjs';
8
+ import { aq as isInCI, ar as getCIName, b as bump, c as changelog, g as publish, e as providerRelease, h as social, p as prComment, r as release } from './shared/relizy.CzL6Efad.mjs';
9
9
  import 'node:child_process';
10
10
  import '@maz-ui/utils';
11
11
  import 'c12';
package/dist/index.d.mts CHANGED
@@ -88,19 +88,41 @@ type ResolvedRelizyConfig = ResolvedConfig & {
88
88
  declare function defineConfig(config: RelizyConfig): RelizyConfig;
89
89
 
90
90
  /**
91
- * Generate changelog for a specific package
91
+ * Controls which sections of the rendered changelog are produced.
92
+ * Each flag defaults to `true`. `compareLink` and `contributors` are
93
+ * additionally suppressed when `minify: true` (see `generateChangelog`).
92
94
  */
93
- declare function generateChangelog({ pkg, config, dryRun, newVersion, minify, }: {
95
+ interface ChangelogInclude {
96
+ title?: boolean;
97
+ compareLink?: boolean;
98
+ body?: boolean;
99
+ contributors?: boolean;
100
+ }
101
+ /**
102
+ * Generate the changelog string for a single package.
103
+ *
104
+ * - Fetches commits internally using `changelog: true`, so types that only
105
+ * declare a `title` (e.g. `docs: { title: '📖 Documentation' }`) are
106
+ * included even though they don't trigger a version bump. Callers must
107
+ * provide `pkg.path` — `pkg.commits` is no longer consumed.
108
+ * - `include` toggles which sections appear in the output. `compareLink`
109
+ * and `contributors` are also skipped when `minify` is true.
110
+ * - `transformBody` is invoked between body rendering and final assembly,
111
+ * used by provider releases to plug an AI rewrite step on the body only.
112
+ */
113
+ declare function generateChangelog({ pkg, config, dryRun, newVersion, minify, include, transformBody, }: {
94
114
  pkg: {
95
115
  fromTag?: string;
96
116
  name: string;
117
+ path: string;
97
118
  newVersion?: string;
98
- commits: GitCommit[];
99
119
  };
100
120
  config: ResolvedRelizyConfig;
101
121
  dryRun: boolean;
102
122
  newVersion: string;
103
123
  minify?: boolean;
124
+ include?: ChangelogInclude;
125
+ transformBody?: (body: string) => Promise<string> | string;
104
126
  }): Promise<string>;
105
127
  /**
106
128
  * Write changelog to file
@@ -1876,4 +1898,4 @@ declare function socialSafetyCheck({ config }: {
1876
1898
  declare function social(options?: Partial<SocialOptions>): Promise<SocialResult>;
1877
1899
 
1878
1900
  export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, bump, capReleaseTypeForZeroMajor, changelog, checkGitStatusIfDirty, collectContributorNames, collectPackageBumps, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, detectPullRequest, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractChangelogSummary, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, filterOutPrivatePackages, findGitHubPR, findGitLabMR, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, hasLernaJson, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, readPackageJson, readPackages, release, resolveTags, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
1879
- export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, ReleaseConfig, ReleaseContext, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, ResolvedTwitterCredentials, RootPackage, SlackCredentials, SlackOptions, SlackPackageEntry, SlackSocialConfig, SocialConfig, SocialNetworkResult, SocialOptions, SocialResult, Step, TemplatesConfig, TokensConfig, TwitterCredentials, TwitterOptions, TwitterSocialConfig, VersionMode };
1901
+ export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogInclude, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, ReleaseConfig, ReleaseContext, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, ResolvedTwitterCredentials, RootPackage, SlackCredentials, SlackOptions, SlackPackageEntry, SlackSocialConfig, SocialConfig, SocialNetworkResult, SocialOptions, SocialResult, Step, TemplatesConfig, TokensConfig, TwitterCredentials, TwitterOptions, TwitterSocialConfig, VersionMode };
package/dist/index.d.ts CHANGED
@@ -88,19 +88,41 @@ type ResolvedRelizyConfig = ResolvedConfig & {
88
88
  declare function defineConfig(config: RelizyConfig): RelizyConfig;
89
89
 
90
90
  /**
91
- * Generate changelog for a specific package
91
+ * Controls which sections of the rendered changelog are produced.
92
+ * Each flag defaults to `true`. `compareLink` and `contributors` are
93
+ * additionally suppressed when `minify: true` (see `generateChangelog`).
92
94
  */
93
- declare function generateChangelog({ pkg, config, dryRun, newVersion, minify, }: {
95
+ interface ChangelogInclude {
96
+ title?: boolean;
97
+ compareLink?: boolean;
98
+ body?: boolean;
99
+ contributors?: boolean;
100
+ }
101
+ /**
102
+ * Generate the changelog string for a single package.
103
+ *
104
+ * - Fetches commits internally using `changelog: true`, so types that only
105
+ * declare a `title` (e.g. `docs: { title: '📖 Documentation' }`) are
106
+ * included even though they don't trigger a version bump. Callers must
107
+ * provide `pkg.path` — `pkg.commits` is no longer consumed.
108
+ * - `include` toggles which sections appear in the output. `compareLink`
109
+ * and `contributors` are also skipped when `minify` is true.
110
+ * - `transformBody` is invoked between body rendering and final assembly,
111
+ * used by provider releases to plug an AI rewrite step on the body only.
112
+ */
113
+ declare function generateChangelog({ pkg, config, dryRun, newVersion, minify, include, transformBody, }: {
94
114
  pkg: {
95
115
  fromTag?: string;
96
116
  name: string;
117
+ path: string;
97
118
  newVersion?: string;
98
- commits: GitCommit[];
99
119
  };
100
120
  config: ResolvedRelizyConfig;
101
121
  dryRun: boolean;
102
122
  newVersion: string;
103
123
  minify?: boolean;
124
+ include?: ChangelogInclude;
125
+ transformBody?: (body: string) => Promise<string> | string;
104
126
  }): Promise<string>;
105
127
  /**
106
128
  * Write changelog to file
@@ -1876,4 +1898,4 @@ declare function socialSafetyCheck({ config }: {
1876
1898
  declare function social(options?: Partial<SocialOptions>): Promise<SocialResult>;
1877
1899
 
1878
1900
  export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, bump, capReleaseTypeForZeroMajor, changelog, checkGitStatusIfDirty, collectContributorNames, collectPackageBumps, confirmBump, createCommitAndTags, createGitlabRelease, defineConfig, detectGitProvider, detectPackageManager, detectPullRequest, determinePublishTag, determineReleaseType, determineSemverChange, executeBuildCmd, executeFormatCmd, executeHook, expandPackagesToBumpWithDependents, extractChangelogSummary, extractVersionFromPackageTag, extractVersionFromTag, fetchGitTags, filterOutPrivatePackages, findGitHubPR, findGitLabMR, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, hasLernaJson, isBumpedPackage, isChangedPreid, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, readPackageJson, readPackages, release, resolveTags, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, topologicalSort, updateLernaVersion, writeChangelogToFile, writeVersion };
1879
- export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, ReleaseConfig, ReleaseContext, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, ResolvedTwitterCredentials, RootPackage, SlackCredentials, SlackOptions, SlackPackageEntry, SlackSocialConfig, SocialConfig, SocialNetworkResult, SocialOptions, SocialResult, Step, TemplatesConfig, TokensConfig, TwitterCredentials, TwitterOptions, TwitterSocialConfig, VersionMode };
1901
+ export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogInclude, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, ReleaseConfig, ReleaseContext, ReleaseOptions, RelizyConfig, RepoConfig, ResolvedConfig, ResolvedRelizyConfig, ResolvedTags, ResolvedTwitterCredentials, RootPackage, SlackCredentials, SlackOptions, SlackPackageEntry, SlackSocialConfig, SocialConfig, SocialNetworkResult, SocialOptions, SocialResult, Step, TemplatesConfig, TokensConfig, TwitterCredentials, TwitterOptions, TwitterSocialConfig, VersionMode };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { ak as NEW_PACKAGE_MARKER, $ as PR_COMMENT_MARKER, M as buildChangelogBody, a as buildCommentBody, L as buildCompareLink, O as buildContributors, b as bump, ay as capReleaseTypeForZeroMajor, c as changelog, v as checkGitStatusIfDirty, N as collectContributorNames, X as collectPackageBumps, aM as confirmBump, B as createCommitAndTags, J as createGitlabRelease, k as defineConfig, y as detectGitProvider, R as detectPackageManager, _ as detectPullRequest, S as determinePublishTag, aA as determineReleaseType, az as determineSemverChange, at as executeBuildCmd, as as executeFormatCmd, ap as executeHook, q as expandPackagesToBumpWithDependents, ad as extractChangelogSummary, aE as extractVersionFromPackageTag, aP as extractVersionFromTag, x as fetchGitTags, av as filterOutPrivatePackages, Y as findGitHubPR, Z as findGitLabMR, a9 as formatChangelogForSlack, aa as formatPackagesForSlack, ab as formatSlackMessage, an as formatTweetMessage, i as generateChangelog, P as generateMarkDown, V as getAuthCommand, aN as getBumpedIndependentPackages, aL as getBumpedPackageIndependently, ar as getCIName, aQ as getCanaryVersion, F as getCurrentGitBranch, G as getCurrentGitRef, j as getDefaultConfig, o as getDependentsOf, E as getFirstCommit, u as getGitStatus, af as getIndependentTag, aj as getLastPackageTag, ai as getLastRepoTag, ag as getLastStableTag, ah as getLastTag, A as getModifiedReleaseFilePatterns, a5 as getPackageCommits, n as getPackageDependencies, aC as getPackageNewVersion, a4 as getPackages, aw as getPackagesOrBumpedPackages, U as getPackagesToPublishInIndependentMode, T as getPackagesToPublishInSelectiveMode, aJ as getPreid, ae as getReleaseUrl, a2 as getRootPackage, H as getShortCommitSha, a7 as getSlackToken, a8 as getSlackWebhookUrl, am as getTwitterCredentials, I as github, K as gitlab, a6 as hasLernaJson, au as isBumpedPackage, aK as isChangedPreid, aI as isGraduating, ax as isGraduatingToStableBetweenVersion, aq as isInCI, aF as isPrerelease, aH as isPrereleaseReleaseType, aG as isStableReleaseType, aR as isTagVersionCompatibleWithCurrent, l as loadRelizyConfig, m as mergeTypes, Q as parseChangelogMarkdown, z as parseGitRemoteUrl, a0 as postPrComment, ac as postReleaseToSlack, ao as postReleaseToTwitter, p as prComment, e as providerRelease, d as providerReleaseSafetyCheck, g as publish, W as publishPackage, f as publishSafetyCheck, C as pushCommitAndTags, a1 as readPackageJson, a3 as readPackages, r as release, al as resolveTags, D as rollbackModifiedFiles, aO as shouldFilterPrereleaseTags, h as social, s as socialSafetyCheck, t as topologicalSort, aD as updateLernaVersion, w as writeChangelogToFile, aB as writeVersion } from './shared/relizy.D5bCkAG-.mjs';
1
+ export { ak as NEW_PACKAGE_MARKER, $ as PR_COMMENT_MARKER, M as buildChangelogBody, a as buildCommentBody, L as buildCompareLink, O as buildContributors, b as bump, ay as capReleaseTypeForZeroMajor, c as changelog, v as checkGitStatusIfDirty, N as collectContributorNames, X as collectPackageBumps, aM as confirmBump, B as createCommitAndTags, J as createGitlabRelease, k as defineConfig, y as detectGitProvider, R as detectPackageManager, _ as detectPullRequest, S as determinePublishTag, aA as determineReleaseType, az as determineSemverChange, at as executeBuildCmd, as as executeFormatCmd, ap as executeHook, q as expandPackagesToBumpWithDependents, ad as extractChangelogSummary, aE as extractVersionFromPackageTag, aP as extractVersionFromTag, x as fetchGitTags, av as filterOutPrivatePackages, Y as findGitHubPR, Z as findGitLabMR, a9 as formatChangelogForSlack, aa as formatPackagesForSlack, ab as formatSlackMessage, an as formatTweetMessage, i as generateChangelog, P as generateMarkDown, V as getAuthCommand, aN as getBumpedIndependentPackages, aL as getBumpedPackageIndependently, ar as getCIName, aQ as getCanaryVersion, F as getCurrentGitBranch, G as getCurrentGitRef, j as getDefaultConfig, o as getDependentsOf, E as getFirstCommit, u as getGitStatus, af as getIndependentTag, aj as getLastPackageTag, ai as getLastRepoTag, ag as getLastStableTag, ah as getLastTag, A as getModifiedReleaseFilePatterns, a5 as getPackageCommits, n as getPackageDependencies, aC as getPackageNewVersion, a4 as getPackages, aw as getPackagesOrBumpedPackages, U as getPackagesToPublishInIndependentMode, T as getPackagesToPublishInSelectiveMode, aJ as getPreid, ae as getReleaseUrl, a2 as getRootPackage, H as getShortCommitSha, a7 as getSlackToken, a8 as getSlackWebhookUrl, am as getTwitterCredentials, I as github, K as gitlab, a6 as hasLernaJson, au as isBumpedPackage, aK as isChangedPreid, aI as isGraduating, ax as isGraduatingToStableBetweenVersion, aq as isInCI, aF as isPrerelease, aH as isPrereleaseReleaseType, aG as isStableReleaseType, aR as isTagVersionCompatibleWithCurrent, l as loadRelizyConfig, m as mergeTypes, Q as parseChangelogMarkdown, z as parseGitRemoteUrl, a0 as postPrComment, ac as postReleaseToSlack, ao as postReleaseToTwitter, p as prComment, e as providerRelease, d as providerReleaseSafetyCheck, g as publish, W as publishPackage, f as publishSafetyCheck, C as pushCommitAndTags, a1 as readPackageJson, a3 as readPackages, r as release, al as resolveTags, D as rollbackModifiedFiles, aO as shouldFilterPrereleaseTags, h as social, s as socialSafetyCheck, t as topologicalSort, aD as updateLernaVersion, w as writeChangelogToFile, aB as writeVersion } from './shared/relizy.CzL6Efad.mjs';
2
2
  import '@maz-ui/node';
3
3
  import 'node:child_process';
4
4
  import 'node:process';
@@ -1163,13 +1163,27 @@ async function getLastRepoTagWithFiltering({
1163
1163
  pkg,
1164
1164
  onlyStable
1165
1165
  });
1166
- if (compatibleTags.length === 0) {
1167
- logger.info(`No compatible tags found for version ${pkg.version}`);
1168
- return null;
1166
+ if (compatibleTags.length > 0) {
1167
+ const lastTag = compatibleTags[0];
1168
+ logger.debug(`Last compatible repo tag: ${lastTag}`);
1169
+ return lastTag;
1170
+ }
1171
+ if (onlyStable) {
1172
+ const prereleaseFallback = filterCompatibleTags({
1173
+ tags: recentTags,
1174
+ pkg,
1175
+ onlyStable: false
1176
+ });
1177
+ if (prereleaseFallback.length > 0) {
1178
+ const fallbackTag = prereleaseFallback[0];
1179
+ logger.info(
1180
+ `No stable repo tag found for version ${pkg.version}, falling back to last prerelease tag: ${fallbackTag}`
1181
+ );
1182
+ return fallbackTag;
1183
+ }
1169
1184
  }
1170
- const lastTag = compatibleTags[0];
1171
- logger.debug(`Last compatible repo tag: ${lastTag}`);
1172
- return lastTag;
1185
+ logger.info(`No compatible tags found for version ${pkg.version}`);
1186
+ return null;
1173
1187
  }
1174
1188
  async function getLastPackageTag({
1175
1189
  pkg,
@@ -1230,13 +1244,27 @@ async function getLastPackageTagWithFiltering({
1230
1244
  pkg,
1231
1245
  onlyStable
1232
1246
  });
1233
- if (compatibleTags.length === 0) {
1234
- logger.info(`No compatible tags found for package ${pkg.name} with version ${pkg.version}`);
1235
- return null;
1247
+ if (compatibleTags.length > 0) {
1248
+ const lastTag = compatibleTags[0];
1249
+ logger.debug(`Last compatible package tag for ${pkg.name}: ${lastTag}`);
1250
+ return lastTag;
1251
+ }
1252
+ if (onlyStable) {
1253
+ const prereleaseFallback = filterCompatibleTags({
1254
+ tags: recentTags,
1255
+ pkg,
1256
+ onlyStable: false
1257
+ });
1258
+ if (prereleaseFallback.length > 0) {
1259
+ const fallbackTag = prereleaseFallback[0];
1260
+ logger.info(
1261
+ `No stable tags found for package ${pkg.name} with version ${pkg.version}, falling back to last prerelease tag: ${fallbackTag}`
1262
+ );
1263
+ return fallbackTag;
1264
+ }
1236
1265
  }
1237
- const lastTag = compatibleTags[0];
1238
- logger.debug(`Last compatible package tag for ${pkg.name}: ${lastTag}`);
1239
- return lastTag;
1266
+ logger.info(`No compatible tags found for package ${pkg.name} with version ${pkg.version}`);
1267
+ return null;
1240
1268
  }
1241
1269
  const NEW_PACKAGE_MARKER = "__NEW_PACKAGE__";
1242
1270
  async function resolveFromTagIndependent({
@@ -2561,68 +2589,138 @@ function groupBy(items, key) {
2561
2589
  return groups;
2562
2590
  }
2563
2591
 
2564
- function fromTagIsFirstCommit(fromTag, cwd) {
2565
- return fromTag === getFirstCommit(cwd);
2592
+ function resolveSections(include) {
2593
+ return {
2594
+ title: include?.title ?? true,
2595
+ compareLink: include?.compareLink ?? true,
2596
+ body: include?.body ?? true,
2597
+ contributors: include?.contributors ?? true
2598
+ };
2566
2599
  }
2567
- async function generateChangelog({
2600
+ function resolveChangelogTags({
2568
2601
  pkg,
2569
2602
  config,
2570
- dryRun,
2571
- newVersion,
2572
- minify
2603
+ newVersion
2604
+ }) {
2605
+ const isIndependent = config.monorepo?.versionMode === "independent";
2606
+ const gitFromRef = config.from || pkg.fromTag || getFirstCommit(config.cwd);
2607
+ const isFirstCommit = gitFromRef === getFirstCommit(config.cwd);
2608
+ const displayFromTag = isFirstCommit ? isIndependent ? getIndependentTag({ version: "0.0.0", name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", "0.0.0") : gitFromRef;
2609
+ const gitToRef = config.to || getCurrentGitRef(config.cwd);
2610
+ const displayToTag = config.to || (isIndependent ? getIndependentTag({ version: newVersion, name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", newVersion));
2611
+ if (!displayToTag) {
2612
+ throw new Error(`No tag found for ${pkg.name}`);
2613
+ }
2614
+ return { gitFromRef, gitToRef, displayFromTag, displayToTag, isFirstCommit };
2615
+ }
2616
+ function renderTitle({
2617
+ fromTag,
2618
+ toTag,
2619
+ config
2620
+ }) {
2621
+ const template = config.templates?.changelogTitle || "{{oldVersion}}...{{newVersion}}";
2622
+ const changelogTitle = template.replace("{{oldVersion}}", fromTag).replace("{{newVersion}}", toTag).replace("{{date}}", (/* @__PURE__ */ new Date()).toISOString().split("T")[0]);
2623
+ return `## ${changelogTitle}`;
2624
+ }
2625
+ async function renderChangelogParts({
2626
+ commits,
2627
+ config,
2628
+ fromTag,
2629
+ toTag,
2630
+ isFirstCommit,
2631
+ sections,
2632
+ minify,
2633
+ transformBody
2573
2634
  }) {
2574
- let fromTag = config.from || pkg.fromTag || getFirstCommit(config.cwd);
2575
- const isFirstCommit = fromTagIsFirstCommit(fromTag, config.cwd);
2576
- if (isFirstCommit) {
2577
- fromTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: "0.0.0", name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", "0.0.0");
2635
+ const parts = [];
2636
+ if (sections.title) {
2637
+ parts.push(renderTitle({ fromTag, toTag, config }));
2638
+ }
2639
+ if (sections.compareLink && !minify) {
2640
+ const compareLink = buildCompareLink({ config, from: fromTag, to: toTag, isFirstCommit });
2641
+ if (compareLink) {
2642
+ parts.push(compareLink);
2643
+ }
2578
2644
  }
2579
- let toTag = config.to;
2580
- if (!toTag) {
2581
- toTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: newVersion, name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", newVersion);
2645
+ if (sections.body) {
2646
+ let body = buildChangelogBody({ commits, config, minify });
2647
+ if (transformBody && body) {
2648
+ body = await transformBody(body);
2649
+ }
2650
+ if (body) {
2651
+ parts.push(body);
2652
+ }
2582
2653
  }
2583
- if (!toTag) {
2584
- throw new Error(`No tag found for ${pkg.name}`);
2654
+ if (sections.contributors && !minify) {
2655
+ const contributors = await buildContributors({ commits, config });
2656
+ if (contributors) {
2657
+ parts.push(contributors);
2658
+ }
2585
2659
  }
2586
- logger.debug(`Generating changelog for ${pkg.name} - from ${fromTag} to ${toTag}`);
2660
+ return parts;
2661
+ }
2662
+ function isFullChangelogOutput(sections, minify) {
2663
+ return !minify && sections.title && sections.compareLink && sections.body && sections.contributors;
2664
+ }
2665
+ async function generateChangelog({
2666
+ pkg,
2667
+ config,
2668
+ dryRun,
2669
+ newVersion,
2670
+ minify,
2671
+ include,
2672
+ transformBody
2673
+ }) {
2674
+ const sections = resolveSections(include);
2675
+ const { gitFromRef, gitToRef, displayFromTag, displayToTag, isFirstCommit } = resolveChangelogTags({ pkg, config, newVersion });
2676
+ logger.debug(`Generating changelog for ${pkg.name} - git ${gitFromRef}..${gitToRef} - display ${displayFromTag}...${displayToTag}`);
2587
2677
  try {
2588
- config = {
2589
- ...config,
2590
- from: fromTag,
2591
- to: toTag
2592
- };
2593
- const generatedChangelog = await generateMarkDown({
2594
- commits: pkg.commits,
2595
- config,
2596
- from: fromTag,
2678
+ const commits = await getPackageCommits({
2679
+ pkg,
2680
+ from: gitFromRef,
2681
+ to: gitToRef,
2682
+ config: { ...config, from: gitFromRef, to: gitToRef },
2683
+ changelog: true
2684
+ });
2685
+ const displayConfig = { ...config, from: displayFromTag, to: displayToTag };
2686
+ const parts = await renderChangelogParts({
2687
+ commits,
2688
+ config: displayConfig,
2689
+ fromTag: displayFromTag,
2690
+ toTag: displayToTag,
2597
2691
  isFirstCommit,
2598
- to: toTag,
2599
- minify
2692
+ sections,
2693
+ minify,
2694
+ transformBody
2600
2695
  });
2601
- let changelog = generatedChangelog;
2602
- if (pkg.commits.length === 0) {
2696
+ let changelog = parts.filter(Boolean).join("\n\n").trim();
2697
+ const isFullOutput = isFullChangelogOutput(sections, minify);
2698
+ if (commits.length === 0 && sections.body && isFullOutput) {
2603
2699
  changelog = `${changelog}
2604
2700
 
2605
- ${config.templates.emptyChangelogContent}`;
2701
+ ${displayConfig.templates.emptyChangelogContent}`;
2702
+ }
2703
+ if (isFullOutput) {
2704
+ const changelogResult = await executeHook("generate:changelog", displayConfig, dryRun, {
2705
+ commits,
2706
+ changelog
2707
+ });
2708
+ changelog = changelogResult || changelog;
2606
2709
  }
2607
- const changelogResult = await executeHook("generate:changelog", config, dryRun, {
2608
- commits: pkg.commits,
2609
- changelog
2610
- });
2611
- changelog = changelogResult || changelog;
2612
2710
  logger.verbose(`Output changelog for ${pkg.name}:
2613
2711
  ${changelog}`);
2614
- logger.debug(`Changelog generated for ${pkg.name} (${pkg.commits.length} commits)`);
2712
+ logger.debug(`Changelog generated for ${pkg.name} (${commits.length} commits)`);
2615
2713
  logger.verbose(`Final changelog for ${pkg.name}:
2616
2714
 
2617
2715
  ${changelog}
2618
2716
 
2619
2717
  `);
2620
2718
  if (dryRun) {
2621
- logger.info(`[dry-run] ${pkg.name} - Generate changelog ${fromTag}...${toTag}`);
2719
+ logger.info(`[dry-run] ${pkg.name} - Generate changelog ${displayFromTag}...${displayToTag}`);
2622
2720
  }
2623
2721
  return changelog;
2624
2722
  } catch (error) {
2625
- throw new Error(`Error generating changelog for ${pkg.name} (${fromTag}...${toTag}): ${getErrorMessage(error)}`, { cause: error });
2723
+ throw new Error(`Error generating changelog for ${pkg.name}: ${getErrorMessage(error)}`, { cause: error });
2626
2724
  }
2627
2725
  }
2628
2726
  function writeChangelogToFile({
@@ -2872,6 +2970,52 @@ function handleFallback(config, rawBody, error) {
2872
2970
  return rawBody;
2873
2971
  }
2874
2972
 
2973
+ async function publishIndependentRelease({
2974
+ pkg,
2975
+ config,
2976
+ dryRun,
2977
+ repoConfig
2978
+ }) {
2979
+ const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
2980
+ const from = config.from || pkg.fromTag;
2981
+ const to = config.to || getIndependentTag({ version: newVersion, name: pkg.name });
2982
+ if (!from) {
2983
+ logger.warn(`No from tag found for ${pkg.name}, skipping release`);
2984
+ return void 0;
2985
+ }
2986
+ const toTag = dryRun ? "HEAD" : to;
2987
+ logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${toTag}`);
2988
+ const releaseBody = await generateChangelog({
2989
+ pkg: { ...pkg, fromTag: from },
2990
+ config,
2991
+ dryRun,
2992
+ newVersion,
2993
+ include: { title: false, compareLink: true, body: true, contributors: true },
2994
+ transformBody: isAIProviderReleaseEnabled(config) ? (body) => generateAIProviderReleaseBody({ config, rawBody: body }) : void 0
2995
+ });
2996
+ const release = {
2997
+ tag_name: to,
2998
+ name: to,
2999
+ body: releaseBody,
3000
+ prerelease: isPrerelease(newVersion)
3001
+ };
3002
+ logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
3003
+ if (dryRun) {
3004
+ logger.info(`[dry-run] Publish GitHub release for ${release.tag_name}`);
3005
+ logger.box("[dry-run] Release Preview", `Tag: ${release.tag_name}
3006
+
3007
+ ${releaseBody}`);
3008
+ } else {
3009
+ logger.debug(`Publishing release ${to} to GitHub...`);
3010
+ await createGithubRelease({ ...config, from, to, repo: repoConfig }, release);
3011
+ }
3012
+ return {
3013
+ name: pkg.name,
3014
+ tag: release.tag_name,
3015
+ version: newVersion,
3016
+ prerelease: release.prerelease
3017
+ };
3018
+ }
2875
3019
  async function githubIndependentMode({
2876
3020
  config,
2877
3021
  dryRun,
@@ -2896,55 +3040,9 @@ async function githubIndependentMode({
2896
3040
  logger.info(`Creating ${packages.length} GitHub release(s)`);
2897
3041
  const postedReleases = [];
2898
3042
  for (const pkg of packages) {
2899
- const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
2900
- const from = config.from || pkg.fromTag;
2901
- const to = config.to || getIndependentTag({ version: newVersion, name: pkg.name });
2902
- if (!from) {
2903
- logger.warn(`No from tag found for ${pkg.name}, skipping release`);
2904
- continue;
2905
- }
2906
- const toTag = dryRun ? "HEAD" : to;
2907
- logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${toTag}`);
2908
- const isFirstCommit = from === getFirstCommit(config.cwd);
2909
- const compareLink = buildCompareLink({ config, from, to, isFirstCommit });
2910
- let body = buildChangelogBody({ commits: pkg.commits, config });
2911
- const contributors = await buildContributors({ commits: pkg.commits, config });
2912
- if (isAIProviderReleaseEnabled(config)) {
2913
- body = await generateAIProviderReleaseBody({ config, rawBody: body });
2914
- }
2915
- const releaseBody = [compareLink, body, contributors].filter(Boolean).join("\n\n").trim();
2916
- const release = {
2917
- tag_name: to,
2918
- name: to,
2919
- body: releaseBody,
2920
- prerelease: isPrerelease(newVersion)
2921
- };
2922
- logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
2923
- if (dryRun) {
2924
- logger.info(`[dry-run] Publish GitHub release for ${release.tag_name}`);
2925
- postedReleases.push({
2926
- name: pkg.name,
2927
- tag: release.tag_name,
2928
- version: newVersion,
2929
- prerelease: release.prerelease
2930
- });
2931
- logger.box("[dry-run] Release Preview", `Tag: ${release.tag_name}
2932
-
2933
- ${releaseBody}`);
2934
- } else {
2935
- logger.debug(`Publishing release ${to} to GitHub...`);
2936
- await createGithubRelease({
2937
- ...config,
2938
- from,
2939
- to,
2940
- repo: repoConfig
2941
- }, release);
2942
- postedReleases.push({
2943
- name: pkg.name,
2944
- tag: release.tag_name,
2945
- version: newVersion,
2946
- prerelease: release.prerelease
2947
- });
3043
+ const posted = await publishIndependentRelease({ pkg, config, dryRun, repoConfig });
3044
+ if (posted) {
3045
+ postedReleases.push(posted);
2948
3046
  }
2949
3047
  }
2950
3048
  if (postedReleases.length === 0) {
@@ -2972,14 +3070,14 @@ async function githubUnified({
2972
3070
  const to = config.to || config.templates.tagBody.replace("{{newVersion}}", newVersion);
2973
3071
  const firstCommit = getFirstCommit(config.cwd);
2974
3072
  const from = config.from || rootPackage.fromTag || firstCommit;
2975
- const isFirstCommit = from === firstCommit;
2976
- const compareLink = buildCompareLink({ config, from, to, isFirstCommit });
2977
- let body = buildChangelogBody({ commits: rootPackage.commits, config });
2978
- const contributors = await buildContributors({ commits: rootPackage.commits, config });
2979
- if (isAIProviderReleaseEnabled(config)) {
2980
- body = await generateAIProviderReleaseBody({ config, rawBody: body });
2981
- }
2982
- const releaseBody = [compareLink, body, contributors].filter(Boolean).join("\n\n").trim();
3073
+ const releaseBody = await generateChangelog({
3074
+ pkg: { ...rootPackage, fromTag: from },
3075
+ config,
3076
+ dryRun,
3077
+ newVersion,
3078
+ include: { title: false, compareLink: true, body: true, contributors: true },
3079
+ transformBody: isAIProviderReleaseEnabled(config) ? (body) => generateAIProviderReleaseBody({ config, rawBody: body }) : void 0
3080
+ });
2983
3081
  const release = {
2984
3082
  tag_name: to,
2985
3083
  name: to,
@@ -3165,18 +3263,25 @@ async function gitlabIndependentMode({
3165
3263
  continue;
3166
3264
  }
3167
3265
  logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${to}`);
3168
- const isFirstCommit = from === getFirstCommit(config.cwd);
3169
- const compareLink = buildCompareLink({ config, from, to, isFirstCommit });
3170
- let body = buildChangelogBody({ commits: pkg.commits, config });
3171
- const contributors = await buildContributors({ commits: pkg.commits, config });
3172
- if (!body) {
3266
+ const bodyOnly = await generateChangelog({
3267
+ pkg: { ...pkg, fromTag: from },
3268
+ config,
3269
+ dryRun,
3270
+ newVersion,
3271
+ include: { title: false, compareLink: false, body: true, contributors: false }
3272
+ });
3273
+ if (!bodyOnly.trim()) {
3173
3274
  logger.warn(`No changelog found for ${pkg.name}`);
3174
3275
  continue;
3175
3276
  }
3176
- if (isAIProviderReleaseEnabled(config)) {
3177
- body = await generateAIProviderReleaseBody({ config, rawBody: body });
3178
- }
3179
- const releaseBody = [compareLink, body, contributors].filter(Boolean).join("\n\n").trim();
3277
+ const releaseBody = await generateChangelog({
3278
+ pkg: { ...pkg, fromTag: from },
3279
+ config,
3280
+ dryRun,
3281
+ newVersion,
3282
+ include: { title: false, compareLink: true, body: true, contributors: true },
3283
+ transformBody: isAIProviderReleaseEnabled(config) ? (body) => generateAIProviderReleaseBody({ config, rawBody: body }) : void 0
3284
+ });
3180
3285
  const release = {
3181
3286
  tag_name: to,
3182
3287
  name: to,
@@ -3222,14 +3327,14 @@ async function gitlabUnified({
3222
3327
  const to = config.templates.tagBody.replace("{{newVersion}}", newVersion);
3223
3328
  const firstCommit = getFirstCommit(config.cwd);
3224
3329
  const from = config.from || rootPackage.fromTag || firstCommit;
3225
- const isFirstCommit = from === firstCommit;
3226
- const compareLink = buildCompareLink({ config, from, to, isFirstCommit });
3227
- let body = buildChangelogBody({ commits: rootPackage.commits, config });
3228
- const contributors = await buildContributors({ commits: rootPackage.commits, config });
3229
- if (isAIProviderReleaseEnabled(config)) {
3230
- body = await generateAIProviderReleaseBody({ config, rawBody: body });
3231
- }
3232
- const releaseBody = [compareLink, body, contributors].filter(Boolean).join("\n\n").trim();
3330
+ const releaseBody = await generateChangelog({
3331
+ pkg: { ...rootPackage, fromTag: from },
3332
+ config,
3333
+ dryRun,
3334
+ newVersion,
3335
+ include: { title: false, compareLink: true, body: true, contributors: true },
3336
+ transformBody: isAIProviderReleaseEnabled(config) ? (body) => generateAIProviderReleaseBody({ config, rawBody: body }) : void 0
3337
+ });
3233
3338
  logger.debug("Getting current branch...");
3234
3339
  const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
3235
3340
  noSuccess: true,
@@ -3726,7 +3831,7 @@ function extractChangelogSummary(changelog, { stripBoldMarkers = false, maxLengt
3726
3831
  if (changelog.trim() === "") {
3727
3832
  return "";
3728
3833
  }
3729
- let cleaned = changelog.split("\n").filter((line) => !line.startsWith("#")).join("\n");
3834
+ let cleaned = changelog.split("\n").filter((line) => !line.startsWith("#") && line.trim() !== "").join("\n");
3730
3835
  if (stripBoldMarkers) {
3731
3836
  cleaned = cleaned.replace(/\*\*([^*]+):\*\*/g, "$1:");
3732
3837
  }
@@ -3786,7 +3891,7 @@ function formatPackagesForSlack(packages) {
3786
3891
  return "";
3787
3892
  }
3788
3893
  return packages.map(
3789
- (pkg) => pkg.hasTransition ? `\u2022 **${pkg.name}** : \`${pkg.oldVersion}\` \u2192 \`${pkg.newVersion}\`` : `\u2022 **${pkg.name}** : \`${pkg.version}\``
3894
+ (pkg) => pkg.hasTransition ? `\u2022 *${pkg.name}* : \`${pkg.oldVersion}\` \u2192 \`${pkg.newVersion}\`` : `\u2022 *${pkg.name}* : \`${pkg.version}\``
3790
3895
  ).join("\n");
3791
3896
  }
3792
3897
  function formatSlackMessage({ projectName, version, changelog, releaseUrl, changelogUrl, template, contributors = [], packages = [], postMaxLength = 2500 }) {
@@ -4599,11 +4704,12 @@ async function generateIndependentRootChangelog({
4599
4704
  logger.debug("Generating aggregated root changelog for independent mode");
4600
4705
  const packageChangelogs = [];
4601
4706
  for (const pkg of packages) {
4707
+ const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
4602
4708
  const changelog2 = await generateChangelog({
4603
4709
  pkg,
4604
4710
  config,
4605
4711
  dryRun,
4606
- newVersion: isBumpedPackage(pkg) && pkg.newVersion || pkg.version
4712
+ newVersion
4607
4713
  });
4608
4714
  if (changelog2) {
4609
4715
  packageChangelogs.push(changelog2);
@@ -4741,13 +4847,7 @@ async function changelog(options = {}) {
4741
4847
  let generatedCount = 0;
4742
4848
  for await (const pkg of packages) {
4743
4849
  const newVersion = options.bumpResult?.bumpedPackages?.find((p) => p.name === pkg.name)?.newVersion || pkg.newVersion || pkg.version;
4744
- const { from, to } = await resolveTags({
4745
- config,
4746
- step: "changelog",
4747
- pkg,
4748
- newVersion
4749
- });
4750
- logger.debug(`Processing ${pkg.name} (${from}...${to})`);
4850
+ logger.debug(`Processing ${pkg.name}`);
4751
4851
  const changelog2 = await generateChangelog({
4752
4852
  pkg,
4753
4853
  config,
@@ -5546,8 +5646,22 @@ async function social(options = {}) {
5546
5646
  from: fromTag,
5547
5647
  to
5548
5648
  });
5549
- const minifiedBody = buildChangelogBody({ commits: rootPackage.commits, config, minify: true });
5550
- const richBody = buildChangelogBody({ commits: rootPackage.commits, config, minify: false });
5649
+ const minifiedBody = await generateChangelog({
5650
+ pkg: { ...rootPackage, fromTag },
5651
+ config,
5652
+ dryRun,
5653
+ newVersion,
5654
+ include: { title: false, compareLink: false, body: true, contributors: false },
5655
+ minify: true
5656
+ });
5657
+ const richBody = await generateChangelog({
5658
+ pkg: { ...rootPackage, fromTag },
5659
+ config,
5660
+ dryRun,
5661
+ newVersion,
5662
+ include: { title: false, compareLink: false, body: true, contributors: false },
5663
+ minify: false
5664
+ });
5551
5665
  const hasContent = !!minifiedBody.trim();
5552
5666
  const twitterReleaseUrl = getReleaseUrl(config, to);
5553
5667
  const twitterChangelogUrl = config.social?.changelogUrl;
@@ -5597,13 +5711,20 @@ ${twitterChangelog}`);
5597
5711
  newVersion,
5598
5712
  tag: to
5599
5713
  });
5714
+ const changelogCommits = await getPackageCommits({
5715
+ pkg: rootPackage,
5716
+ from: fromTag,
5717
+ to: "HEAD",
5718
+ config,
5719
+ changelog: true
5720
+ });
5600
5721
  const slackResponse = await handleSlackPost({
5601
5722
  config,
5602
5723
  changelog: slackChangelog,
5603
5724
  dryRun,
5604
5725
  newVersion,
5605
5726
  tag: to,
5606
- commits: rootPackage.commits,
5727
+ commits: changelogCommits,
5607
5728
  bumpedPackages: options.bumpResult?.bumpedPackages
5608
5729
  });
5609
5730
  const results = [];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "relizy",
3
3
  "type": "module",
4
- "version": "1.4.4",
4
+ "version": "1.4.6",
5
5
  "description": "Changelogen adapter for monorepo management with unified and independent versioning",
6
6
  "author": "Louis Mazel <me@loicmazuel.com>",
7
7
  "license": "MIT",
@@ -126,7 +126,7 @@
126
126
  "test:unit": "vitest run",
127
127
  "test:unit:watch": "vitest watch",
128
128
  "test:unit:coverage": "vitest run --coverage",
129
- "health": "pnpm typecheck && pnpm lint:all && pnpm test:unit:coverage && pnpm build && pnpm -F docs build",
129
+ "health": "pnpm typecheck && pnpm -F docs typecheck && pnpm lint:fix:all && pnpm test:unit:coverage && pnpm build && pnpm -F docs build",
130
130
  "pre-commit": "lint-staged"
131
131
  }
132
132
  }