@varlock/bumpy 1.2.1 → 1.3.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.
Files changed (34) hide show
  1. package/README.md +52 -38
  2. package/dist/{add-DF6bawDT.mjs → add-ET1tcdQm.mjs} +8 -8
  3. package/dist/apply-release-plan-BvZ32LAm.mjs +57 -0
  4. package/dist/{bump-file-C3S_bzSf.mjs → bump-file-CoaSxqne.mjs} +6 -9
  5. package/dist/changelog-BIkNBJ15.mjs +110 -0
  6. package/dist/{changelog-github-DZSHX3Tb.mjs → changelog-github-BAtgxeXv.mjs} +30 -14
  7. package/dist/{check-BJL-YDWz.mjs → check-C80o_gJK.mjs} +7 -7
  8. package/dist/{ci-C88ecvIP.mjs → ci-WJ8kTjeN.mjs} +76 -56
  9. package/dist/{ci-setup-CARJFhcE.mjs → ci-setup-D1NCzbNH.mjs} +3 -3
  10. package/dist/cli.mjs +17 -19
  11. package/dist/{config-D7Umr-fT.mjs → config-D13G4-R8.mjs} +2 -80
  12. package/dist/{generate-D93b3NAD.mjs → generate-BJq--oCu.mjs} +6 -6
  13. package/dist/{git-H9S9z6g-.mjs → git-D0__HP86.mjs} +1 -1
  14. package/dist/index.d.mts +4 -2
  15. package/dist/index.mjs +10 -8
  16. package/dist/{init-DJhMaceS.mjs → init-DND7zRGD.mjs} +3 -3
  17. package/dist/{publish-DGSV607z.mjs → publish-CfZCAlPx.mjs} +49 -13
  18. package/dist/{publish-pipeline-DiwZZ5AF.mjs → publish-pipeline-BvLIu7WF.mjs} +4 -4
  19. package/dist/{release-plan-CNOuSI-d.mjs → release-plan-RBjKmavL.mjs} +3 -2
  20. package/dist/{status-S2ztf_8E.mjs → status-pMfPtt1p.mjs} +7 -7
  21. package/dist/types-BX4pfmKh.mjs +80 -0
  22. package/dist/{version-BXrP4TIO.mjs → version-DLU0h1cq.mjs} +9 -9
  23. package/dist/{workspace-BHsAPUmC.mjs → workspace-BKOAMeki.mjs} +2 -2
  24. package/package.json +1 -1
  25. package/dist/apply-release-plan-B1Wwx3HG.mjs +0 -146
  26. /package/dist/{ai-STKnq09z.mjs → ai-C66IfTzs.mjs} +0 -0
  27. /package/dist/{clack-C6bVkGxf.mjs → clack-CJT1JFFa.mjs} +0 -0
  28. /package/dist/{commit-message-BwsowSds.mjs → commit-message-DOIfDxfj.mjs} +0 -0
  29. /package/dist/{dep-graph-DiLeAhl9.mjs → dep-graph-E-9-eQ2J.mjs} +0 -0
  30. /package/dist/{names-C-TuOPbd.mjs → names-CBy7d8K_.mjs} +0 -0
  31. /package/dist/{package-manager-ByJ0wKYh.mjs → package-manager-CClZtIHP.mjs} +0 -0
  32. /package/dist/{picomatch-DMmqYjgq.mjs → picomatch-TGJi--_I.mjs} +0 -0
  33. /package/dist/{semver-BJzWIuRz.mjs → semver-DfQyVLM_.mjs} +0 -0
  34. /package/dist/{shell-CY7OD48z.mjs → shell-u3bYGxNy.mjs} +0 -0
