@releasekit/release 0.7.48 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24913,7 +24913,7 @@ var init_aggregator_IUQUAVJC = __esm({
24913
24913
  }
24914
24914
  });
24915
24915
 
24916
- // ../notes/dist/chunk-Y4S5UWCL.js
24916
+ // ../notes/dist/chunk-5B2RYLOK.js
24917
24917
  import * as TOML from "smol-toml";
24918
24918
  import * as fs32 from "fs";
24919
24919
  import * as path32 from "path";
@@ -26245,8 +26245,8 @@ function handleError(err) {
26245
26245
  process.exit(EXIT_CODES2.GENERAL_ERROR);
26246
26246
  }
26247
26247
  var import_handlebars, ConfigError, MAX_JSONC_LENGTH, GitConfigSchema, MonorepoConfigSchema, BranchPatternSchema, VersionCargoConfigSchema, VersionConfigSchema, NpmConfigSchema, CargoPublishConfigSchema, PublishGitConfigSchema, GitHubReleaseConfigSchema, VerifyRegistryConfigSchema, VerifyConfigSchema, PublishConfigSchema, TemplateConfigSchema, LocationModeSchema, ChangelogConfigSchema, LLMOptionsSchema, LLMRetryConfigSchema, LLMTasksConfigSchema, LLMCategorySchema, ScopeRulesSchema, ScopeConfigSchema, LLMPromptOverridesSchema, LLMPromptsConfigSchema, LLMConfigSchema, ReleaseNotesConfigSchema, NotesInputConfigSchema, NotesConfigSchema, CILabelsConfigSchema, CIConfigSchema, ReleaseCIConfigSchema, ReleaseConfigSchema, ReleaseKitConfigSchema, MAX_INPUT_LENGTH, SOLE_REFERENCE_PATTERN, AUTH_DIR, AUTH_FILE, CONFIG_FILE, NotesError, InputParseError, TemplateError, LLMError, GitHubError, ConfigError2, LLM_DEFAULTS, BaseLLMProvider, AnthropicProvider, OllamaProvider, OpenAIProvider, OpenAICompatibleProvider, DEFAULT_CATEGORIZE_PROMPT, DEFAULT_ENHANCE_PROMPT, DEFAULT_RELEASE_NOTES_PROMPT, DEFAULT_SUMMARIZE_PROMPT;
