relizy 1.5.1 → 1.7.0-beta.0

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 { aw as isInCI, S as getCIName, f as bump, h as changelog, aN as publish, aL as providerRelease, b4 as social, aK as prComment, aW as release } from './shared/relizy.DDpPSTvS.mjs';
8
+ import { aC as isInCI, V as getCIName, h as bump, j as changelog, aT as publish, aR as providerRelease, ba as social, aQ as prComment, b0 as release } from './shared/relizy.uCxVVpbQ.mjs';
9
9
  import 'node:child_process';
10
10
  import '@maz-ui/utils/helpers/formatJson';
11
11
  import 'c12';
package/dist/index.d.mts CHANGED
@@ -194,11 +194,61 @@ declare function createCommitAndTags({ config, noVerify, bumpedPackages, newVers
194
194
  dryRun?: boolean;
195
195
  logLevel: LogLevel;
196
196
  }): Promise<string[]>;
197
- declare function pushCommitAndTags({ config, dryRun, logLevel, cwd }: {
197
+ interface GitUpstream {
198
+ /** Remote name, e.g. `origin` */
199
+ remote: string;
200
+ /** Remote branch ref, e.g. `refs/heads/main` */
201
+ mergeRef: string;
202
+ /** Remote-tracking ref, e.g. `refs/remotes/origin/main` */
203
+ trackingRef: string;
204
+ /** Short remote-tracking name, e.g. `origin/main` */
205
+ name: string;
206
+ }
207
+ /**
208
+ * Resolve the upstream of the current branch. Returns null on a detached HEAD
209
+ * or when the branch has no upstream configured.
210
+ */
211
+ declare function getGitUpstream(cwd: string): Promise<GitUpstream | null>;
212
+ /**
213
+ * Ensure the current branch contains every commit of its remote counterpart.
214
+ *
215
+ * A release commit created on a branch that is behind its remote can never be
216
+ * pushed. Since packages are published before the push, running this check
217
+ * right before publishing prevents shipping a version whose release commit is
218
+ * then rejected (leaving an orphan tag and the repository stuck on the
219
+ * previous version).
220
+ *
221
+ * Skipped (no error) on a detached HEAD, without upstream, or when the remote
222
+ * cannot be fetched.
223
+ */
224
+ declare function assertBranchUpToDateWithRemote({ cwd }: {
225
+ cwd: string;
226
+ }): Promise<void>;
227
+ declare function pushCommitAndTags({ config, dryRun, logLevel, cwd, tags, }: {
198
228
  config: ResolvedRelizyConfig;
199
229
  dryRun: boolean;
200
230
  logLevel?: LogLevel;
201
231
  cwd: string;
232
+ tags?: string[];
233
+ }): Promise<void>;
234
+ /**
235
+ * Compute the git tag names a release will create, mirroring `createCommitAndTags`.
236
+ */
237
+ declare function getReleaseTagNames({ config, bumpedPackages, newVersion, }: {
238
+ config: ResolvedRelizyConfig;
239
+ bumpedPackages?: BumpResultTruthy['bumpedPackages'];
240
+ newVersion?: string;
241
+ }): string[];
242
+ /**
243
+ * Fail early when a tag the release is about to create already exists.
244
+ *
245
+ * This typically happens after a release that published its packages and
246
+ * pushed its tag, but whose release commit was rejected: the branch is still
247
+ * on the previous version, so the next run computes the same version again.
248
+ */
249
+ declare function assertReleaseTagsAvailable({ tags, cwd }: {
250
+ tags: string[];
251
+ cwd: string;
202
252
  }): Promise<void>;
203
253
  /**
204
254
  * Rollback modified files to their last committed state
@@ -537,6 +587,13 @@ declare function postPrComment({ config, pr, body, }: {
537
587
  */
538
588
  declare function redactSecrets<T>(value: T): T;
539
589
 
590
+ /**
591
+ * Resolve the commit a new package's compare link starts from: the parent of
592
+ * the first commit that touched the package, so the link covers the whole
593
+ * package history. Falls back to that first commit when it is the repository
594
+ * root commit (no parent). Returns null when the package has no commits yet.
595
+ */
596
+ declare function getNewPackageCompareBase(packagePath: string, cwd: string): string | null;
540
597
  declare function readPackageJson(packagePath: string): ReadPackage | undefined;
541
598
  /**
542
599
  * Resolve a set of path globs (relative to `cwd`) to the absolute directories
@@ -779,6 +836,14 @@ declare function isBumpedPackage(pkg: PackageBase): pkg is PackageBase & {
779
836
  declare function filterOutPrivatePackages<T extends {
780
837
  private: boolean;
781
838
  }>(packages: T[]): T[];
839
+ /**
840
+ * Keep private packages only when `monorepo.includePrivates` is enabled. They
841
+ * are then versioned and tagged like public ones, so they also get provider
842
+ * releases and appear in PR comments. Publishing ignores them regardless.
843
+ */
844
+ declare function filterPrivatePackagesUnlessIncluded<T extends {
845
+ private: boolean;
846
+ }>(packages: T[], includePrivates: boolean | undefined): T[];
782
847
  declare function getPackagesOrBumpedPackages({ config, bumpResult, suffix, force, dryRun, }: {
783
848
  config: ResolvedRelizyConfig;
784
849
  bumpResult: BumpResultTruthy | undefined;
@@ -2232,6 +2297,7 @@ interface CommentBodyParams {
2232
2297
  packages?: Array<{
2233
2298
  name: string;
2234
2299
  version: string;
2300
+ private: boolean;
2235
2301
  }>;
2236
2302
  /** Fallback root version for standalone CLI mode */
2237
2303
  rootVersion?: string;
@@ -2289,5 +2355,5 @@ declare function socialSafetyCheck({ config }: {
2289
2355
  }): Promise<void>;
2290
2356
  declare function social(options?: Partial<SocialOptions>): Promise<SocialResult>;
2291
2357
 
2292
- export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, buildReleaseSummary, 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, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitChangedFiles, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitDiff, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, globDirsAbsolute, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isCommitOnlyInIgnoredPackages, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, isVersionAlreadyPublishedError, isVersionPublished, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveIgnoredPackagePaths, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, tryPostPrComment, updateLernaVersion, withRegistryNpmrc, writeChangelogToFile, writeVersion };
2293
- 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, OnRewrittenTag, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, RegistryTarget, 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 };
2358
+ export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, assertBranchUpToDateWithRemote, assertReleaseTagsAvailable, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, buildReleaseSummary, 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, filterPrivatePackagesUnlessIncluded, findGitHubPR, findGitLabMR, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitChangedFiles, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitDiff, getGitStatus, getGitUpstream, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNewPackageCompareBase, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseTagNames, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, globDirsAbsolute, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isCommitOnlyInIgnoredPackages, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, isVersionAlreadyPublishedError, isVersionPublished, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveIgnoredPackagePaths, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, tryPostPrComment, updateLernaVersion, withRegistryNpmrc, writeChangelogToFile, writeVersion };
2359
+ export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogInclude, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitUpstream, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, OnRewrittenTag, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, RegistryTarget, 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
@@ -194,11 +194,61 @@ declare function createCommitAndTags({ config, noVerify, bumpedPackages, newVers
194
194
  dryRun?: boolean;
195
195
  logLevel: LogLevel;
196
196
  }): Promise<string[]>;
197
- declare function pushCommitAndTags({ config, dryRun, logLevel, cwd }: {
197
+ interface GitUpstream {
198
+ /** Remote name, e.g. `origin` */
199
+ remote: string;
200
+ /** Remote branch ref, e.g. `refs/heads/main` */
201
+ mergeRef: string;
202
+ /** Remote-tracking ref, e.g. `refs/remotes/origin/main` */
203
+ trackingRef: string;
204
+ /** Short remote-tracking name, e.g. `origin/main` */
205
+ name: string;
206
+ }
207
+ /**
208
+ * Resolve the upstream of the current branch. Returns null on a detached HEAD
209
+ * or when the branch has no upstream configured.
210
+ */
211
+ declare function getGitUpstream(cwd: string): Promise<GitUpstream | null>;
212
+ /**
213
+ * Ensure the current branch contains every commit of its remote counterpart.
214
+ *
215
+ * A release commit created on a branch that is behind its remote can never be
216
+ * pushed. Since packages are published before the push, running this check
217
+ * right before publishing prevents shipping a version whose release commit is
218
+ * then rejected (leaving an orphan tag and the repository stuck on the
219
+ * previous version).
220
+ *
221
+ * Skipped (no error) on a detached HEAD, without upstream, or when the remote
222
+ * cannot be fetched.
223
+ */
224
+ declare function assertBranchUpToDateWithRemote({ cwd }: {
225
+ cwd: string;
226
+ }): Promise<void>;
227
+ declare function pushCommitAndTags({ config, dryRun, logLevel, cwd, tags, }: {
198
228
  config: ResolvedRelizyConfig;
199
229
  dryRun: boolean;
200
230
  logLevel?: LogLevel;
201
231
  cwd: string;
232
+ tags?: string[];
233
+ }): Promise<void>;
234
+ /**
235
+ * Compute the git tag names a release will create, mirroring `createCommitAndTags`.
236
+ */
237
+ declare function getReleaseTagNames({ config, bumpedPackages, newVersion, }: {
238
+ config: ResolvedRelizyConfig;
239
+ bumpedPackages?: BumpResultTruthy['bumpedPackages'];
240
+ newVersion?: string;
241
+ }): string[];
242
+ /**
243
+ * Fail early when a tag the release is about to create already exists.
244
+ *
245
+ * This typically happens after a release that published its packages and
246
+ * pushed its tag, but whose release commit was rejected: the branch is still
247
+ * on the previous version, so the next run computes the same version again.
248
+ */
249
+ declare function assertReleaseTagsAvailable({ tags, cwd }: {
250
+ tags: string[];
251
+ cwd: string;
202
252
  }): Promise<void>;
203
253
  /**
204
254
  * Rollback modified files to their last committed state
@@ -537,6 +587,13 @@ declare function postPrComment({ config, pr, body, }: {
537
587
  */
538
588
  declare function redactSecrets<T>(value: T): T;
539
589
 
590
+ /**
591
+ * Resolve the commit a new package's compare link starts from: the parent of
592
+ * the first commit that touched the package, so the link covers the whole
593
+ * package history. Falls back to that first commit when it is the repository
594
+ * root commit (no parent). Returns null when the package has no commits yet.
595
+ */
596
+ declare function getNewPackageCompareBase(packagePath: string, cwd: string): string | null;
540
597
  declare function readPackageJson(packagePath: string): ReadPackage | undefined;
541
598
  /**
542
599
  * Resolve a set of path globs (relative to `cwd`) to the absolute directories
@@ -779,6 +836,14 @@ declare function isBumpedPackage(pkg: PackageBase): pkg is PackageBase & {
779
836
  declare function filterOutPrivatePackages<T extends {
780
837
  private: boolean;
781
838
  }>(packages: T[]): T[];
839
+ /**
840
+ * Keep private packages only when `monorepo.includePrivates` is enabled. They
841
+ * are then versioned and tagged like public ones, so they also get provider
842
+ * releases and appear in PR comments. Publishing ignores them regardless.
843
+ */
844
+ declare function filterPrivatePackagesUnlessIncluded<T extends {
845
+ private: boolean;
846
+ }>(packages: T[], includePrivates: boolean | undefined): T[];
782
847
  declare function getPackagesOrBumpedPackages({ config, bumpResult, suffix, force, dryRun, }: {
783
848
  config: ResolvedRelizyConfig;
784
849
  bumpResult: BumpResultTruthy | undefined;
@@ -2232,6 +2297,7 @@ interface CommentBodyParams {
2232
2297
  packages?: Array<{
2233
2298
  name: string;
2234
2299
  version: string;
2300
+ private: boolean;
2235
2301
  }>;
2236
2302
  /** Fallback root version for standalone CLI mode */
2237
2303
  rootVersion?: string;
@@ -2289,5 +2355,5 @@ declare function socialSafetyCheck({ config }: {
2289
2355
  }): Promise<void>;
2290
2356
  declare function social(options?: Partial<SocialOptions>): Promise<SocialResult>;
2291
2357
 
2292
- export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, buildReleaseSummary, 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, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitChangedFiles, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitDiff, getGitStatus, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, globDirsAbsolute, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isCommitOnlyInIgnoredPackages, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, isVersionAlreadyPublishedError, isVersionPublished, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveIgnoredPackagePaths, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, tryPostPrComment, updateLernaVersion, withRegistryNpmrc, writeChangelogToFile, writeVersion };
2293
- 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, OnRewrittenTag, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, RegistryTarget, 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 };
2358
+ export { NEW_PACKAGE_MARKER, PR_COMMENT_MARKER, assertBranchUpToDateWithRemote, assertReleaseTagsAvailable, buildChangelogBody, buildCommentBody, buildCompareLink, buildContributors, buildReleaseSummary, 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, filterPrivatePackagesUnlessIncluded, findGitHubPR, findGitLabMR, findReachableCommitBySubject, formatChangelogForSlack, formatPackagesForSlack, formatSlackMessage, formatTweetMessage, generateChangelog, generateMarkDown, getAuthCommand, getBumpedIndependentPackages, getBumpedPackageIndependently, getCIName, getCanaryVersion, getCommitChangedFiles, getCommitSubject, getCurrentGitBranch, getCurrentGitRef, getDefaultConfig, getDependentsOf, getFirstCommit, getGitDiff, getGitStatus, getGitUpstream, getIndependentTag, getLastPackageTag, getLastRepoTag, getLastStableTag, getLastTag, getModifiedReleaseFilePatterns, getNewPackageCompareBase, getNpmRegistry, getPackageCommits, getPackageDependencies, getPackageNewVersion, getPackages, getPackagesOrBumpedPackages, getPackagesToPublishInIndependentMode, getPackagesToPublishInSelectiveMode, getPreid, getReleaseTagNames, getReleaseUrl, getRootPackage, getShortCommitSha, getSlackToken, getSlackWebhookUrl, getTwitterCredentials, github, gitlab, globDirsAbsolute, hasLernaJson, isAncestor, isBumpedPackage, isChangedPreid, isCommitOnlyInIgnoredPackages, isGraduating, isGraduatingToStableBetweenVersion, isInCI, isPrerelease, isPrereleaseReleaseType, isStableReleaseType, isTagVersionCompatibleWithCurrent, isVersionAlreadyPublishedError, isVersionPublished, loadRelizyConfig, mergeTypes, parseChangelogMarkdown, parseGitRemoteUrl, postPrComment, postReleaseToSlack, postReleaseToTwitter, prComment, providerRelease, providerReleaseSafetyCheck, publish, publishPackage, publishSafetyCheck, pushCommitAndTags, pushTagForce, readPackageJson, readPackages, reconcileFromTag, redactSecrets, release, resetRewrittenTagCache, resolveAllConfiguredRegistryTargets, resolveIgnoredPackagePaths, resolveRegistryTargetsForPackage, resolveRegistryTargetsForPackages, resolveTags, retagAnnotatedLocal, rollbackModifiedFiles, shouldFilterPrereleaseTags, social, socialSafetyCheck, tagExists, topologicalSort, tryPostPrComment, updateLernaVersion, withRegistryNpmrc, writeChangelogToFile, writeVersion };
2359
+ export type { AIConfig, AIPromptTarget, AIProviderName, AISocialConfig, AISystemPromptOverrides, AITargetConfig, BumpConfig, BumpOptions, BumpResult, BumpResultFalsy, BumpResultTruthy, ChangelogConfig, ChangelogInclude, ChangelogOptions, ClaudeCodeProviderOptions, ConfigType, GitProvider, GitUpstream, GitlabRelease, GitlabReleaseResponse, HookConfig, HookStep, HookType, MonorepoConfig, OnRewrittenTag, PackageBase, PackageBumpEntry, PackageManager, PostedRelease, PrCommentConfig, PrCommentMode, PrCommentOptions, PrCommentStatus, ProviderReleaseOptions, ProviderReleaseResult, PublishConfig, PublishOptions, PublishResponse, PullRequestInfo, ReadPackage, Reference, RegistryTarget, 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 { N as NEW_PACKAGE_MARKER, P as PR_COMMENT_MARKER, b as buildChangelogBody, a as buildCommentBody, c as buildCompareLink, d as buildContributors, e as buildReleaseSummary, f as bump, g as capReleaseTypeForZeroMajor, h as changelog, i as checkGitStatusIfDirty, j as collectContributorNames, k as collectPackageBumps, l as confirmBump, m as createCommitAndTags, n as createGitlabRelease, o as defineConfig, p as detectGitProvider, q as detectPackageManager, r as detectPullRequest, s as determinePublishTag, t as determineReleaseType, u as determineSemverChange, v as executeBuildCmd, w as executeFormatCmd, x as executeHook, y as expandPackagesToBumpWithDependents, z as extractChangelogSummary, A as extractVersionFromPackageTag, B as extractVersionFromTag, C as fetchGitTags, D as filterOutPrivatePackages, E as findGitHubPR, F as findGitLabMR, G as findReachableCommitBySubject, H as formatChangelogForSlack, I as formatPackagesForSlack, J as formatSlackMessage, K as formatTweetMessage, L as generateChangelog, M as generateMarkDown, O as getAuthCommand, Q as getBumpedIndependentPackages, R as getBumpedPackageIndependently, S as getCIName, T as getCanaryVersion, U as getCommitChangedFiles, V as getCommitSubject, W as getCurrentGitBranch, X as getCurrentGitRef, Y as getDefaultConfig, Z as getDependentsOf, _ as getFirstCommit, $ as getGitDiff, a0 as getGitStatus, a1 as getIndependentTag, a2 as getLastPackageTag, a3 as getLastRepoTag, a4 as getLastStableTag, a5 as getLastTag, a6 as getModifiedReleaseFilePatterns, a7 as getNpmRegistry, a8 as getPackageCommits, a9 as getPackageDependencies, aa as getPackageNewVersion, ab as getPackages, ac as getPackagesOrBumpedPackages, ad as getPackagesToPublishInIndependentMode, ae as getPackagesToPublishInSelectiveMode, af as getPreid, ag as getReleaseUrl, ah as getRootPackage, ai as getShortCommitSha, aj as getSlackToken, ak as getSlackWebhookUrl, al as getTwitterCredentials, am as github, an as gitlab, ao as globDirsAbsolute, ap as hasLernaJson, aq as isAncestor, ar as isBumpedPackage, as as isChangedPreid, at as isCommitOnlyInIgnoredPackages, au as isGraduating, av as isGraduatingToStableBetweenVersion, aw as isInCI, ax as isPrerelease, ay as isPrereleaseReleaseType, az as isStableReleaseType, aA as isTagVersionCompatibleWithCurrent, aB as isVersionAlreadyPublishedError, aC as isVersionPublished, aD as loadRelizyConfig, aE as mergeTypes, aF as parseChangelogMarkdown, aG as parseGitRemoteUrl, aH as postPrComment, aI as postReleaseToSlack, aJ as postReleaseToTwitter, aK as prComment, aL as providerRelease, aM as providerReleaseSafetyCheck, aN as publish, aO as publishPackage, aP as publishSafetyCheck, aQ as pushCommitAndTags, aR as pushTagForce, aS as readPackageJson, aT as readPackages, aU as reconcileFromTag, aV as redactSecrets, aW as release, aX as resetRewrittenTagCache, aY as resolveAllConfiguredRegistryTargets, aZ as resolveIgnoredPackagePaths, a_ as resolveRegistryTargetsForPackage, a$ as resolveRegistryTargetsForPackages, b0 as resolveTags, b1 as retagAnnotatedLocal, b2 as rollbackModifiedFiles, b3 as shouldFilterPrereleaseTags, b4 as social, b5 as socialSafetyCheck, b6 as tagExists, b7 as topologicalSort, b8 as tryPostPrComment, b9 as updateLernaVersion, ba as withRegistryNpmrc, bb as writeChangelogToFile, bc as writeVersion } from './shared/relizy.DDpPSTvS.mjs';
1
+ export { N as NEW_PACKAGE_MARKER, P as PR_COMMENT_MARKER, a as assertBranchUpToDateWithRemote, b as assertReleaseTagsAvailable, c as buildChangelogBody, d as buildCommentBody, e as buildCompareLink, f as buildContributors, g as buildReleaseSummary, h as bump, i as capReleaseTypeForZeroMajor, j as changelog, k as checkGitStatusIfDirty, l as collectContributorNames, m as collectPackageBumps, n as confirmBump, o as createCommitAndTags, p as createGitlabRelease, q as defineConfig, r as detectGitProvider, s as detectPackageManager, t as detectPullRequest, u as determinePublishTag, v as determineReleaseType, w as determineSemverChange, x as executeBuildCmd, y as executeFormatCmd, z as executeHook, A as expandPackagesToBumpWithDependents, B as extractChangelogSummary, C as extractVersionFromPackageTag, D as extractVersionFromTag, E as fetchGitTags, F as filterOutPrivatePackages, G as filterPrivatePackagesUnlessIncluded, H as findGitHubPR, I as findGitLabMR, J as findReachableCommitBySubject, K as formatChangelogForSlack, L as formatPackagesForSlack, M as formatSlackMessage, O as formatTweetMessage, Q as generateChangelog, R as generateMarkDown, S as getAuthCommand, T as getBumpedIndependentPackages, U as getBumpedPackageIndependently, V as getCIName, W as getCanaryVersion, X as getCommitChangedFiles, Y as getCommitSubject, Z as getCurrentGitBranch, _ as getCurrentGitRef, $ as getDefaultConfig, a0 as getDependentsOf, a1 as getFirstCommit, a2 as getGitDiff, a3 as getGitStatus, a4 as getGitUpstream, a5 as getIndependentTag, a6 as getLastPackageTag, a7 as getLastRepoTag, a8 as getLastStableTag, a9 as getLastTag, aa as getModifiedReleaseFilePatterns, ab as getNewPackageCompareBase, ac as getNpmRegistry, ad as getPackageCommits, ae as getPackageDependencies, af as getPackageNewVersion, ag as getPackages, ah as getPackagesOrBumpedPackages, ai as getPackagesToPublishInIndependentMode, aj as getPackagesToPublishInSelectiveMode, ak as getPreid, al as getReleaseTagNames, am as getReleaseUrl, an as getRootPackage, ao as getShortCommitSha, ap as getSlackToken, aq as getSlackWebhookUrl, ar as getTwitterCredentials, as as github, at as gitlab, au as globDirsAbsolute, av as hasLernaJson, aw as isAncestor, ax as isBumpedPackage, ay as isChangedPreid, az as isCommitOnlyInIgnoredPackages, aA as isGraduating, aB as isGraduatingToStableBetweenVersion, aC as isInCI, aD as isPrerelease, aE as isPrereleaseReleaseType, aF as isStableReleaseType, aG as isTagVersionCompatibleWithCurrent, aH as isVersionAlreadyPublishedError, aI as isVersionPublished, aJ as loadRelizyConfig, aK as mergeTypes, aL as parseChangelogMarkdown, aM as parseGitRemoteUrl, aN as postPrComment, aO as postReleaseToSlack, aP as postReleaseToTwitter, aQ as prComment, aR as providerRelease, aS as providerReleaseSafetyCheck, aT as publish, aU as publishPackage, aV as publishSafetyCheck, aW as pushCommitAndTags, aX as pushTagForce, aY as readPackageJson, aZ as readPackages, a_ as reconcileFromTag, a$ as redactSecrets, b0 as release, b1 as resetRewrittenTagCache, b2 as resolveAllConfiguredRegistryTargets, b3 as resolveIgnoredPackagePaths, b4 as resolveRegistryTargetsForPackage, b5 as resolveRegistryTargetsForPackages, b6 as resolveTags, b7 as retagAnnotatedLocal, b8 as rollbackModifiedFiles, b9 as shouldFilterPrereleaseTags, ba as social, bb as socialSafetyCheck, bc as tagExists, bd as topologicalSort, be as tryPostPrComment, bf as updateLernaVersion, bg as withRegistryNpmrc, bh as writeChangelogToFile, bi as writeVersion } from './shared/relizy.uCxVVpbQ.mjs';
2
2
  import '@maz-ui/node';
3
3
  import 'node:child_process';
4
4
  import 'node:process';
@@ -250,7 +250,7 @@ function buildExplanation({
250
250
  }) {
251
251
  const lines = [
252
252
  `\u26A0\uFE0F Tag "${from}" points to a commit that is no longer in the history of "${to}".`,
253
- `It was most likely rewritten by a "git rebase" after the tag was created.`,
253
+ `It was most likely rewritten by a "git rebase" after the tag was created, or its release commit was never pushed to "${to}" (rejected push during a release).`,
254
254
  `Generating a changelog from it would span the whole divergent range (often the entire history since the last stable release, with duplicated commits) instead of the real changes.`
255
255
  ];
256
256
  if (twin) {
@@ -414,6 +414,24 @@ function getFirstPackageCommitHash(packagePath, cwd) {
414
414
  return null;
415
415
  }
416
416
  }
417
+ function getCommitParentHash(hash, cwd) {
418
+ try {
419
+ const parent = execSync(
420
+ `git rev-parse --verify --quiet "${hash}^"`,
421
+ { cwd, encoding: "utf8" }
422
+ ).trim();
423
+ return parent || null;
424
+ } catch {
425
+ return null;
426
+ }
427
+ }
428
+ function getNewPackageCompareBase(packagePath, cwd) {
429
+ const firstPackageCommit = getFirstPackageCommitHash(packagePath, cwd);
430
+ if (!firstPackageCommit) {
431
+ return null;
432
+ }
433
+ return getCommitParentHash(firstPackageCommit, cwd) || firstPackageCommit;
434
+ }
417
435
  function readPackageJson(packagePath) {
418
436
  const packageJsonPath = join(packagePath, "package.json");
419
437
  if (!existsSync(packageJsonPath)) {
@@ -774,13 +792,13 @@ async function getPackageCommits({
774
792
  return [];
775
793
  }
776
794
  logger.debug(`${pkg.name} is a new package, using first package commit: ${firstPackageCommit.slice(0, 8)}`);
777
- actualFrom = `${firstPackageCommit}^`;
795
+ actualFrom = getCommitParentHash(firstPackageCommit, config.cwd) ?? void 0;
778
796
  } else {
779
797
  actualFrom = await reconcileFromTag({ from, to, config, dryRun });
780
798
  }
781
799
  const changelogConfig = {
782
800
  ...config,
783
- from: actualFrom,
801
+ from: actualFrom ?? "",
784
802
  to
785
803
  };
786
804
  const rawCommits = getGitDiff(actualFrom, to, changelogConfig.cwd);
@@ -1875,6 +1893,9 @@ function isBumpedPackage(pkg) {
1875
1893
  function filterOutPrivatePackages(packages) {
1876
1894
  return packages.filter((p) => !p.private);
1877
1895
  }
1896
+ function filterPrivatePackagesUnlessIncluded(packages, includePrivates) {
1897
+ return includePrivates ? packages : filterOutPrivatePackages(packages);
1898
+ }
1878
1899
  async function getPackagesOrBumpedPackages({
1879
1900
  config,
1880
1901
  bumpResult,
@@ -2440,7 +2461,7 @@ async function publishToRegistryTarget({
2440
2461
  return;
2441
2462
  }
2442
2463
  throw new Error(
2443
- `Version ${packageNameAndVersion} already exists on the registry${registryLabel} and cannot be overwritten. This usually happens when re-running a release on the same commit (e.g. a canary rerun). Enable publish.skipExistingVersions (or pass --skip-existing-versions) to skip already-published versions instead of failing.`,
2464
+ `Version ${packageNameAndVersion} already exists on the registry${registryLabel} and cannot be overwritten. This usually happens when re-running a release on the same commit (e.g. a canary rerun), or after a release that published this version but failed to push its release commit (merge its tag into your branch to recover). Enable publish.skipExistingVersions (or pass --skip-existing-versions) to skip already-published versions instead of failing.`,
2444
2465
  { cause: error }
2445
2466
  );
2446
2467
  } else {
@@ -2993,17 +3014,158 @@ async function createCommitAndTags({
2993
3014
  throw error;
2994
3015
  }
2995
3016
  }
2996
- async function pushCommitAndTags({ config, dryRun, logLevel, cwd }) {
3017
+ const quietExec = { noStderr: true, noStdout: true, noSuccess: true, noError: true };
3018
+ async function getGitUpstream(cwd) {
3019
+ try {
3020
+ const branch = getCurrentGitBranch(cwd);
3021
+ if (!branch || branch === "HEAD") {
3022
+ return null;
3023
+ }
3024
+ const [{ stdout: remote }, { stdout: mergeRef }, { stdout: trackingRef }] = await Promise.all([
3025
+ execPromise(`git config --get branch.${branch}.remote`, { cwd, ...quietExec }),
3026
+ execPromise(`git config --get branch.${branch}.merge`, { cwd, ...quietExec }),
3027
+ execPromise("git rev-parse --symbolic-full-name @{upstream}", { cwd, ...quietExec })
3028
+ ]);
3029
+ if (!remote.trim() || !mergeRef.trim() || !trackingRef.trim()) {
3030
+ return null;
3031
+ }
3032
+ return {
3033
+ remote: remote.trim(),
3034
+ mergeRef: mergeRef.trim(),
3035
+ trackingRef: trackingRef.trim(),
3036
+ name: trackingRef.trim().replace(/^refs\/remotes\//, "")
3037
+ };
3038
+ } catch {
3039
+ return null;
3040
+ }
3041
+ }
3042
+ async function fetchUpstream(upstream, cwd) {
3043
+ await execPromise(`git fetch ${upstream.remote} +${upstream.mergeRef}:${upstream.trackingRef}`, { cwd, ...quietExec });
3044
+ }
3045
+ async function assertBranchUpToDateWithRemote({ cwd }) {
3046
+ const upstream = await getGitUpstream(cwd);
3047
+ if (!upstream) {
3048
+ logger.debug("No upstream branch configured, skipping remote sync check");
3049
+ return;
3050
+ }
3051
+ try {
3052
+ await fetchUpstream(upstream, cwd);
3053
+ } catch (error) {
3054
+ logger.warn(`Could not fetch "${upstream.name}", skipping remote sync check`);
3055
+ logger.debug("Fetch error:", error);
3056
+ return;
3057
+ }
3058
+ const { stdout } = await execPromise(`git rev-list --count HEAD..${upstream.trackingRef}`, { cwd, ...quietExec });
3059
+ const missingCommits = Number.parseInt(stdout.trim(), 10) || 0;
3060
+ if (missingCommits > 0) {
3061
+ throw new Error(
3062
+ `The current branch is behind "${upstream.name}" by ${missingCommits} commit(s): new commits were pushed while the release was running.
3063
+ Releasing now would publish packages whose release commit cannot be pushed.
3064
+ Re-run the release from the latest commit of "${upstream.name}".`
3065
+ );
3066
+ }
3067
+ logger.debug(`Branch is up to date with "${upstream.name}"`);
3068
+ }
3069
+ function isPushRejectedAsBehind(error) {
3070
+ if (!error || typeof error !== "object") {
3071
+ return false;
3072
+ }
3073
+ const { message, stderr } = error;
3074
+ const output = `${typeof message === "string" ? message : ""}
3075
+ ${typeof stderr === "string" ? stderr : ""}`;
3076
+ return output.includes("(non-fast-forward)") || output.includes("(fetch first)");
3077
+ }
3078
+ async function recoverRejectedPush({
3079
+ config,
3080
+ command,
3081
+ tags,
3082
+ pushError,
3083
+ logLevel,
3084
+ cwd
3085
+ }) {
3086
+ const upstream = await getGitUpstream(cwd);
3087
+ if (!upstream) {
3088
+ throw pushError;
3089
+ }
3090
+ logger.warn(`Push rejected: "${upstream.name}" received new commits during the release. Merging them into the release commit and retrying...`);
3091
+ try {
3092
+ await fetchUpstream(upstream, cwd);
3093
+ const noVerifyFlag = config.release.noVerify ? " --no-verify" : "";
3094
+ await execPromise(`git merge --no-edit${noVerifyFlag} ${upstream.name}`, { cwd, ...quietExec });
3095
+ } catch (mergeError) {
3096
+ await execPromise("git merge --abort", { cwd, ...quietExec }).catch(() => {
3097
+ });
3098
+ if (tags.length > 0) {
3099
+ const tagRefs = tags.map((tag) => `refs/tags/${tag}`).join(" ");
3100
+ await execPromise(`git push ${upstream.remote} ${tagRefs}`, { cwd, ...quietExec }).catch(() => {
3101
+ });
3102
+ }
3103
+ const recoverRef = tags[0] ?? "HEAD";
3104
+ throw new Error(
3105
+ `Push rejected: "${upstream.name}" received new commits during the release, and they could not be merged automatically into the release commit.
3106
+ The packages are already published, but the release commit is not on the branch.
3107
+ To recover, merge it manually: git fetch --tags && git merge ${recoverRef} && git push`,
3108
+ { cause: mergeError }
3109
+ );
3110
+ }
3111
+ await execPromise(command, { noStderr: true, noStdout: true, logLevel, cwd });
3112
+ logger.success(`Merged "${upstream.name}" into the release commit and pushed`);
3113
+ }
3114
+ async function pushCommitAndTags({
3115
+ config,
3116
+ dryRun,
3117
+ logLevel,
3118
+ cwd,
3119
+ tags = []
3120
+ }) {
2997
3121
  logger.start("Start push changes and tags");
2998
3122
  const command = config.release.gitTag ? "git push --follow-tags" : "git push";
2999
3123
  if (dryRun) {
3000
3124
  logger.info(`[dry-run] ${command}`);
3001
3125
  } else {
3002
3126
  logger.debug(`Executing: ${command}`);
3003
- await execPromise(command, { noStderr: true, noStdout: true, logLevel, cwd });
3127
+ try {
3128
+ await execPromise(command, { noStderr: true, noStdout: true, noError: true, logLevel, cwd });
3129
+ } catch (error) {
3130
+ if (!isPushRejectedAsBehind(error)) {
3131
+ logger.error(`${command} failed`, error);
3132
+ throw error;
3133
+ }
3134
+ await recoverRejectedPush({ config, command, tags, pushError: error, logLevel, cwd });
3135
+ }
3004
3136
  }
3005
3137
  logger.success("Pushing changes and tags completed!");
3006
3138
  }
3139
+ function getReleaseTagNames({
3140
+ config,
3141
+ bumpedPackages,
3142
+ newVersion
3143
+ }) {
3144
+ if (!config.release.gitTag) {
3145
+ return [];
3146
+ }
3147
+ if (config.monorepo?.versionMode === "independent") {
3148
+ return (bumpedPackages ?? []).filter((pkg) => pkg.newVersion).map((pkg) => getIndependentTag({ name: pkg.name, version: pkg.newVersion }));
3149
+ }
3150
+ const version = newVersion || readPackageJson(config.cwd)?.version;
3151
+ const tagName = version ? config.templates.tagBody?.replaceAll("{{newVersion}}", version) : void 0;
3152
+ return tagName ? [tagName] : [];
3153
+ }
3154
+ async function assertReleaseTagsAvailable({ tags, cwd }) {
3155
+ for (const tag of tags) {
3156
+ if (!await tagExists(tag, cwd)) {
3157
+ continue;
3158
+ }
3159
+ if (await isAncestor(tag, "HEAD", cwd)) {
3160
+ throw new Error(`Tag "${tag}" already exists. Check the versions in your package.json files, they are behind the latest release.`);
3161
+ }
3162
+ throw new Error(
3163
+ `Tag "${tag}" already exists but is not part of the current branch history.
3164
+ A previous release most likely published this version and pushed its tag, but its release commit was never pushed to the branch.
3165
+ To recover, merge the release commit, then re-run the release: git fetch --tags && git merge ${tag} && git push`
3166
+ );
3167
+ }
3168
+ }
3007
3169
  async function rollbackModifiedFiles({
3008
3170
  config
3009
3171
  }) {
@@ -3310,14 +3472,16 @@ function resolveChangelogTags({
3310
3472
  }) {
3311
3473
  const isIndependent = config.monorepo?.versionMode === "independent";
3312
3474
  const gitFromRef = config.from || pkg.fromTag || getFirstCommit(config.cwd);
3313
- const isFirstCommit = gitFromRef === getFirstCommit(config.cwd);
3314
- const displayFromTag = isFirstCommit ? isIndependent ? getIndependentTag({ version: "0.0.0", name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", "0.0.0") : gitFromRef;
3475
+ const isNewPackage = gitFromRef === NEW_PACKAGE_MARKER;
3476
+ const isFirstCommit = !isNewPackage && gitFromRef === getFirstCommit(config.cwd);
3477
+ const displayFromTag = isFirstCommit || isNewPackage ? isIndependent ? getIndependentTag({ version: "0.0.0", name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", "0.0.0") : gitFromRef;
3478
+ const compareFromRef = isNewPackage ? getNewPackageCompareBase(pkg.path, config.cwd) : displayFromTag;
3315
3479
  const gitToRef = config.to || getCurrentGitRef(config.cwd);
3316
3480
  const displayToTag = config.to || (isIndependent ? getIndependentTag({ version: newVersion, name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", newVersion));
3317
3481
  if (!displayToTag) {
3318
3482
  throw new Error(`No tag found for ${pkg.name}`);
3319
3483
  }
3320
- return { gitFromRef, gitToRef, displayFromTag, displayToTag, isFirstCommit };
3484
+ return { gitFromRef, gitToRef, displayFromTag, displayToTag, compareFromRef, isFirstCommit };
3321
3485
  }
3322
3486
  function renderTitle({
3323
3487
  fromTag,
@@ -3333,6 +3497,7 @@ async function renderChangelogParts({
3333
3497
  config,
3334
3498
  fromTag,
3335
3499
  toTag,
3500
+ compareFromRef,
3336
3501
  isFirstCommit,
3337
3502
  sections,
3338
3503
  minify,
@@ -3342,8 +3507,8 @@ async function renderChangelogParts({
3342
3507
  if (sections.title) {
3343
3508
  parts.push(renderTitle({ fromTag, toTag, config }));
3344
3509
  }
3345
- if (sections.compareLink && !minify) {
3346
- const compareLink = buildCompareLink({ config, from: fromTag, to: toTag, isFirstCommit });
3510
+ if (sections.compareLink && !minify && compareFromRef) {
3511
+ const compareLink = buildCompareLink({ config, from: compareFromRef, to: toTag, isFirstCommit });
3347
3512
  if (compareLink) {
3348
3513
  parts.push(compareLink);
3349
3514
  }
@@ -3378,7 +3543,7 @@ async function generateChangelog({
3378
3543
  transformBody
3379
3544
  }) {
3380
3545
  const sections = resolveSections(include);
3381
- const { gitFromRef, gitToRef, displayFromTag, displayToTag, isFirstCommit } = resolveChangelogTags({ pkg, config, newVersion });
3546
+ const { gitFromRef, gitToRef, displayFromTag, displayToTag, compareFromRef, isFirstCommit } = resolveChangelogTags({ pkg, config, newVersion });
3382
3547
  logger.debug(`Generating changelog for ${pkg.name} - git ${gitFromRef}..${gitToRef} - display ${displayFromTag}...${displayToTag}`);
3383
3548
  try {
3384
3549
  const commits = await getPackageCommits({
@@ -3395,6 +3560,7 @@ async function generateChangelog({
3395
3560
  config: displayConfig,
3396
3561
  fromTag: displayFromTag,
3397
3562
  toTag: displayToTag,
3563
+ compareFromRef,
3398
3564
  isFirstCommit,
3399
3565
  sections,
3400
3566
  minify,
@@ -3738,13 +3904,13 @@ async function githubIndependentMode({
3738
3904
  if (!config.tokens.github && !config.repo?.token) {
3739
3905
  throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
3740
3906
  }
3741
- const packages = filterOutPrivatePackages(await getPackagesOrBumpedPackages({
3907
+ const packages = filterPrivatePackagesUnlessIncluded(await getPackagesOrBumpedPackages({
3742
3908
  config,
3743
3909
  bumpResult,
3744
3910
  suffix,
3745
3911
  force,
3746
3912
  dryRun
3747
- }));
3913
+ }), config.monorepo?.includePrivates);
3748
3914
  logger.info(`Creating ${packages.length} GitHub release(s)`);
3749
3915
  const postedReleases = [];
3750
3916
  for (const pkg of packages) {
@@ -3948,13 +4114,13 @@ async function gitlabIndependentMode({
3948
4114
  force
3949
4115
  }) {
3950
4116
  logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
3951
- const packages = filterOutPrivatePackages(await getPackagesOrBumpedPackages({
4117
+ const packages = filterPrivatePackagesUnlessIncluded(await getPackagesOrBumpedPackages({
3952
4118
  config,
3953
4119
  bumpResult,
3954
4120
  suffix,
3955
4121
  force,
3956
4122
  dryRun
3957
- }));
4123
+ }), config.monorepo?.includePrivates);
3958
4124
  logger.info(`Creating ${packages.length} GitLab release(s) for independent packages`);
3959
4125
  logger.debug("Getting current branch...");
3960
4126
  const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
@@ -5640,10 +5806,12 @@ function buildMetadataLines({
5640
5806
  branch
5641
5807
  }) {
5642
5808
  const lines = [];
5643
- const versionChanged = oldVersion && oldVersion !== version;
5644
- lines.push(
5645
- versionChanged ? `- **Version**: \`${oldVersion}\` \u2192 \`${version}\`` : `- **Version**: \`${version}\``
5646
- );
5809
+ if (version) {
5810
+ const versionChanged = oldVersion && oldVersion !== version;
5811
+ lines.push(
5812
+ versionChanged ? `- **Version**: \`${oldVersion}\` \u2192 \`${version}\`` : `- **Version**: \`${version}\``
5813
+ );
5814
+ }
5647
5815
  if (tags.length > 0) {
5648
5816
  lines.push(`- **Tag(s)**: ${formatTagsList(tags)}`);
5649
5817
  }
@@ -5691,7 +5859,7 @@ function buildInstallPackages({
5691
5859
  if (packages && packages.length > 0) {
5692
5860
  return packages.map((p) => `${p.name}@${p.version}`);
5693
5861
  }
5694
- if (rootPackageName) {
5862
+ if (rootPackageName && version) {
5695
5863
  return [`${rootPackageName}@${version}`];
5696
5864
  }
5697
5865
  return [];
@@ -5726,6 +5894,22 @@ function buildInstallLines({
5726
5894
  }
5727
5895
  return lines;
5728
5896
  }
5897
+ function buildPublishedInstallLines({
5898
+ config,
5899
+ bumpedPackages,
5900
+ packages,
5901
+ version,
5902
+ distTag
5903
+ }) {
5904
+ const publishedBumpedPackages = filterOutPrivatePackages(bumpedPackages);
5905
+ const publishedPackages = packages && filterOutPrivatePackages(packages);
5906
+ const hasNoPackages = bumpedPackages.length === 0 && !packages?.length;
5907
+ const rootPackageName = hasNoPackages ? config.projectName : void 0;
5908
+ const installCmd = getInstallCommand(config.publish?.packageManager);
5909
+ const installPkgs = buildInstallPackages({ bumpedPackages: publishedBumpedPackages, packages: publishedPackages, version, rootPackageName });
5910
+ const pkgNames = resolvePackageNames(publishedBumpedPackages, publishedPackages, rootPackageName);
5911
+ return buildInstallLines({ installCmd, installPkgs, distTag, pkgNames });
5912
+ }
5729
5913
  function buildSuccessComment({
5730
5914
  config,
5731
5915
  branch,
@@ -5735,11 +5919,15 @@ function buildSuccessComment({
5735
5919
  rootVersion
5736
5920
  }) {
5737
5921
  const bumpResult = releaseContext?.bumpResult;
5738
- const bumpedPackages = filterOutPrivatePackages(bumpResult?.bumpedPackages ?? []);
5739
- const version = bumpResult?.newVersion ?? rootVersion ?? "unknown";
5922
+ const includePrivates = config.monorepo?.includePrivates;
5923
+ const allBumpedPackages = bumpResult?.bumpedPackages ?? [];
5924
+ const bumpedPackages = filterPrivatePackagesUnlessIncluded(allBumpedPackages, includePrivates);
5925
+ const listedPackages = packages && filterPrivatePackagesUnlessIncluded(packages, includePrivates);
5926
+ const isIndependent = config.monorepo?.versionMode === "independent";
5927
+ const version = isIndependent ? void 0 : bumpResult?.newVersion ?? rootVersion;
5740
5928
  const tags = releaseContext?.tags ?? [];
5741
- const distTag = config.publish?.tag;
5742
- const installCmd = getInstallCommand(config.publish?.packageManager);
5929
+ const isPublishing = config.release.publish !== false;
5930
+ const distTag = isPublishing ? config.publish?.tag : void 0;
5743
5931
  const lines = [PR_COMMENT_MARKER, "", "## \u{1F680} Release published", ""];
5744
5932
  const previousVersion = extractVersionFromTag(bumpResult?.fromTag ?? "") || bumpResult?.oldVersion;
5745
5933
  lines.push(...buildMetadataLines({
@@ -5750,10 +5938,10 @@ function buildSuccessComment({
5750
5938
  date,
5751
5939
  branch
5752
5940
  }));
5753
- lines.push(...buildPackageTableLines(bumpedPackages, packages));
5754
- const installPkgs = buildInstallPackages({ bumpedPackages, packages, version, rootPackageName: config.projectName });
5755
- const pkgNames = resolvePackageNames(bumpedPackages, packages, config.projectName);
5756
- lines.push(...buildInstallLines({ installCmd, installPkgs, distTag, pkgNames }));
5941
+ lines.push(...buildPackageTableLines(bumpedPackages, listedPackages));
5942
+ if (isPublishing) {
5943
+ lines.push(...buildPublishedInstallLines({ config, bumpedPackages: allBumpedPackages, packages, version, distTag }));
5944
+ }
5757
5945
  return lines.join("\n");
5758
5946
  }
5759
5947
  function buildNoReleaseComment({ branch, date }) {
@@ -5811,21 +5999,21 @@ async function prComment(options = {}) {
5811
5999
  const branch = getCurrentGitBranch(config.cwd) ?? "unknown";
5812
6000
  const date = getFormattedDate();
5813
6001
  let packages = [];
5814
- let rootVersion = "unknown";
6002
+ let rootVersion;
5815
6003
  if (!options.releaseContext) {
5816
6004
  const rootPackage = readPackageJson(config.cwd);
5817
6005
  if (!rootPackage) {
5818
6006
  throw new Error("Failed to read root package.json");
5819
6007
  }
5820
6008
  rootVersion = rootPackage.version;
5821
- const readPkgs = filterOutPrivatePackages(readPackages({
6009
+ const readPkgs = readPackages({
5822
6010
  cwd: config.cwd,
5823
6011
  patterns: config.monorepo?.packages,
5824
6012
  ignorePackageNames: config.monorepo?.ignorePackageNames,
5825
6013
  ignored: config.monorepo?.ignored,
5826
6014
  includePrivates: config.monorepo?.includePrivates
5827
- }));
5828
- packages = readPkgs.map((pkg) => ({ name: pkg.name, version: pkg.version }));
6015
+ });
6016
+ packages = readPkgs.map((pkg) => ({ name: pkg.name, version: pkg.version, private: pkg.private }));
5829
6017
  }
5830
6018
  const body = buildCommentBody({
5831
6019
  config,
@@ -6678,6 +6866,20 @@ function getReleaseConfig(options = {}) {
6678
6866
  }
6679
6867
  });
6680
6868
  }
6869
+ function shouldPushReleaseCommit(config) {
6870
+ return Boolean(config.release.push && config.release.commit);
6871
+ }
6872
+ async function guardBeforePublish({ config, dryRun, guard }) {
6873
+ try {
6874
+ await guard();
6875
+ } catch (error) {
6876
+ if (!dryRun) {
6877
+ logger.fail("Release aborted before publishing, rolling back modified files...");
6878
+ await rollbackModifiedFiles({ config });
6879
+ }
6880
+ throw error;
6881
+ }
6882
+ }
6681
6883
  async function releaseSafetyCheck({
6682
6884
  config,
6683
6885
  provider
@@ -6691,7 +6893,8 @@ async function releaseSafetyCheck({
6691
6893
  await Promise.all([
6692
6894
  providerReleaseSafetyCheck({ config, provider }),
6693
6895
  publishSafetyCheck({ config }),
6694
- socialSafetyCheck({ config })
6896
+ socialSafetyCheck({ config }),
6897
+ ...shouldPushReleaseCommit(config) ? [assertBranchUpToDateWithRemote({ cwd: config.cwd })] : []
6695
6898
  ]);
6696
6899
  logger.success("Safety checks passed");
6697
6900
  } catch (error) {
@@ -6800,6 +7003,16 @@ async function release(options = {}) {
6800
7003
  });
6801
7004
  return;
6802
7005
  }
7006
+ if (config.release.commit) {
7007
+ await guardBeforePublish({
7008
+ config,
7009
+ dryRun,
7010
+ guard: () => assertReleaseTagsAvailable({
7011
+ tags: getReleaseTagNames({ config, bumpedPackages: bumpResult.bumpedPackages, newVersion: bumpResult.newVersion }),
7012
+ cwd: config.cwd
7013
+ })
7014
+ });
7015
+ }
6803
7016
  logger.box("Generate changelogs");
6804
7017
  if (config.release.changelog) {
6805
7018
  await changelog({
@@ -6819,6 +7032,13 @@ async function release(options = {}) {
6819
7032
  } else {
6820
7033
  logger.info("Skipping changelog generation (--no-changelog)");
6821
7034
  }
7035
+ if (shouldPushReleaseCommit(config)) {
7036
+ await guardBeforePublish({
7037
+ config,
7038
+ dryRun,
7039
+ guard: () => assertBranchUpToDateWithRemote({ cwd: config.cwd })
7040
+ });
7041
+ }
6822
7042
  logger.box("Publish packages to registry");
6823
7043
  let publishResponse;
6824
7044
  if (config.release.publish) {
@@ -6870,7 +7090,8 @@ async function release(options = {}) {
6870
7090
  config,
6871
7091
  dryRun,
6872
7092
  logLevel: config.logLevel,
6873
- cwd: config.cwd
7093
+ cwd: config.cwd,
7094
+ tags: createdTags
6874
7095
  });
6875
7096
  await executeHook("success:push", config, dryRun);
6876
7097
  } catch (error) {
@@ -6963,4 +7184,4 @@ async function release(options = {}) {
6963
7184
  }
6964
7185
  }
6965
7186
 
6966
- export { getGitDiff as $, extractVersionFromPackageTag as A, extractVersionFromTag as B, fetchGitTags as C, filterOutPrivatePackages as D, findGitHubPR as E, findGitLabMR as F, findReachableCommitBySubject as G, formatChangelogForSlack as H, formatPackagesForSlack as I, formatSlackMessage as J, formatTweetMessage as K, generateChangelog as L, generateMarkDown as M, NEW_PACKAGE_MARKER as N, getAuthCommand as O, PR_COMMENT_MARKER as P, getBumpedIndependentPackages as Q, getBumpedPackageIndependently as R, getCIName as S, getCanaryVersion as T, getCommitChangedFiles as U, getCommitSubject as V, getCurrentGitBranch as W, getCurrentGitRef as X, getDefaultConfig as Y, getDependentsOf as Z, getFirstCommit as _, buildCommentBody as a, resolveRegistryTargetsForPackages as a$, getGitStatus as a0, getIndependentTag as a1, getLastPackageTag as a2, getLastRepoTag as a3, getLastStableTag as a4, getLastTag as a5, getModifiedReleaseFilePatterns as a6, getNpmRegistry as a7, getPackageCommits as a8, getPackageDependencies as a9, isTagVersionCompatibleWithCurrent as aA, isVersionAlreadyPublishedError as aB, isVersionPublished as aC, loadRelizyConfig as aD, mergeTypes as aE, parseChangelogMarkdown as aF, parseGitRemoteUrl as aG, postPrComment as aH, postReleaseToSlack as aI, postReleaseToTwitter as aJ, prComment as aK, providerRelease as aL, providerReleaseSafetyCheck as aM, publish as aN, publishPackage as aO, publishSafetyCheck as aP, pushCommitAndTags as aQ, pushTagForce as aR, readPackageJson as aS, readPackages as aT, reconcileFromTag as aU, redactSecrets as aV, release as aW, resetRewrittenTagCache as aX, resolveAllConfiguredRegistryTargets as aY, resolveIgnoredPackagePaths as aZ, resolveRegistryTargetsForPackage as a_, getPackageNewVersion as aa, getPackages as ab, getPackagesOrBumpedPackages as ac, getPackagesToPublishInIndependentMode as ad, getPackagesToPublishInSelectiveMode as ae, getPreid as af, getReleaseUrl as ag, getRootPackage as ah, getShortCommitSha as ai, getSlackToken as aj, getSlackWebhookUrl as ak, getTwitterCredentials as al, github as am, gitlab as an, globDirsAbsolute as ao, hasLernaJson as ap, isAncestor as aq, isBumpedPackage as ar, isChangedPreid as as, isCommitOnlyInIgnoredPackages as at, isGraduating as au, isGraduatingToStableBetweenVersion as av, isInCI as aw, isPrerelease as ax, isPrereleaseReleaseType as ay, isStableReleaseType as az, buildChangelogBody as b, resolveTags as b0, retagAnnotatedLocal as b1, rollbackModifiedFiles as b2, shouldFilterPrereleaseTags as b3, social as b4, socialSafetyCheck as b5, tagExists as b6, topologicalSort as b7, tryPostPrComment as b8, updateLernaVersion as b9, withRegistryNpmrc as ba, writeChangelogToFile as bb, writeVersion as bc, buildCompareLink as c, buildContributors as d, buildReleaseSummary as e, bump as f, capReleaseTypeForZeroMajor as g, changelog as h, checkGitStatusIfDirty as i, collectContributorNames as j, collectPackageBumps as k, confirmBump as l, createCommitAndTags as m, createGitlabRelease as n, defineConfig as o, detectGitProvider as p, detectPackageManager as q, detectPullRequest as r, determinePublishTag as s, determineReleaseType as t, determineSemverChange as u, executeBuildCmd as v, executeFormatCmd as w, executeHook as x, expandPackagesToBumpWithDependents as y, extractChangelogSummary as z };
7187
+ export { getDefaultConfig as $, expandPackagesToBumpWithDependents as A, extractChangelogSummary as B, extractVersionFromPackageTag as C, extractVersionFromTag as D, fetchGitTags as E, filterOutPrivatePackages as F, filterPrivatePackagesUnlessIncluded as G, findGitHubPR as H, findGitLabMR as I, findReachableCommitBySubject as J, formatChangelogForSlack as K, formatPackagesForSlack as L, formatSlackMessage as M, NEW_PACKAGE_MARKER as N, formatTweetMessage as O, PR_COMMENT_MARKER as P, generateChangelog as Q, generateMarkDown as R, getAuthCommand as S, getBumpedIndependentPackages as T, getBumpedPackageIndependently as U, getCIName as V, getCanaryVersion as W, getCommitChangedFiles as X, getCommitSubject as Y, getCurrentGitBranch as Z, getCurrentGitRef as _, assertBranchUpToDateWithRemote as a, redactSecrets as a$, getDependentsOf as a0, getFirstCommit as a1, getGitDiff as a2, getGitStatus as a3, getGitUpstream as a4, getIndependentTag as a5, getLastPackageTag as a6, getLastRepoTag as a7, getLastStableTag as a8, getLastTag as a9, isGraduating as aA, isGraduatingToStableBetweenVersion as aB, isInCI as aC, isPrerelease as aD, isPrereleaseReleaseType as aE, isStableReleaseType as aF, isTagVersionCompatibleWithCurrent as aG, isVersionAlreadyPublishedError as aH, isVersionPublished as aI, loadRelizyConfig as aJ, mergeTypes as aK, parseChangelogMarkdown as aL, parseGitRemoteUrl as aM, postPrComment as aN, postReleaseToSlack as aO, postReleaseToTwitter as aP, prComment as aQ, providerRelease as aR, providerReleaseSafetyCheck as aS, publish as aT, publishPackage as aU, publishSafetyCheck as aV, pushCommitAndTags as aW, pushTagForce as aX, readPackageJson as aY, readPackages as aZ, reconcileFromTag as a_, getModifiedReleaseFilePatterns as aa, getNewPackageCompareBase as ab, getNpmRegistry as ac, getPackageCommits as ad, getPackageDependencies as ae, getPackageNewVersion as af, getPackages as ag, getPackagesOrBumpedPackages as ah, getPackagesToPublishInIndependentMode as ai, getPackagesToPublishInSelectiveMode as aj, getPreid as ak, getReleaseTagNames as al, getReleaseUrl as am, getRootPackage as an, getShortCommitSha as ao, getSlackToken as ap, getSlackWebhookUrl as aq, getTwitterCredentials as ar, github as as, gitlab as at, globDirsAbsolute as au, hasLernaJson as av, isAncestor as aw, isBumpedPackage as ax, isChangedPreid as ay, isCommitOnlyInIgnoredPackages as az, assertReleaseTagsAvailable as b, release as b0, resetRewrittenTagCache as b1, resolveAllConfiguredRegistryTargets as b2, resolveIgnoredPackagePaths as b3, resolveRegistryTargetsForPackage as b4, resolveRegistryTargetsForPackages as b5, resolveTags as b6, retagAnnotatedLocal as b7, rollbackModifiedFiles as b8, shouldFilterPrereleaseTags as b9, social as ba, socialSafetyCheck as bb, tagExists as bc, topologicalSort as bd, tryPostPrComment as be, updateLernaVersion as bf, withRegistryNpmrc as bg, writeChangelogToFile as bh, writeVersion as bi, buildChangelogBody as c, buildCommentBody as d, buildCompareLink as e, buildContributors as f, buildReleaseSummary as g, bump as h, capReleaseTypeForZeroMajor as i, changelog as j, checkGitStatusIfDirty as k, collectContributorNames as l, collectPackageBumps as m, confirmBump as n, createCommitAndTags as o, createGitlabRelease as p, defineConfig as q, detectGitProvider as r, detectPackageManager as s, detectPullRequest as t, determinePublishTag as u, determineReleaseType as v, determineSemverChange as w, executeBuildCmd as x, executeFormatCmd as y, executeHook as z };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "relizy",
3
3
  "type": "module",
4
- "version": "1.5.1",
4
+ "version": "1.7.0-beta.0",
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",