@@ -1,34 +1,28 @@
1
1
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
- import { a as loadConfig } from "./config-D7Umr-fT.mjs";
3
- import { t as detectPackageManager } from "./package-manager-ByJ0wKYh.mjs";
4
- import { n as discoverWorkspace } from "./workspace-BHsAPUmC.mjs";
5
- import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
6
- import { n as runArgs, r as runArgsAsync, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
7
- import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-C3S_bzSf.mjs";
8
- import { t as assembleReleasePlan } from "./release-plan-CNOuSI-d.mjs";
9
- import { r as getChangedFiles } from "./git-H9S9z6g-.mjs";
10
- import { t as randomName } from "./names-C-TuOPbd.mjs";
11
- import { findChangedPackages } from "./check-BJL-YDWz.mjs";
12
- import { t as resolveCommitMessage } from "./commit-message-BwsowSds.mjs";
2
+ import { a as loadConfig } from "./config-D13G4-R8.mjs";
3
+ import { t as detectPackageManager } from "./package-manager-CClZtIHP.mjs";
4
+ import { n as discoverWorkspace } from "./workspace-BKOAMeki.mjs";
5
+ import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
6
+ import { n as runArgs, r as runArgsAsync, s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
7
+ import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-CoaSxqne.mjs";
8
+ import { t as assembleReleasePlan } from "./release-plan-RBjKmavL.mjs";
9
+ import { r as getChangedFiles } from "./git-D0__HP86.mjs";
10
+ import { t as randomName } from "./names-CBy7d8K_.mjs";
11
+ import { findChangedPackages } from "./check-C80o_gJK.mjs";
12
+ import { t as resolveCommitMessage } from "./commit-message-DOIfDxfj.mjs";
13
13
  import { createHash } from "node:crypto";
14
14
  //#region src/commands/ci.ts
15
15
  /**
16
16
  * Temporarily override GH_TOKEN with BUMPY_GH_TOKEN for a gh CLI call.
17
17
  *
18
- * Use `--pat-pr` / `--pat-comments` flags to opt in. This is useful when
19
- * BUMPY_GH_TOKEN belongs to a dedicated automation/bot account. If you're
20
- * using a developer's personal PAT, it's better to leave these flags off so
21
- * that PRs and comments appear from github-actions[bot] allowing the
22
- * developer to still review and approve the PR.
18
+ * When BUMPY_GH_TOKEN is set (e.g. a dedicated bot PAT or GitHub App token),
19
+ * it is used so that PRs created by bumpy can trigger CI workflows (the
20
+ * default GITHUB_TOKEN cannot do this). If BUMPY_GH_TOKEN is not available
21
+ * (e.g. fork PRs where secrets are hidden), falls back to the default token.
23
22
  */
24
- function requirePatToken() {
23
+ async function withPatToken(fn) {
25
24
  const token = process.env.BUMPY_GH_TOKEN;
26
- if (!token) throw new Error("BUMPY_GH_TOKEN must be set when using --pat-pr or --pat-comments");
27
- return token;
28
- }
29
- async function withPatToken(usePat, fn) {
30
- if (!usePat) return fn();
31
- const token = requirePatToken();
25
+ if (!token) return fn();
32
26
  const originalGhToken = process.env.GH_TOKEN;
33
27
  process.env.GH_TOKEN = token;
34
28
  try {
@@ -89,12 +83,12 @@ async function ciCheckCommand(rootDir, opts) {
89
83
  const prNumber = detectPrNumber();
90
84
  const pm = await detectPackageManager(rootDir);
91
85
  const changedFiles = getChangedFiles(rootDir, config.baseBranch);
92
- const { branchBumpFiles: prBumpFiles, hasEmptyBumpFile } = filterBranchBumpFiles(allBumpFiles, changedFiles, rootDir, parseErrors);
86
+ const { branchBumpFiles: prBumpFiles, emptyBumpFileIds } = filterBranchBumpFiles(allBumpFiles, changedFiles, rootDir, parseErrors);
93
87
  if (parseErrors.length > 0) for (const err of parseErrors) log.error(err);
94
88
  if (prBumpFiles.length === 0) {
95
- if (hasEmptyBumpFile && parseErrors.length === 0) {
89
+ if (emptyBumpFileIds.length > 0 && parseErrors.length === 0) {
96
90
  log.success("Empty bump file found — no releases needed.");
97
- if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatEmptyBumpFileComment(), rootDir, opts.patComments);
91
+ if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatEmptyBumpFileComment(emptyBumpFileIds, prNumber, detectPrBranch(rootDir)), rootDir);
98
92
  return;
99
93
  }
100
94
  const willFail = !opts.noFail || parseErrors.length > 0;
@@ -103,7 +97,7 @@ async function ciCheckCommand(rootDir, opts) {
103
97
  else log.warn(msg);
104
98
  if (shouldComment && prNumber) {
105
99
  const prBranch = detectPrBranch(rootDir);
106
- await postOrUpdatePrComment(prNumber, parseErrors.length > 0 ? formatBumpFileErrorsComment(parseErrors, prBranch, pm) : formatNoBumpFilesComment(prBranch, pm), rootDir, opts.patComments);
100
+ await postOrUpdatePrComment(prNumber, parseErrors.length > 0 ? formatBumpFileErrorsComment(parseErrors, prBranch, pm) : formatNoBumpFilesComment(prBranch, pm), rootDir);
107
101
  }
108
102
  if (willFail) process.exit(1);
109
103
  return;
@@ -115,7 +109,7 @@ async function ciCheckCommand(rootDir, opts) {
115
109
  console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${tag}`);
116
110
  }
117
111
  if (plan.warnings.length > 0) for (const w of plan.warnings) log.warn(w);
118
- if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatReleasePlanComment(plan, prBumpFiles, prNumber, detectPrBranch(rootDir), pm, plan.warnings, parseErrors), rootDir, opts.patComments);
112
+ if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatReleasePlanComment(plan, prBumpFiles, prNumber, detectPrBranch(rootDir), pm, plan.warnings, parseErrors, emptyBumpFileIds), rootDir);
119
113
  if (parseErrors.length > 0 && !opts.noFail) process.exit(1);
120
114
  const coveredPackages = new Set(plan.releases.map((r) => r.name));
121
115
  const missing = (await findChangedPackages(changedFiles, packages, rootDir, config)).filter((name) => !coveredPackages.has(name));
@@ -141,7 +135,7 @@ async function ciReleaseCommand(rootDir, opts) {
141
135
  }
142
136
  if (bumpFiles.length === 0) {
143
137
  log.info("No pending bump files — checking for unpublished packages...");
144
- const { publishCommand } = await import("./publish-DGSV607z.mjs");
138
+ const { publishCommand } = await import("./publish-CfZCAlPx.mjs");
145
139
  await publishCommand(rootDir, { tag: opts.tag });
146
140
  return;
147
141
  }
@@ -151,11 +145,11 @@ async function ciReleaseCommand(rootDir, opts) {
151
145
  return;
152
146
  }
153
147
  if (opts.mode === "auto-publish") await autoPublish(rootDir, config, plan, opts.tag);
154
- else await createVersionPr(rootDir, plan, config, new Map([...packages.values()].map((p) => [p.name, p.relativeDir])), opts.branch, opts.patPr);
148
+ else await createVersionPr(rootDir, plan, config, new Map([...packages.values()].map((p) => [p.name, p.relativeDir])), opts.branch);
155
149
  }
156
150
  async function autoPublish(rootDir, config, plan, tag) {
157
151
  log.step("Running bumpy version...");
158
- const { versionCommand } = await import("./version-BXrP4TIO.mjs");
152
+ const { versionCommand } = await import("./version-DLU0h1cq.mjs");
159
153
  await versionCommand(rootDir);
160
154
  log.step("Committing version changes...");
161
155
  runArgs([
@@ -184,7 +178,7 @@ async function autoPublish(rootDir, config, plan, tag) {
184
178
  ], { cwd: rootDir });
185
179
  }
186
180
  log.step("Running bumpy publish...");
187
- const { publishCommand } = await import("./publish-DGSV607z.mjs");
181
+ const { publishCommand } = await import("./publish-CfZCAlPx.mjs");
188
182
  await publishCommand(rootDir, { tag });
189
183
  }
190
184
  /**
@@ -306,7 +300,7 @@ function pushWithToken(rootDir, branch, config) {
306
300
  if (!token && repo) log.warn("BUMPY_GH_TOKEN is not set — PR checks will not trigger automatically.\n Run `bumpy ci setup` for help.");
307
301
  }
308
302
  }
309
- async function createVersionPr(rootDir, plan, config, packageDirs, branchName, patPr) {
303
+ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
310
304
  const branch = validateBranchName(branchName || config.versionPr.branch);
311
305
  const baseBranch = validateBranchName(tryRunArgs([
312
306
  "git",
@@ -350,7 +344,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
350
344
  branch
351
345
  ], { cwd: rootDir });
352
346
  log.step("Running bumpy version...");
353
- const { versionCommand } = await import("./version-BXrP4TIO.mjs");
347
+ const { versionCommand } = await import("./version-DLU0h1cq.mjs");
354
348
  await versionCommand(rootDir);
355
349
  runArgs([
356
350
  "git",
@@ -381,11 +375,12 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
381
375
  });
382
376
  pushWithToken(rootDir, branch, config);
383
377
  const repo = process.env.GITHUB_REPOSITORY;
378
+ const noPatWarning = !process.env.BUMPY_GH_TOKEN && !!repo;
384
379
  if (existingPr) {
385
380
  const validPr = validatePrNumber(existingPr);
386
- const prBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs, repo, validPr);
381
+ const prBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs, repo, validPr, noPatWarning);
387
382
  log.step(`Updating existing PR #${validPr}...`);
388
- await withPatToken(!!patPr, () => runArgsAsync([
383
+ await withPatToken(() => runArgsAsync([
389
384
  "gh",
390
385
  "pr",
391
386
  "edit",
@@ -402,8 +397,8 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
402
397
  } else {
403
398
  log.step("Creating version PR...");
404
399
  const prTitle = config.versionPr.title;
405
- const prBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs, repo, null);
406
- const result = await withPatToken(!!patPr, () => runArgsAsync([
400
+ const prBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs, repo, null, noPatWarning);
401
+ const result = await withPatToken(() => runArgsAsync([
407
402
  "gh",
408
403
  "pr",
409
404
  "create",
@@ -423,8 +418,8 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
423
418
  if (repo) {
424
419
  const newPrNumber = result?.match(/\/pull\/(\d+)/)?.[1];
425
420
  if (newPrNumber) {
426
- const updatedBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs, repo, newPrNumber);
427
- await withPatToken(!!patPr, () => runArgsAsync([
421
+ const updatedBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs, repo, newPrNumber, noPatWarning);
422
+ await withPatToken(() => runArgsAsync([
428
423
  "gh",
429
424
  "pr",
430
425
  "edit",
@@ -437,7 +432,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
437
432
  }));
438
433
  }
439
434
  }
440
- if (!patPr) pushWithToken(rootDir, branch, config);
435
+ if (!process.env.BUMPY_GH_TOKEN) pushWithToken(rootDir, branch, config);
441
436
  }
442
437
  runArgs([
443
438
  "git",
@@ -467,11 +462,11 @@ function pmRunCommand(pm) {
467
462
  if (pm === "yarn") return "yarn bumpy";
468
463
  return "npx bumpy";
469
464
  }
470
- function formatReleasePlanComment(plan, bumpFiles, prNumber, prBranch, pm, warnings = [], parseErrors = []) {
465
+ function formatReleasePlanComment(plan, bumpFiles, prNumber, prBranch, pm, warnings = [], parseErrors = [], emptyBumpFileIds = []) {
471
466
  const repo = process.env.GITHUB_REPOSITORY;
472
467
  const lines = [];
473
468
  const preamble = [
474
- `<a href="https://bumpy.varlock.dev"><img src="${FROG_IMG_BASE}/frog-talking.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
469
+ `<a href="https://bumpy.varlock.dev"><img src="${FROG_IMG_BASE}/frog-clipboard.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
475
470
  "",
476
471
  "**The changes in this PR will be included in the next version bump.**",
477
472
  "<br clear=\"left\" />"
@@ -510,6 +505,15 @@ function formatReleasePlanComment(plan, bumpFiles, prNumber, prBranch, pm, warni
510
505
  }
511
506
  lines.push(`- ${parts.join(" ")}`);
512
507
  }
508
+ for (const id of emptyBumpFileIds) {
509
+ const filename = `${id}.md`;
510
+ const parts = [`\`${filename}\` _(empty — no release)_`];
511
+ if (repo) {
512
+ parts.push(`([view diff](https://github.com/${repo}/pull/${prNumber}/changes#diff-${sha256Hex(`.bumpy/${filename}`)}))`);
513
+ if (prBranch) parts.push(`([edit](https://github.com/${repo}/edit/${prBranch}/.bumpy/${filename}))`);
514
+ }
515
+ lines.push(`- ${parts.join(" ")}`);
516
+ }
513
517
  lines.push("");
514
518
  if (parseErrors.length > 0) {
515
519
  lines.push("#### Errors");
@@ -533,7 +537,7 @@ function formatReleasePlanComment(plan, bumpFiles, prNumber, prBranch, pm, warni
533
537
  function formatBumpFileErrorsComment(errors, prBranch, pm) {
534
538
  const runCmd = pmRunCommand(pm);
535
539
  const lines = [
536
- `<a href="https://bumpy.varlock.dev"><img src="${FROG_IMG_BASE}/frog-neutral.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
540
+ `<a href="https://bumpy.varlock.dev"><img src="${FROG_IMG_BASE}/frog-error.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
537
541
  "",
538
542
  "**This PR has bump file(s) with errors that need to be fixed.**",
539
543
  "<br clear=\"left\" />\n",
@@ -555,20 +559,32 @@ function formatBumpFileErrorsComment(errors, prBranch, pm) {
555
559
  lines.push(`_This comment is maintained by [bumpy](https://bumpy.varlock.dev)._`);
556
560
  return lines.join("\n");
557
561
  }
558
- function formatEmptyBumpFileComment() {
559
- return [
562
+ function formatEmptyBumpFileComment(emptyBumpFileIds, prNumber, prBranch) {
563
+ const repo = process.env.GITHUB_REPOSITORY;
564
+ const lines = [
560
565
  `<a href="https://bumpy.varlock.dev"><img src="${FROG_IMG_BASE}/frog-neutral.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
561
566
  "",
562
567
  "**This PR includes an empty bump file — no version bump is needed.** :white_check_mark:",
563
568
  "<br clear=\"left\" />",
564
- "\n---",
565
- `_This comment is maintained by [bumpy](https://bumpy.varlock.dev)._`
566
- ].join("\n");
569
+ ""
570
+ ];
571
+ for (const id of emptyBumpFileIds) {
572
+ const filename = `${id}.md`;
573
+ const parts = [`\`${filename}\``];
574
+ if (repo) {
575
+ parts.push(`([view diff](https://github.com/${repo}/pull/${prNumber}/changes#diff-${sha256Hex(`.bumpy/${filename}`)}))`);
576
+ if (prBranch) parts.push(`([edit](https://github.com/${repo}/edit/${prBranch}/.bumpy/${filename}))`);
577
+ }
578
+ lines.push(`- ${parts.join(" ")}`);
579
+ }
580
+ lines.push("\n---");
581
+ lines.push(`_This comment is maintained by [bumpy](https://bumpy.varlock.dev)._`);
582
+ return lines.join("\n");
567
583
  }
568
584
  function formatNoBumpFilesComment(prBranch, pm) {
569
585
  const runCmd = pmRunCommand(pm);
570
586
  const lines = [
571
- `<a href="https://bumpy.varlock.dev"><img src="${FROG_IMG_BASE}/frog-neutral.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
587
+ `<a href="https://bumpy.varlock.dev"><img src="${FROG_IMG_BASE}/frog-warning.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
572
588
  "",
573
589
  "Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a bump file.**",
574
590
  "<br clear=\"left\" />\n",
@@ -598,7 +614,7 @@ function buildDiffLinks(pkgDir, changesBaseUrl) {
598
614
  function sha256Hex(input) {
599
615
  return createHash("sha256").update(input).digest("hex");
600
616
  }
601
- function formatVersionPrBody(plan, preamble, packageDirs, repo, prNumber) {
617
+ function formatVersionPrBody(plan, preamble, packageDirs, repo, prNumber, showNoPatWarning = false) {
602
618
  const changesBaseUrl = repo && prNumber ? `https://github.com/${repo}/pull/${prNumber}/changes` : null;
603
619
  const lines = [];
604
620
  lines.push(preamble);
@@ -637,10 +653,14 @@ function formatVersionPrBody(plan, preamble, packageDirs, repo, prNumber) {
637
653
  lines.push("");
638
654
  }
639
655
  }
656
+ if (showNoPatWarning) {
657
+ lines.push("> ⚠️ `BUMPY_GH_TOKEN` is not set — CI checks will not run automatically on this PR. Run `bumpy ci setup` for help.");
658
+ lines.push("");
659
+ }
640
660
  return lines.join("\n");
641
661
  }
642
662
  const COMMENT_MARKER = "<!-- bumpy-release-plan -->";
643
- async function postOrUpdatePrComment(prNumber, body, rootDir, usePat = false) {
663
+ async function postOrUpdatePrComment(prNumber, body, rootDir) {
644
664
  const validPr = validatePrNumber(prNumber);
645
665
  const markedBody = `${COMMENT_MARKER}\n${body}`;
646
666
  try {
@@ -655,7 +675,7 @@ async function postOrUpdatePrComment(prNumber, body, rootDir, usePat = false) {
655
675
  `.comments[] | select(.body | startswith("${COMMENT_MARKER}")) | .url | capture("issuecomment-(?<id>[0-9]+)$") | .id`
656
676
  ], { cwd: rootDir })?.split("\n")[0]?.trim();
657
677
  if (commentId) {
658
- await withPatToken(usePat, () => runArgsAsync([
678
+ await runArgsAsync([
659
679
  "gh",
660
680
  "api",
661
681
  `repos/{owner}/{repo}/issues/comments/${commentId}`,
@@ -666,10 +686,10 @@ async function postOrUpdatePrComment(prNumber, body, rootDir, usePat = false) {
666
686
  ], {
667
687
  cwd: rootDir,
668
688
  input: markedBody
669
- }));
689
+ });
670
690
  log.dim(" Updated PR comment");
671
691
  } else {
672
- await withPatToken(usePat, () => runArgsAsync([
692
+ await runArgsAsync([
673
693
  "gh",
674
694
  "pr",
675
695
  "comment",
@@ -679,7 +699,7 @@ async function postOrUpdatePrComment(prNumber, body, rootDir, usePat = false) {
679
699
  ], {
680
700
  cwd: rootDir,
681
701
  input: markedBody
682
- }));
702
+ });
683
703
  log.dim(" Posted PR comment");
684
704
  }
685
705
  } catch (err) {
@@ -1,7 +1,7 @@
1
1
  import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
2
- import { t as detectPackageManager } from "./package-manager-ByJ0wKYh.mjs";
3
- import { s as tryRunArgs } from "./shell-CY7OD48z.mjs";
4
- import { a as fe, c as ot, i as _t, n as O, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-C6bVkGxf.mjs";
2
+ import { t as detectPackageManager } from "./package-manager-CClZtIHP.mjs";
3
+ import { s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
4
+ import { a as fe, c as ot, i as _t, n as O, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-CJT1JFFa.mjs";
5
5
  //#region src/commands/ci-setup.ts
6
6
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
7
7
  const PAT_PERMISSIONS = [
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
3
- import { n as findRoot } from "./config-D7Umr-fT.mjs";
3
+ import { n as findRoot } from "./config-D13G4-R8.mjs";
4
4
  //#region src/cli.ts
5
5
  const args = process.argv.slice(2);
6
6
  const command = args[0];
@@ -25,13 +25,13 @@ async function main() {
25
25
  switch (command) {
26
26
  case "init": {
27
27
  const rootDir = await findRoot();
28
- const { initCommand } = await import("./init-DJhMaceS.mjs");
28
+ const { initCommand } = await import("./init-DND7zRGD.mjs");
29
29
  await initCommand(rootDir, { force: flags.force === true });
30
30
  break;
31
31
  }
32
32
  case "add": {
33
33
  const rootDir = await findRoot();
34
- const { addCommand } = await import("./add-DF6bawDT.mjs");
34
+ const { addCommand } = await import("./add-ET1tcdQm.mjs");
35
35
  await addCommand(rootDir, {
36
36
  packages: flags.packages,
37
37
  message: flags.message,
@@ -42,7 +42,7 @@ async function main() {
42
42
  }
43
43
  case "status": {
44
44
  const rootDir = await findRoot();
45
- const { statusCommand } = await import("./status-S2ztf_8E.mjs");
45
+ const { statusCommand } = await import("./status-pMfPtt1p.mjs");
46
46
  await statusCommand(rootDir, {
47
47
  json: flags.json === true,
48
48
  packagesOnly: flags.packages === true,
@@ -54,13 +54,13 @@ async function main() {
54
54
  }
55
55
  case "version": {
56
56
  const rootDir = await findRoot();
57
- const { versionCommand } = await import("./version-BXrP4TIO.mjs");
57
+ const { versionCommand } = await import("./version-DLU0h1cq.mjs");
58
58
  await versionCommand(rootDir, { commit: flags.commit === true });
59
59
  break;
60
60
  }
61
61
  case "generate": {
62
62
  const rootDir = await findRoot();
63
- const { generateCommand } = await import("./generate-D93b3NAD.mjs");
63
+ const { generateCommand } = await import("./generate-BJq--oCu.mjs");
64
64
  await generateCommand(rootDir, {
65
65
  from: flags.from,
66
66
  dryRun: flags["dry-run"] === true,
@@ -70,7 +70,7 @@ async function main() {
70
70
  }
71
71
  case "check": {
72
72
  const rootDir = await findRoot();
73
- const { checkCommand } = await import("./check-BJL-YDWz.mjs");
73
+ const { checkCommand } = await import("./check-C80o_gJK.mjs");
74
74
  await checkCommand(rootDir, {
75
75
  strict: flags.strict === true,
76
76
  noFail: flags["no-fail"] === true
@@ -82,23 +82,21 @@ async function main() {
82
82
  const subcommand = args[1];
83
83
  const ciFlags = parseFlags(args.slice(2));
84
84
  if (subcommand === "check") {
85
- const { ciCheckCommand } = await import("./ci-C88ecvIP.mjs");
85
+ const { ciCheckCommand } = await import("./ci-WJ8kTjeN.mjs");
86
86
  await ciCheckCommand(rootDir, {
87
87
  comment: ciFlags.comment !== void 0 ? ciFlags.comment === true : void 0,
88
88
  strict: ciFlags.strict === true,
89
- noFail: ciFlags["no-fail"] === true,
90
- patComments: ciFlags["pat-comments"] === true
89
+ noFail: ciFlags["no-fail"] === true
91
90
  });
92
91
  } else if (subcommand === "release") {
93
- const { ciReleaseCommand } = await import("./ci-C88ecvIP.mjs");
92
+ const { ciReleaseCommand } = await import("./ci-WJ8kTjeN.mjs");
94
93
  await ciReleaseCommand(rootDir, {
95
94
  mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
96
95
  tag: ciFlags.tag,
97
- branch: ciFlags.branch,
98
- patPr: ciFlags["pat-pr"] === true
96
+ branch: ciFlags.branch
99
97
  });
100
98
  } else if (subcommand === "setup") {
101
- const { ciSetupCommand } = await import("./ci-setup-CARJFhcE.mjs");
99
+ const { ciSetupCommand } = await import("./ci-setup-D1NCzbNH.mjs");
102
100
  await ciSetupCommand(rootDir);
103
101
  } else {
104
102
  log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
@@ -108,7 +106,7 @@ async function main() {
108
106
  }
109
107
  case "publish": {
110
108
  const rootDir = await findRoot();
111
- const { publishCommand } = await import("./publish-DGSV607z.mjs");
109
+ const { publishCommand } = await import("./publish-CfZCAlPx.mjs");
112
110
  await publishCommand(rootDir, {
113
111
  dryRun: flags["dry-run"] === true,
114
112
  tag: flags.tag,
@@ -122,7 +120,7 @@ async function main() {
122
120
  const subcommand = args[1];
123
121
  const aiFlags = parseFlags(args.slice(2));
124
122
  if (subcommand === "setup") {
125
- const { aiSetupCommand } = await import("./ai-STKnq09z.mjs");
123
+ const { aiSetupCommand } = await import("./ai-C66IfTzs.mjs");
126
124
  await aiSetupCommand(rootDir, { target: aiFlags.target });
127
125
  } else {
128
126
  log.error(`Unknown ai subcommand: ${subcommand}. Use "ai setup".`);
@@ -132,7 +130,7 @@ async function main() {
132
130
  }
133
131
  case "--version":
134
132
  case "-v":
135
- console.log(`bumpy 1.2.1`);
133
+ console.log(`bumpy 1.3.0`);
136
134
  break;
137
135
  case "help":
138
136
  case "--help":
@@ -152,7 +150,7 @@ async function main() {
152
150
  }
153
151
  function printHelp() {
154
152
  console.log(`
155
- ${colorize(`🐸 bumpy v1.2.1`, "bold")} - Modern monorepo versioning
153
+ ${colorize(`🐸 bumpy v1.3.0`, "bold")} - Modern monorepo versioning
156
154
 
157
155
  Usage: bumpy <command> [options]
158
156
 
@@ -206,7 +204,7 @@ function printHelp() {
206
204
  --branch <name> Branch name for version PR (default: bumpy/version-packages)
207
205
 
208
206
  AI setup options:
209
- --target <tool> Target AI tool: opencode, cursor, codex
207
+ --target <tool> Target AI tool: claude, opencode, cursor, codex
210
208
 
211
209
  ${colorize("https://bumpy.varlock.dev", "dim")}
212
210
  `);
@@ -1,85 +1,7 @@
1
1
  import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
2
2
  import { a as readJson, n as exists, o as readJsonc } from "./fs-DnDogVn-.mjs";
3
+ import { r as DEFAULT_CONFIG } from "./types-BX4pfmKh.mjs";
3
4
  import { resolve } from "node:path";
4
- //#region src/types.ts
5
- const BUMP_LEVELS = {
6
- patch: 0,
7
- minor: 1,
8
- major: 2
9
- };
10
- function bumpLevel(type) {
11
- return BUMP_LEVELS[type];
12
- }
13
- function maxBump(a, b) {
14
- if (!a) return b;
15
- return bumpLevel(a) >= bumpLevel(b) ? a : b;
16
- }
17
- const DEFAULT_BUMP_RULES = {
18
- dependencies: {
19
- trigger: "patch",
20
- bumpAs: "patch"
21
- },
22
- peerDependencies: {
23
- trigger: "major",
24
- bumpAs: "match"
25
- },
26
- devDependencies: false,
27
- optionalDependencies: {
28
- trigger: "minor",
29
- bumpAs: "patch"
30
- }
31
- };
32
- const DEP_TYPES = [
33
- "dependencies",
34
- "devDependencies",
35
- "peerDependencies",
36
- "optionalDependencies"
37
- ];
38
- const DEFAULT_PUBLISH_CONFIG = {
39
- packManager: "auto",
40
- publishManager: "npm",
41
- publishArgs: [],
42
- protocolResolution: "pack"
43
- };
44
- const DEFAULT_CONFIG = {
45
- baseBranch: "main",
46
- access: "public",
47
- versionCommitMessage: void 0,
48
- changedFilePatterns: ["**"],
49
- changelog: "default",
50
- fixed: [],
51
- linked: [],
52
- ignore: [],
53
- include: [],
54
- updateInternalDependencies: "out-of-range",
55
- dependencyBumpRules: {},
56
- privatePackages: {
57
- version: false,
58
- tag: false
59
- },
60
- allowCustomCommands: false,
61
- packages: {},
62
- publish: { ...DEFAULT_PUBLISH_CONFIG },
63
- aggregateRelease: false,
64
- gitUser: {
65
- name: "bumpy-bot",
66
- email: "276066384+bumpy-bot@users.noreply.github.com"
67
- },
68
- versionPr: {
69
- title: "🐸 Versioned release",
70
- branch: "bumpy/version-packages",
71
- preamble: [
72
- `<a href="https://bumpy.varlock.dev"><img src="https://raw.githubusercontent.com/dmno-dev/bumpy/main/images/frog-talking.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
73
- "",
74
- `This PR was created and will be kept in sync by [bumpy](https://bumpy.varlock.dev) based on your bump files (in \`.bumpy/\`). Merge it when you are ready to release the packages listed below:`,
75
- "<br clear=\"left\" />"
76
- ].join("\n")
77
- }
78
- };
79
- function hasCascade(r) {
80
- return "cascade" in r && Object.keys(r.cascade).length > 0;
81
- }
82
- //#endregion
83
5
  //#region src/core/config.ts
84
6
  var config_exports = /* @__PURE__ */ __exportAll({
85
7
  findRoot: () => findRoot,
@@ -218,4 +140,4 @@ function isPackageManaged(pkgName, isPrivate, config, pkgBumpy) {
218
140
  return true;
219
141
  }
220
142
  //#endregion
221
- export { loadConfig as a, BUMP_LEVELS as c, DEFAULT_PUBLISH_CONFIG as d, DEP_TYPES as f, maxBump as h, isPackageManaged as i, DEFAULT_BUMP_RULES as l, hasCascade as m, findRoot as n, loadPackageConfig as o, bumpLevel as p, getBumpyDir as r, matchGlob as s, config_exports as t, DEFAULT_CONFIG as u };
143
+ export { loadConfig as a, isPackageManaged as i, findRoot as n, loadPackageConfig as o, getBumpyDir as r, matchGlob as s, config_exports as t };
@@ -1,11 +1,11 @@
1
1
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
2
  import { t as ensureDir } from "./fs-DnDogVn-.mjs";
3
- import { a as loadConfig, r as getBumpyDir } from "./config-D7Umr-fT.mjs";
4
- import { t as discoverPackages } from "./workspace-BHsAPUmC.mjs";
5
- import { s as tryRunArgs } from "./shell-CY7OD48z.mjs";
6
- import { i as writeBumpFile } from "./bump-file-C3S_bzSf.mjs";
7
- import { a as getFilesChangedInCommit, n as getBranchCommits } from "./git-H9S9z6g-.mjs";
8
- import { n as slugify, t as randomName } from "./names-C-TuOPbd.mjs";
3
+ import { a as loadConfig, r as getBumpyDir } from "./config-D13G4-R8.mjs";
4
+ import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
5
+ import { s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
6
+ import { i as writeBumpFile } from "./bump-file-CoaSxqne.mjs";
7
+ import { a as getFilesChangedInCommit, n as getBranchCommits } from "./git-D0__HP86.mjs";
8
+ import { n as slugify, t as randomName } from "./names-CBy7d8K_.mjs";
9
9
  import { relative } from "node:path";
10
10
  //#region src/commands/generate.ts
11
11
  const BUMP_MAP = {
@@ -1,4 +1,4 @@
1
- import { n as runArgs, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
1
+ import { n as runArgs, s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
2
2
  //#region src/core/git.ts
3
3
  /** Create a git tag */
4
4
  function createTag(tag, opts) {
package/dist/index.d.mts CHANGED
@@ -231,13 +231,15 @@ interface ChangelogContext {
231
231
  bumpFiles: BumpFile[];
232
232
  /** ISO date string (YYYY-MM-DD) */
233
233
  date: string;
234
+ /** Where this entry will be used — formatters can customize output per target (default: 'changelog') */
235
+ target?: 'changelog' | 'github-release';
234
236
  }
235
237
  /**
236
238
  * A changelog formatter receives full context and returns the complete
237
239
  * changelog entry string for a single release.
238
240
  */
239
241
  type ChangelogFormatter = (ctx: ChangelogContext) => string | Promise<string>;
240
- /** Default formatter — version heading, date, bullet points */
242
+ /** Default formatter — version heading with date, bullet points sorted by bump type */
241
243
  declare const defaultFormatter: ChangelogFormatter;
242
244
  /**
243
245
  * Load a changelog formatter from config.
@@ -245,7 +247,7 @@ declare const defaultFormatter: ChangelogFormatter;
245
247
  */
246
248
  declare function loadFormatter(changelog: BumpyConfig['changelog'], rootDir: string): Promise<ChangelogFormatter>;
247
249
  /** Generate a changelog entry using the configured formatter */
248
- declare function generateChangelogEntry(release: PlannedRelease, bumpFiles: BumpFile[], formatter?: ChangelogFormatter, date?: string): Promise<string>;
250
+ declare function generateChangelogEntry(release: PlannedRelease, bumpFiles: BumpFile[], formatter?: ChangelogFormatter, date?: string, target?: ChangelogContext['target']): Promise<string>;
249
251
  /** Prepend a new entry to an existing CHANGELOG.md content */
250
252
  declare function prependToChangelog(existingContent: string, newEntry: string): string;
251
253
  //#endregion
package/dist/index.mjs CHANGED
@@ -1,9 +1,11 @@
1
- import { a as loadConfig, c as BUMP_LEVELS, d as DEFAULT_PUBLISH_CONFIG, f as DEP_TYPES, h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, n as findRoot, p as bumpLevel, r as getBumpyDir, s as matchGlob, u as DEFAULT_CONFIG } from "./config-D7Umr-fT.mjs";
2
- import { t as discoverPackages } from "./workspace-BHsAPUmC.mjs";
3
- import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
4
- import { i as writeBumpFile, n as parseBumpFile, r as readBumpFiles } from "./bump-file-C3S_bzSf.mjs";
5
- import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-BJzWIuRz.mjs";
6
- import { t as assembleReleasePlan } from "./release-plan-CNOuSI-d.mjs";
7
- import { a as prependToChangelog, i as loadFormatter, n as defaultFormatter, r as generateChangelogEntry, t as applyReleasePlan } from "./apply-release-plan-B1Wwx3HG.mjs";
8
- import { t as publishPackages } from "./publish-pipeline-DiwZZ5AF.mjs";
1
+ import { a as DEP_TYPES, c as maxBump, i as DEFAULT_PUBLISH_CONFIG, n as DEFAULT_BUMP_RULES, o as bumpLevel, r as DEFAULT_CONFIG, s as hasCascade, t as BUMP_LEVELS } from "./types-BX4pfmKh.mjs";
2
+ import { a as loadConfig, n as findRoot, r as getBumpyDir, s as matchGlob } from "./config-D13G4-R8.mjs";
3
+ import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
4
+ import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
5
+ import { i as writeBumpFile, n as parseBumpFile, r as readBumpFiles } from "./bump-file-CoaSxqne.mjs";
6
+ import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-DfQyVLM_.mjs";
7
+ import { t as assembleReleasePlan } from "./release-plan-RBjKmavL.mjs";
8
+ import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry, t as defaultFormatter } from "./changelog-BIkNBJ15.mjs";
9
+ import { t as applyReleasePlan } from "./apply-release-plan-BvZ32LAm.mjs";
10
+ import { t as publishPackages } from "./publish-pipeline-BvLIu7WF.mjs";
9
11
  export { BUMP_LEVELS, DEFAULT_BUMP_RULES, DEFAULT_CONFIG, DEFAULT_PUBLISH_CONFIG, DEP_TYPES, DependencyGraph, applyReleasePlan, assembleReleasePlan, bumpLevel, bumpVersion, defaultFormatter, discoverPackages, findRoot, generateChangelogEntry, getBumpyDir, hasCascade, loadConfig, loadFormatter, matchGlob, maxBump, parseBumpFile, prependToChangelog, publishPackages, readBumpFiles, satisfies, stripProtocol, writeBumpFile };
@@ -1,8 +1,8 @@
1
1
  import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
2
2
  import { a as readJson, d as writeJson, f as writeText, i as listFiles, n as exists, s as readText, t as ensureDir } from "./fs-DnDogVn-.mjs";
3
- import { t as detectPackageManager } from "./package-manager-ByJ0wKYh.mjs";
4
- import { t as run } from "./shell-CY7OD48z.mjs";
5
- import { c as ot, o as gt, s as mt, t as unwrap } from "./clack-C6bVkGxf.mjs";
3
+ import { t as detectPackageManager } from "./package-manager-CClZtIHP.mjs";
4
+ import { t as run } from "./shell-u3bYGxNy.mjs";
5
+ import { c as ot, o as gt, s as mt, t as unwrap } from "./clack-CJT1JFFa.mjs";
6
6
  import { resolve } from "node:path";
7
7
  import { readdir, rename, rm } from "node:fs/promises";
8
8
  //#region ../../.bumpy/README.md