26248
- var init_chunk_Y4S5UWCL = __esm({
26249
- "../notes/dist/chunk-Y4S5UWCL.js"() {
26248
+ var init_chunk_5B2RYLOK = __esm({
26249
+ "../notes/dist/chunk-5B2RYLOK.js"() {
26250
26250
  "use strict";
26251
26251
  init_chunk_7TJSPQPW();
26252
26252
  init_sdk();
@@ -26528,7 +26528,18 @@ var init_chunk_Y4S5UWCL = __esm({
26528
26528
  major: "release:major",
26529
26529
  minor: "release:minor",
26530
26530
  patch: "release:patch"
26531
- })
26531
+ }),
26532
+ /**
26533
+ * Map of scope labels to package patterns.
26534
+ * When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
26535
+ */
26536
+ scopeLabels: z.record(z.string(), z.string()).optional(),
26537
+ /**
26538
+ * Default scope to use when no scope label is found on the merged PR.
26539
+ * Must reference a key from scopeLabels (e.g., "scope:shared").
26540
+ * Only applies when scopeLabels is configured.
26541
+ */
26542
+ defaultScope: z.string().optional()
26532
26543
  });
26533
26544
  ReleaseCIConfigSchema = z.object({
26534
26545
  skipPatterns: z.array(z.string().min(1)).optional(),
@@ -26910,7 +26921,7 @@ function writeJson(outputPath, contexts, dryRun) {
26910
26921
  var init_dist = __esm({
26911
26922
  "../notes/dist/index.js"() {
26912
26923
  "use strict";
26913
- init_chunk_Y4S5UWCL();
26924
+ init_chunk_5B2RYLOK();
26914
26925
  init_chunk_F7MUVHZ2();
26915
26926
  init_chunk_7TJSPQPW();
26916
26927
  }
@@ -28846,7 +28857,7 @@ var require_semver2 = __commonJS({
28846
28857
  }
28847
28858
  });
28848
28859
 
28849
- // ../publish/dist/chunk-OZHNJUFW.js
28860
+ // ../publish/dist/chunk-UARK5H2F.js
28850
28861
  import chalk3 from "chalk";
28851
28862
  import * as fs23 from "fs";
28852
28863
  import * as TOML2 from "smol-toml";
@@ -30383,8 +30394,8 @@ function createPublishCommand() {
30383
30394
  });
30384
30395
  }
30385
30396
  var import_semver, LOG_LEVELS3, PREFIXES3, COLORS3, currentLevel3, quietMode3, ReleaseKitError3, EXIT_CODES3, ConfigError3, MAX_JSONC_LENGTH2, GitConfigSchema2, MonorepoConfigSchema2, BranchPatternSchema2, VersionCargoConfigSchema2, VersionConfigSchema2, NpmConfigSchema2, CargoPublishConfigSchema2, PublishGitConfigSchema2, GitHubReleaseConfigSchema2, VerifyRegistryConfigSchema2, VerifyConfigSchema2, PublishConfigSchema2, TemplateConfigSchema2, LocationModeSchema2, ChangelogConfigSchema2, LLMOptionsSchema2, LLMRetryConfigSchema2, LLMTasksConfigSchema2, LLMCategorySchema2, ScopeRulesSchema2, ScopeConfigSchema2, LLMPromptOverridesSchema2, LLMPromptsConfigSchema2, LLMConfigSchema2, ReleaseNotesConfigSchema2, NotesInputConfigSchema2, NotesConfigSchema2, CILabelsConfigSchema2, CIConfigSchema2, ReleaseCIConfigSchema2, ReleaseConfigSchema2, ReleaseKitConfigSchema2, MAX_INPUT_LENGTH2, SOLE_REFERENCE_PATTERN2, AUTH_DIR2, AUTH_FILE2, CONFIG_FILE2, BasePublishError, PublishError, PipelineError, PublishErrorCode, VersionChangelogEntrySchema, VersionPackageChangelogSchema, VersionPackageUpdateSchema, VersionOutputSchema;
30386
- var init_chunk_OZHNJUFW = __esm({
30387
- "../publish/dist/chunk-OZHNJUFW.js"() {
30397
+ var init_chunk_UARK5H2F = __esm({
30398
+ "../publish/dist/chunk-UARK5H2F.js"() {
30388
30399
  "use strict";
30389
30400
  import_semver = __toESM(require_semver2(), 1);
30390
30401
  LOG_LEVELS3 = {
@@ -30713,7 +30724,18 @@ var init_chunk_OZHNJUFW = __esm({
30713
30724
  major: "release:major",
30714
30725
  minor: "release:minor",
30715
30726
  patch: "release:patch"
30716
- })
30727
+ }),
30728
+ /**
30729
+ * Map of scope labels to package patterns.
30730
+ * When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
30731
+ */
30732
+ scopeLabels: z3.record(z3.string(), z3.string()).optional(),
30733
+ /**
30734
+ * Default scope to use when no scope label is found on the merged PR.
30735
+ * Must reference a key from scopeLabels (e.g., "scope:shared").
30736
+ * Only applies when scopeLabels is configured.
30737
+ */
30738
+ defaultScope: z3.string().optional()
30717
30739
  });
30718
30740
  ReleaseCIConfigSchema2 = z3.object({
30719
30741
  skipPatterns: z3.array(z3.string().min(1)).optional(),
@@ -30846,7 +30868,7 @@ __export(dist_exports2, {
30846
30868
  var init_dist2 = __esm({
30847
30869
  "../publish/dist/index.js"() {
30848
30870
  "use strict";
30849
- init_chunk_OZHNJUFW();
30871
+ init_chunk_UARK5H2F();
30850
30872
  }
30851
30873
  });
30852
30874
 
@@ -43388,7 +43410,7 @@ var init_baseError_DQHIJACF = __esm({
43388
43410
  }
43389
43411
  });
43390
43412
 
43391
- // ../version/dist/chunk-UBCKZYTO.js
43413
+ // ../version/dist/chunk-GHCENMVA.js
43392
43414
  import * as fs15 from "fs";
43393
43415
  import * as path17 from "path";
43394
43416
  import * as TOML3 from "smol-toml";
@@ -45177,8 +45199,8 @@ function createVersionCommand() {
45177
45199
  });
45178
45200
  }
45179
45201
  var import_semver4, import_semver5, import_semver6, ConfigError4, MAX_JSONC_LENGTH3, GitConfigSchema3, MonorepoConfigSchema3, BranchPatternSchema3, VersionCargoConfigSchema3, VersionConfigSchema3, NpmConfigSchema3, CargoPublishConfigSchema3, PublishGitConfigSchema3, GitHubReleaseConfigSchema3, VerifyRegistryConfigSchema3, VerifyConfigSchema3, PublishConfigSchema3, TemplateConfigSchema3, LocationModeSchema3, ChangelogConfigSchema3, LLMOptionsSchema3, LLMRetryConfigSchema3, LLMTasksConfigSchema3, LLMCategorySchema3, ScopeRulesSchema3, ScopeConfigSchema3, LLMPromptOverridesSchema3, LLMPromptsConfigSchema3, LLMConfigSchema3, ReleaseNotesConfigSchema3, NotesInputConfigSchema3, NotesConfigSchema3, CILabelsConfigSchema3, CIConfigSchema3, ReleaseCIConfigSchema3, ReleaseConfigSchema3, ReleaseKitConfigSchema3, MAX_INPUT_LENGTH3, SOLE_REFERENCE_PATTERN3, AUTH_DIR3, AUTH_FILE3, CONFIG_FILE3, VersionError, VersionErrorCode, _jsonOutputMode, _pendingWrites, _jsonData, STANDARD_BUMP_TYPES, VersionMismatchError, CONVENTIONAL_COMMIT_REGEX, BREAKING_CHANGE_REGEX, PackageProcessor, GitError, VersionEngine;
45180
- var init_chunk_UBCKZYTO = __esm({
45181
- "../version/dist/chunk-UBCKZYTO.js"() {
45202
+ var init_chunk_GHCENMVA = __esm({
45203
+ "../version/dist/chunk-GHCENMVA.js"() {
45182
45204
  "use strict";
45183
45205
  init_chunk_Q3FHZORY();
45184
45206
  init_chunk_LMPZV35Z();
@@ -45464,7 +45486,18 @@ var init_chunk_UBCKZYTO = __esm({
45464
45486
  major: "release:major",
45465
45487
  minor: "release:minor",
45466
45488
  patch: "release:patch"
45467
- })
45489
+ }),
45490
+ /**
45491
+ * Map of scope labels to package patterns.
45492
+ * When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
45493
+ */
45494
+ scopeLabels: z4.record(z4.string(), z4.string()).optional(),
45495
+ /**
45496
+ * Default scope to use when no scope label is found on the merged PR.
45497
+ * Must reference a key from scopeLabels (e.g., "scope:shared").
45498
+ * Only applies when scopeLabels is configured.
45499
+ */
45500
+ defaultScope: z4.string().optional()
45468
45501
  });
45469
45502
  ReleaseCIConfigSchema3 = z4.object({
45470
45503
  skipPatterns: z4.array(z4.string().min(1)).optional(),
@@ -45919,7 +45952,7 @@ __export(dist_exports5, {
45919
45952
  var init_dist15 = __esm({
45920
45953
  "../version/dist/index.js"() {
45921
45954
  "use strict";
45922
- init_chunk_UBCKZYTO();
45955
+ init_chunk_GHCENMVA();
45923
45956
  init_chunk_Q3FHZORY();
45924
45957
  init_chunk_LMPZV35Z();
45925
45958
  }
@@ -46379,7 +46412,18 @@ var CIConfigSchema4 = z5.object({
46379
46412
  major: "release:major",
46380
46413
  minor: "release:minor",
46381
46414
  patch: "release:patch"
46382
- })
46415
+ }),
46416
+ /**
46417
+ * Map of scope labels to package patterns.
46418
+ * When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
46419
+ */
46420
+ scopeLabels: z5.record(z5.string(), z5.string()).optional(),
46421
+ /**
46422
+ * Default scope to use when no scope label is found on the merged PR.
46423
+ * Must reference a key from scopeLabels (e.g., "scope:shared").
46424
+ * Only applies when scopeLabels is configured.
46425
+ */
46426
+ defaultScope: z5.string().optional()
46383
46427
  });
46384
46428
  var ReleaseCIConfigSchema4 = z5.object({
46385
46429
  skipPatterns: z5.array(z5.string().min(1)).optional(),
@@ -46482,6 +46526,34 @@ function loadCIConfig(options) {
46482
46526
  return config.ci;
46483
46527
  }
46484
46528
 
46529
+ // src/label-utils.ts
46530
+ var DEFAULT_LABELS = {
46531
+ stable: "release:stable",
46532
+ prerelease: "release:prerelease",
46533
+ skip: "release:skip",
46534
+ major: "release:major",
46535
+ minor: "release:minor",
46536
+ patch: "release:patch"
46537
+ };
46538
+ function detectLabelConflicts(prLabels, labels = DEFAULT_LABELS) {
46539
+ const bumpLabelsPresent = [
46540
+ prLabels.includes(labels.major) && "major",
46541
+ prLabels.includes(labels.minor) && "minor",
46542
+ prLabels.includes(labels.patch) && "patch"
46543
+ ].filter(Boolean);
46544
+ const bumpConflict = bumpLabelsPresent.length > 1;
46545
+ const hasStable = prLabels.includes(labels.stable);
46546
+ const hasPrerelease = prLabels.includes(labels.prerelease);
46547
+ const prereleaseConflict = hasStable && hasPrerelease;
46548
+ return {
46549
+ bumpConflict,
46550
+ bumpLabelsPresent,
46551
+ prereleaseConflict,
46552
+ hasStable,
46553
+ hasPrerelease
46554
+ };
46555
+ }
46556
+
46485
46557
  // src/preview-context.ts
46486
46558
  import * as fs17 from "fs";
46487
46559
  function resolvePreviewContext(opts) {
@@ -46598,25 +46670,54 @@ function getIntroMessage(strategy, standingPrNumber) {
46598
46670
  }
46599
46671
  function getLabelBanner(labelContext) {
46600
46672
  if (!labelContext) return [];
46673
+ const lines = [];
46674
+ if (labelContext.scopeLabels && labelContext.scopeLabels.length > 0) {
46675
+ lines.push(`> **Scope:** ${labelContext.scopeLabels.join(", ")}`, "");
46676
+ }
46601
46677
  if (labelContext.trigger === "commit") {
46602
46678
  if (labelContext.skip) {
46603
- return ["> **Warning:** This PR is marked to skip release.", ""];
46679
+ lines.push("> **Warning:** This PR is marked to skip release.", "");
46680
+ return lines;
46604
46681
  }
46605
46682
  if (labelContext.bumpLabel === "major") {
46606
- return ["> **Important:** This PR is labeled for a **major** release.", ""];
46607
- }
46683
+ lines.push("> **Important:** This PR is labeled for a **major** release.", "");
46684
+ return lines;
46685
+ }
46686
+ }
46687
+ if (labelContext.prereleaseConflict) {
46688
+ const labels = labelContext.labels;
46689
+ const stableLabel = labels?.stable ?? "release:stable";
46690
+ const prereleaseLabel = labels?.prerelease ?? "release:prerelease";
46691
+ lines.push(
46692
+ "> **Error:** Conflicting release type labels detected.",
46693
+ `> **Note:** Please use only one of \`${stableLabel}\` or \`${prereleaseLabel}\` at a time.`,
46694
+ ""
46695
+ );
46696
+ return lines;
46608
46697
  }
46609
46698
  if (labelContext.trigger === "label") {
46699
+ if (labelContext.bumpConflict) {
46700
+ const labels = labelContext.labels;
46701
+ const labelExamples = labels ? `\`${labels.patch}\`, \`${labels.minor}\`, or \`${labels.major}\`` : "a release label (e.g., `release:patch`, `release:minor`, `release:major`)";
46702
+ lines.push(
46703
+ "> **Error:** Conflicting bump labels detected.",
46704
+ `> **Note:** Please use only one release label at a time. Use ${labelExamples}.`,
46705
+ ""
46706
+ );
46707
+ return lines;
46708
+ }
46610
46709
  if (labelContext.noBumpLabel) {
46611
46710
  const labels = labelContext.labels;
46612
46711
  const labelExamples = labels ? `\`${labels.patch}\`, \`${labels.minor}\`, or \`${labels.major}\`` : "a release label (e.g., `release:patch`, `release:minor`, `release:major`)";
46613
- return ["> No release label detected.", `> **Note:** Add ${labelExamples} to trigger a release.`, ""];
46712
+ lines.push("> No release label detected.", `> **Note:** Add ${labelExamples} to trigger a release.`, "");
46713
+ return lines;
46614
46714
  }
46615
46715
  if (labelContext.bumpLabel) {
46616
- return [`> This PR is labeled for a **${labelContext.bumpLabel}** release.`, ""];
46716
+ lines.push(`> This PR is labeled for a **${labelContext.bumpLabel}** release.`, "");
46717
+ return lines;
46617
46718
  }
46618
46719
  }
46619
- return [];
46720
+ return lines;
46620
46721
  }
46621
46722
  function formatPreviewComment(result, options) {
46622
46723
  const strategy = options?.strategy ?? "direct";
@@ -46725,6 +46826,18 @@ import { Octokit } from "@octokit/rest";
46725
46826
  function createOctokit(token) {
46726
46827
  return new Octokit({ auth: token });
46727
46828
  }
46829
+ async function findMergedPRsForCommit(octokit, owner, repo, commitSha) {
46830
+ try {
46831
+ const { data: prs } = await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
46832
+ owner,
46833
+ repo,
46834
+ commit_sha: commitSha
46835
+ });
46836
+ return prs.filter((pr) => pr.merged_at !== null).map((pr) => pr.number);
46837
+ } catch {
46838
+ return [];
46839
+ }
46840
+ }
46728
46841
  async function findPreviewComment(octokit, owner, repo, prNumber) {
46729
46842
  const iterator = octokit.paginate.iterator(octokit.rest.issues.listComments, {
46730
46843
  owner,
@@ -46777,6 +46890,82 @@ function getHeadCommitMessage(cwd3) {
46777
46890
  return null;
46778
46891
  }
46779
46892
  }
46893
+ function getGitHubContext() {
46894
+ const repo = process.env.GITHUB_REPOSITORY;
46895
+ const sha = process.env.GITHUB_SHA;
46896
+ if (!repo || !sha) {
46897
+ return null;
46898
+ }
46899
+ const [owner, repoName] = repo.split("/");
46900
+ if (!owner || !repoName) {
46901
+ return null;
46902
+ }
46903
+ return { owner, repo: repoName, sha };
46904
+ }
46905
+ async function applyScopeLabelsFromPR(ciConfig, options) {
46906
+ const scopeLabels = ciConfig?.scopeLabels ?? {};
46907
+ const defaultScope = ciConfig?.defaultScope;
46908
+ const githubContext = getGitHubContext();
46909
+ if (!githubContext) {
46910
+ return { target: options.target, scopeLabels: [], labels: [] };
46911
+ }
46912
+ const token = process.env.GITHUB_TOKEN;
46913
+ if (!token) {
46914
+ warn("No GITHUB_TOKEN available \u2014 skipping scope label detection");
46915
+ return { target: options.target, scopeLabels: [], labels: [] };
46916
+ }
46917
+ const octokit = createOctokit(token);
46918
+ const prNumbers = await findMergedPRsForCommit(octokit, githubContext.owner, githubContext.repo, githubContext.sha);
46919
+ const allLabels = [];
46920
+ const perPRLabels = /* @__PURE__ */ new Map();
46921
+ for (const prNumber of prNumbers) {
46922
+ const labels = await fetchPRLabels(octokit, githubContext.owner, githubContext.repo, prNumber);
46923
+ allLabels.push(...labels);
46924
+ perPRLabels.set(prNumber, labels);
46925
+ }
46926
+ for (const [prNumber, labels] of perPRLabels) {
46927
+ const conflict = detectLabelConflicts(labels, ciConfig?.labels ?? DEFAULT_LABELS);
46928
+ if (conflict.prereleaseConflict) {
46929
+ warn(
46930
+ `PR #${prNumber} has conflicting labels "${ciConfig?.labels?.stable ?? "release:stable"}" and "${ciConfig?.labels?.prerelease ?? "release:prerelease"}" \u2014 release blocked`
46931
+ );
46932
+ return { target: options.target, scopeLabels: [], labels: [], blocked: true };
46933
+ }
46934
+ if (conflict.bumpConflict && (ciConfig?.releaseTrigger ?? "label") === "label") {
46935
+ warn(`PR #${prNumber} has conflicting bump labels (${conflict.bumpLabelsPresent.join(", ")}) \u2014 release blocked`);
46936
+ return { target: options.target, scopeLabels: [], labels: [], blocked: true };
46937
+ }
46938
+ }
46939
+ if (prNumbers.length === 0) {
46940
+ if (defaultScope && Object.keys(scopeLabels).length > 0) {
46941
+ const defaultPattern = scopeLabels[defaultScope];
46942
+ if (defaultPattern) {
46943
+ info(`No merged PRs found \u2014 using default scope "${defaultScope}" (${defaultPattern})`);
46944
+ return { target: defaultPattern, scopeLabels: [], labels: allLabels };
46945
+ }
46946
+ }
46947
+ info("No merged PRs found for HEAD commit \u2014 releasing all packages");
46948
+ return { target: options.target, scopeLabels: [], labels: allLabels };
46949
+ }
46950
+ const matchedScopePatterns = [];
46951
+ for (const [labelName, packagePattern] of Object.entries(scopeLabels)) {
46952
+ if (allLabels.includes(labelName)) {
46953
+ info(`Scope label "${labelName}" detected \u2014 limiting release to packages matching "${packagePattern}"`);
46954
+ matchedScopePatterns.push(packagePattern);
46955
+ }
46956
+ }
46957
+ let finalTarget = options.target;
46958
+ if (matchedScopePatterns.length > 0) {
46959
+ finalTarget = matchedScopePatterns.join(", ");
46960
+ } else if (defaultScope && Object.keys(scopeLabels).length > 0) {
46961
+ const defaultPattern = scopeLabels[defaultScope];
46962
+ if (defaultPattern) {
46963
+ info(`No scope label found \u2014 using default scope "${defaultScope}" (${defaultPattern})`);
46964
+ finalTarget = defaultPattern;
46965
+ }
46966
+ }
46967
+ return { target: finalTarget, scopeLabels: matchedScopePatterns, labels: allLabels };
46968
+ }
46780
46969
  async function runRelease(inputOptions) {
46781
46970
  const options = { ...inputOptions };
46782
46971
  if (options.verbose) setLogLevel("debug");
@@ -46790,6 +46979,26 @@ async function runRelease(inputOptions) {
46790
46979
  throw err;
46791
46980
  }
46792
46981
  const releaseConfig = releaseKitConfig.release;
46982
+ const ciConfig = loadCIConfig({ cwd: options.projectDir, configPath: options.config });
46983
+ if (!options.dryRun) {
46984
+ const scopeResult = await applyScopeLabelsFromPR(ciConfig, options);
46985
+ if (scopeResult.blocked) {
46986
+ info("Release blocked due to conflicting PR labels");
46987
+ return null;
46988
+ }
46989
+ if (scopeResult.target !== options.target) {
46990
+ options.target = scopeResult.target;
46991
+ }
46992
+ } else if (ciConfig?.scopeLabels) {
46993
+ const scopeResult = await applyScopeLabelsFromPR(ciConfig, options);
46994
+ if (scopeResult.blocked) {
46995
+ info("Release blocked due to conflicting PR labels");
46996
+ return null;
46997
+ }
46998
+ if (scopeResult.target !== options.target) {
46999
+ options.target = scopeResult.target;
47000
+ }
47001
+ }
46793
47002
  if (releaseConfig?.ci?.skipPatterns?.length) {
46794
47003
  const headCommit = getHeadCommitMessage(options.projectDir);
46795
47004
  if (headCommit) {
@@ -46919,14 +47128,6 @@ async function runPublishStep(versionOutput, options, releaseNotes, additionalFi
46919
47128
  }
46920
47129
 
46921
47130
  // src/preview.ts
46922
- var DEFAULT_LABELS = {
46923
- stable: "release:stable",
46924
- prerelease: "release:prerelease",
46925
- skip: "release:skip",
46926
- major: "release:major",
46927
- minor: "release:minor",
46928
- patch: "release:patch"
46929
- };
46930
47131
  async function runPreview(options) {
46931
47132
  const ciConfig = loadCIConfig({ cwd: options.projectDir, configPath: options.config });
46932
47133
  if (ciConfig?.prPreview === false) {
@@ -46960,6 +47161,7 @@ async function runPreview(options) {
46960
47161
  sync: false,
46961
47162
  bump: effectiveOptions.bump,
46962
47163
  prerelease: prereleaseFlag,
47164
+ stable: effectiveOptions.stable,
46963
47165
  skipNotes: true,
46964
47166
  skipPublish: true,
46965
47167
  skipGit: true,
@@ -46968,7 +47170,8 @@ async function runPreview(options) {
46968
47170
  json: false,
46969
47171
  verbose: false,
46970
47172
  quiet: true,
46971
- projectDir: effectiveOptions.projectDir
47173
+ projectDir: effectiveOptions.projectDir,
47174
+ target: effectiveOptions.target
46972
47175
  });
46973
47176
  } else {
46974
47177
  info("No release label detected \u2014 skipping version analysis");
@@ -46999,7 +47202,14 @@ function resolvePrerelease(options, packagePaths, projectDir) {
46999
47202
  async function applyLabelOverrides(options, ciConfig, context, existingOctokit) {
47000
47203
  const trigger = ciConfig?.releaseTrigger ?? "label";
47001
47204
  const labels = ciConfig?.labels ?? DEFAULT_LABELS;
47002
- const defaultLabelContext = { trigger, skip: false, noBumpLabel: false };
47205
+ const scopeLabels = ciConfig?.scopeLabels ?? {};
47206
+ const defaultLabelContext = {
47207
+ trigger,
47208
+ skip: false,
47209
+ noBumpLabel: false,
47210
+ bumpConflict: false,
47211
+ prereleaseConflict: false
47212
+ };
47003
47213
  if (!context) {
47004
47214
  return {
47005
47215
  options,
@@ -47018,7 +47228,41 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
47018
47228
  };
47019
47229
  }
47020
47230
  const result = { ...options };
47021
- const labelContext = { trigger, skip: false, noBumpLabel: false, labels };
47231
+ const labelContext = {
47232
+ trigger,
47233
+ skip: false,
47234
+ noBumpLabel: false,
47235
+ bumpConflict: false,
47236
+ prereleaseConflict: false,
47237
+ labels,
47238
+ scopeLabels: []
47239
+ };
47240
+ const matchedScopePatterns = [];
47241
+ for (const [labelName, packagePattern] of Object.entries(scopeLabels)) {
47242
+ if (prLabels.includes(labelName)) {
47243
+ info(`PR label "${labelName}" detected \u2014 limiting release to packages matching "${packagePattern}"`);
47244
+ matchedScopePatterns.push(packagePattern);
47245
+ }
47246
+ }
47247
+ labelContext.scopeLabels = matchedScopePatterns;
47248
+ if (matchedScopePatterns.length > 0) {
47249
+ result.target = matchedScopePatterns.join(", ");
47250
+ } else if (ciConfig?.defaultScope && scopeLabels[ciConfig.defaultScope]) {
47251
+ const defaultPattern = scopeLabels[ciConfig.defaultScope];
47252
+ info(`No scope label found \u2014 using default scope "${ciConfig.defaultScope}" (${defaultPattern})`);
47253
+ result.target = defaultPattern;
47254
+ }
47255
+ const conflict = detectLabelConflicts(prLabels, labels);
47256
+ if (trigger === "label" && conflict.bumpConflict) {
47257
+ warn(`Conflicting bump labels detected (${conflict.bumpLabelsPresent.join(", ")}) \u2014 release blocked`);
47258
+ labelContext.noBumpLabel = true;
47259
+ labelContext.bumpConflict = true;
47260
+ }
47261
+ if (conflict.prereleaseConflict) {
47262
+ warn(`Conflicting labels "${labels.stable}" and "${labels.prerelease}" detected \u2014 release blocked`);
47263
+ labelContext.noBumpLabel = true;
47264
+ labelContext.prereleaseConflict = true;
47265
+ }
47022
47266
  if (trigger === "commit") {
47023
47267
  if (prLabels.includes(labels.skip)) {
47024
47268
  info(`PR label "${labels.skip}" detected \u2014 release will be skipped`);
@@ -47030,7 +47274,8 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
47030
47274
  result.bump = "major";
47031
47275
  }
47032
47276
  } else {
47033
- if (prLabels.includes(labels.major)) {
47277
+ if (conflict.bumpConflict || conflict.prereleaseConflict) {
47278
+ } else if (prLabels.includes(labels.major)) {
47034
47279
  info(`PR label "${labels.major}" detected \u2014 major release`);
47035
47280
  labelContext.bumpLabel = "major";
47036
47281
  result.bump = "major";
@@ -47042,17 +47287,26 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
47042
47287
  info(`PR label "${labels.patch}" detected \u2014 patch release`);
47043
47288
  labelContext.bumpLabel = "patch";
47044
47289
  result.bump = "patch";
47045
- } else {
47046
- labelContext.noBumpLabel = true;
47290
+ } else if (matchedScopePatterns.length === 0) {
47291
+ const hasStableOrPrerelease = conflict.hasStable || conflict.hasPrerelease;
47292
+ if (!hasStableOrPrerelease) {
47293
+ labelContext.noBumpLabel = true;
47294
+ }
47047
47295
  }
47048
47296
  }
47049
47297
  if (!options.stable && options.prerelease === void 0) {
47050
- if (prLabels.includes(labels.stable)) {
47298
+ if (conflict.hasStable && conflict.hasPrerelease) {
47299
+ } else if (conflict.hasStable) {
47051
47300
  info(`PR label "${labels.stable}" detected \u2014 using stable release preview`);
47052
47301
  result.stable = true;
47053
- } else if (prLabels.includes(labels.prerelease)) {
47302
+ } else if (conflict.hasPrerelease) {
47054
47303
  info(`PR label "${labels.prerelease}" detected \u2014 using prerelease preview`);
47055
47304
  result.prerelease = true;
47305
+ if (trigger === "label" && !result.bump) {
47306
+ info("No bump label found \u2014 defaulting to patch bump for prerelease release");
47307
+ result.bump = "patch";
47308
+ labelContext.bumpLabel = "patch";
47309
+ }
47056
47310
  }
47057
47311
  }
47058
47312
  return { options: result, labelContext: { ...labelContext, labels } };
@@ -47060,7 +47314,7 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
47060
47314
 
47061
47315
  // src/preview-command.ts
47062
47316
  function createPreviewCommand() {
47063
- return new Command5("preview").description("Post a release preview comment on the current pull request").option("-c, --config <path>", "Path to config file").option("--project-dir <path>", "Project directory", process.cwd()).option("--pr <number>", "PR number (auto-detected from GitHub Actions)").option("--repo <owner/repo>", "Repository (auto-detected from GITHUB_REPOSITORY)").option("-p, --prerelease [identifier]", "Force prerelease preview (auto-detected by default)").option("--stable", "Force stable release preview (graduation from prerelease)", false).option(
47317
+ return new Command5("preview").description("Post a release preview comment on the current pull request").option("-c, --config <path>", "Path to config file").option("--project-dir <path>", "Project directory", process.cwd()).option("--pr <number>", "PR number (auto-detected from GitHub Actions)").option("--repo <owner/repo>", "Repository (auto-detected from GITHUB_REPOSITORY)").option("-p, --prerelease [identifier]", "Force prerelease preview (auto-detected by default)").option("--stable", "Force stable release preview (graduation from prerelease)", false).option("-t, --target <packages>", "Target specific packages (comma-separated)").option(
47064
47318
  "-d, --dry-run",
47065
47319
  "Print the comment to stdout without posting (GitHub context not available in dry-run mode)",
47066
47320
  false
@@ -47073,7 +47327,8 @@ function createPreviewCommand() {
47073
47327
  repo: opts.repo,
47074
47328
  prerelease: opts.prerelease,
47075
47329
  stable: opts.stable,
47076
- dryRun: opts.dryRun
47330
+ dryRun: opts.dryRun,
47331
+ target: opts.target
47077
47332
  });
47078
47333
  } catch (error3) {
47079
47334
  console.error(error3 instanceof Error ? error3.message : String(error3));
@@ -47123,8 +47378,8 @@ function createReleaseCommand() {
47123
47378
  // src/dispatcher.ts
47124
47379
  function createDispatcherProgram() {
47125
47380
  const program = new Command7().name("releasekit").description("Unified release pipeline: version, changelog, and publish").version(readPackageVersion(import.meta.url));
47126
- program.addCommand(createReleaseCommand(), { isDefault: true });
47127
- program.addCommand(createPreviewCommand());
47381
+ program.addCommand(createPreviewCommand(), { isDefault: true });
47382
+ program.addCommand(createReleaseCommand());
47128
47383
  program.addCommand(createInitCommand());
47129
47384
  program.addCommand(createVersionCommand());
47130
47385
  program.addCommand(createNotesCommand());