@varlock/bumpy 0.0.2 → 1.1.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 (43) hide show
  1. package/.claude-plugin/plugin.json +2 -2
  2. package/config-schema.json +327 -0
  3. package/dist/add-BmNL5VwL.mjs +323 -0
  4. package/dist/{ai-CQhUyHAG.mjs → ai-sMYUf3lP.mjs} +21 -4
  5. package/dist/{apply-release-plan-D6TSrcwX.mjs → apply-release-plan-0kH62jhu.mjs} +35 -26
  6. package/dist/bump-file-DVqR3k67.mjs +157 -0
  7. package/dist/{changelog-github-Du62krXi.mjs → changelog-github-DkACMj0j.mjs} +23 -21
  8. package/dist/check-BjWF6SJm.mjs +65 -0
  9. package/dist/{ci-D6LQbR38.mjs → ci-DY58ugIi.mjs} +138 -91
  10. package/dist/{ci-setup-C6FlOfW5.mjs → ci-setup-BQwktQEe.mjs} +3 -3
  11. package/dist/cli.mjs +36 -41
  12. package/dist/commit-message-BwsowSds.mjs +23 -0
  13. package/dist/{config-BkwIEaQg.mjs → config-B-Qg3DZH.mjs} +30 -24
  14. package/dist/fs-DYR2XuFE.mjs +81 -0
  15. package/dist/generate-DX46X-rW.mjs +186 -0
  16. package/dist/{git-CGHVXXKw.mjs → git-YDedMddc.mjs} +54 -2
  17. package/dist/index.d.mts +68 -39
  18. package/dist/index.mjs +9 -9
  19. package/dist/init-DkTPs_WQ.mjs +196 -0
  20. package/dist/{names-Ck8cun7B.mjs → names-C-TuOPbd.mjs} +1 -1
  21. package/dist/{js-yaml-DpZfOoD4.mjs → package-manager-Clsmr-9r.mjs} +79 -1
  22. package/dist/picomatch-DMmqYjgq.mjs +1870 -0
  23. package/dist/{publish-D_7RqEYL.mjs → publish-CGB4TIKD.mjs} +26 -25
  24. package/dist/{publish-pipeline-ChnqW8nR.mjs → publish-pipeline-CXuqce1N.mjs} +24 -19
  25. package/dist/release-plan-JNir7bSM.mjs +264 -0
  26. package/dist/{semver-BTzYh8vc.mjs → semver-BJzWIuRz.mjs} +13 -3
  27. package/dist/{shell-Dj7JRD_q.mjs → shell-CY7OD48z.mjs} +20 -2
  28. package/dist/{status--Q8yAxQ4.mjs → status-EGYqULJg.mjs} +26 -22
  29. package/dist/{version-cAUkfYPx.mjs → version-BcfidiVX.mjs} +23 -22
  30. package/dist/{workspace-CxEKakDm.mjs → workspace-DWXlwcH4.mjs} +3 -3
  31. package/package.json +16 -1
  32. package/skills/add-change/SKILL.md +18 -14
  33. package/dist/add-BjyVIUlr.mjs +0 -175
  34. package/dist/changeset-UCZdSRDv.mjs +0 -108
  35. package/dist/check-jIwike9F.mjs +0 -51
  36. package/dist/fs-0AtnPUUe.mjs +0 -51
  37. package/dist/generate-Btrsn1qi.mjs +0 -177
  38. package/dist/init-B0q3wEQW.mjs +0 -22
  39. package/dist/migrate-CfQNwD0T.mjs +0 -121
  40. package/dist/package-manager-DcI5TdDE.mjs +0 -80
  41. package/dist/release-plan-BEzwApuK.mjs +0 -173
  42. /package/dist/{clack-CDRCHrC-.mjs → clack-C6bVkGxf.mjs} +0 -0
  43. /package/dist/{dep-graph-E-9-eQ2J.mjs → dep-graph-DiLeAhl9.mjs} +0 -0
@@ -1,14 +1,42 @@
1
1
  import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
- import { a as loadConfig } from "./config-BkwIEaQg.mjs";
3
- import { t as detectPackageManager } from "./package-manager-DcI5TdDE.mjs";
4
- import { n as discoverWorkspace } from "./workspace-CxEKakDm.mjs";
5
- import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
6
- import { n as runArgsAsync, o as tryRunArgs, t as runArgs } from "./shell-Dj7JRD_q.mjs";
7
- import { r as readChangesets } from "./changeset-UCZdSRDv.mjs";
8
- import { t as assembleReleasePlan } from "./release-plan-BEzwApuK.mjs";
9
- import { n as getChangedFiles } from "./git-CGHVXXKw.mjs";
10
- import { t as randomName } from "./names-Ck8cun7B.mjs";
2
+ import { a as loadConfig } from "./config-B-Qg3DZH.mjs";
3
+ import { t as detectPackageManager } from "./package-manager-Clsmr-9r.mjs";
4
+ import { n as discoverWorkspace } from "./workspace-DWXlwcH4.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-DVqR3k67.mjs";
8
+ import { t as assembleReleasePlan } from "./release-plan-JNir7bSM.mjs";
9
+ import { r as getChangedFiles } from "./git-YDedMddc.mjs";
10
+ import { t as randomName } from "./names-C-TuOPbd.mjs";
11
+ import { t as resolveCommitMessage } from "./commit-message-BwsowSds.mjs";
12
+ import { createHash } from "node:crypto";
11
13
  //#region src/commands/ci.ts
14
+ /**
15
+ * Temporarily override GH_TOKEN with BUMPY_GH_TOKEN for a gh CLI call.
16
+ *
17
+ * Use `--pat-pr` / `--pat-comments` flags to opt in. This is useful when
18
+ * BUMPY_GH_TOKEN belongs to a dedicated automation/bot account. If you're
19
+ * using a developer's personal PAT, it's better to leave these flags off so
20
+ * that PRs and comments appear from github-actions[bot] — allowing the
21
+ * developer to still review and approve the PR.
22
+ */
23
+ function requirePatToken() {
24
+ const token = process.env.BUMPY_GH_TOKEN;
25
+ if (!token) throw new Error("BUMPY_GH_TOKEN must be set when using --pat-pr or --pat-comments");
26
+ return token;
27
+ }
28
+ async function withPatToken(usePat, fn) {
29
+ if (!usePat) return fn();
30
+ const token = requirePatToken();
31
+ const originalGhToken = process.env.GH_TOKEN;
32
+ process.env.GH_TOKEN = token;
33
+ try {
34
+ return await fn();
35
+ } finally {
36
+ if (originalGhToken !== void 0) process.env.GH_TOKEN = originalGhToken;
37
+ else delete process.env.GH_TOKEN;
38
+ }
39
+ }
12
40
  /** Validate a git branch name to prevent injection */
13
41
  function validateBranchName(name) {
14
42
  if (!/^[a-zA-Z0-9_./-]+$/.test(name)) throw new Error(`Invalid branch name: ${name}`);
@@ -43,14 +71,14 @@ function ensureGitIdentity(rootDir, config) {
43
71
  }
44
72
  }
45
73
  /**
46
- * CI check: report on pending changesets.
74
+ * CI check: report on pending bump files.
47
75
  * Designed for PR workflows — shows what would be released and optionally comments on the PR.
48
76
  */
49
77
  async function ciCheckCommand(rootDir, opts) {
50
78
  const config = await loadConfig(rootDir);
51
79
  const { packages } = await discoverWorkspace(rootDir, config);
52
80
  const depGraph = new DependencyGraph(packages);
53
- const allChangesets = await readChangesets(rootDir);
81
+ const allBumpFiles = await readBumpFiles(rootDir);
54
82
  if (detectPrBranch(rootDir) === config.versionPr.branch) {
55
83
  log.dim(" Skipping — this is the version PR branch.");
56
84
  return;
@@ -59,22 +87,26 @@ async function ciCheckCommand(rootDir, opts) {
59
87
  const shouldComment = opts.comment ?? inCI;
60
88
  const prNumber = detectPrNumber();
61
89
  const pm = await detectPackageManager(rootDir);
62
- const changedFiles = getChangedFiles(rootDir, config.baseBranch);
63
- const prChangesetIds = new Set(changedFiles.filter((f) => /^\.bumpy\/.*\.md$/.test(f) && !f.endsWith("README.md")).map((f) => f.replace(/^\.bumpy\//, "").replace(/\.md$/, "")));
64
- const prChangesets = allChangesets.filter((cs) => prChangesetIds.has(cs.id));
65
- if (prChangesets.length === 0) {
66
- log.info("No changesets found in this PR.");
67
- if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatNoChangesetsComment(detectPrBranch(rootDir), pm), rootDir);
90
+ const { branchBumpFiles: prBumpFiles, branchBumpFileIds: prBumpFileIds } = filterBranchBumpFiles(allBumpFiles, getChangedFiles(rootDir, config.baseBranch));
91
+ if (prBumpFileIds.size > prBumpFiles.length) {
92
+ log.success("Empty bump file found no releases needed.");
93
+ if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatNoBumpFilesComment(detectPrBranch(rootDir), pm), rootDir, opts.patComments);
94
+ return;
95
+ }
96
+ if (prBumpFiles.length === 0) {
97
+ log.info("No bump files found in this PR.");
98
+ if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatNoBumpFilesComment(detectPrBranch(rootDir), pm), rootDir, opts.patComments);
68
99
  if (opts.failOnMissing) process.exit(1);
69
100
  return;
70
101
  }
71
- const plan = assembleReleasePlan(prChangesets, packages, depGraph, config);
72
- log.bold(`${prChangesets.length} changeset(s) → ${plan.releases.length} package(s) to release\n`);
102
+ const plan = assembleReleasePlan(prBumpFiles, packages, depGraph, config);
103
+ log.bold(`${prBumpFiles.length} bump file(s) → ${plan.releases.length} package(s) to release\n`);
73
104
  for (const r of plan.releases) {
74
105
  const tag = r.isDependencyBump ? " (dep)" : r.isCascadeBump ? " (cascade)" : "";
75
106
  console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${tag}`);
76
107
  }
77
- if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatReleasePlanComment(plan, prChangesets, prNumber, detectPrBranch(rootDir), pm), rootDir);
108
+ if (plan.warnings.length > 0) for (const w of plan.warnings) log.warn(w);
109
+ if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatReleasePlanComment(plan, prBumpFiles, prNumber, detectPrBranch(rootDir), pm, plan.warnings), rootDir, opts.patComments);
78
110
  }
79
111
  /**
80
112
  * CI release: either auto-publish or create a version PR.
@@ -85,24 +117,24 @@ async function ciReleaseCommand(rootDir, opts) {
85
117
  ensureGitIdentity(rootDir, config);
86
118
  const { packages } = await discoverWorkspace(rootDir, config);
87
119
  const depGraph = new DependencyGraph(packages);
88
- const changesets = await readChangesets(rootDir);
89
- if (changesets.length === 0) {
90
- log.info("No pending changesets — checking for unpublished packages...");
91
- const { publishCommand } = await import("./publish-D_7RqEYL.mjs");
120
+ const bumpFiles = await readBumpFiles(rootDir);
121
+ if (bumpFiles.length === 0) {
122
+ log.info("No pending bump files — checking for unpublished packages...");
123
+ const { publishCommand } = await import("./publish-CGB4TIKD.mjs");
92
124
  await publishCommand(rootDir, { tag: opts.tag });
93
125
  return;
94
126
  }
95
- const plan = assembleReleasePlan(changesets, packages, depGraph, config);
127
+ const plan = assembleReleasePlan(bumpFiles, packages, depGraph, config);
96
128
  if (plan.releases.length === 0) {
97
- log.info("Changesets found but no packages would be released.");
129
+ log.info("Bump files found but no packages would be released.");
98
130
  return;
99
131
  }
100
- if (opts.mode === "auto-publish") await autoPublish(rootDir, config, opts.tag);
101
- else await createVersionPr(rootDir, plan, config, new Map([...packages.values()].map((p) => [p.name, p.relativeDir])), opts.branch);
132
+ if (opts.mode === "auto-publish") await autoPublish(rootDir, config, plan, opts.tag);
133
+ else await createVersionPr(rootDir, plan, config, new Map([...packages.values()].map((p) => [p.name, p.relativeDir])), opts.branch, opts.patPr);
102
134
  }
103
- async function autoPublish(rootDir, config, tag) {
135
+ async function autoPublish(rootDir, config, plan, tag) {
104
136
  log.step("Running bumpy version...");
105
- const { versionCommand } = await import("./version-cAUkfYPx.mjs");
137
+ const { versionCommand } = await import("./version-BcfidiVX.mjs");
106
138
  await versionCommand(rootDir);
107
139
  log.step("Committing version changes...");
108
140
  runArgs([
@@ -118,13 +150,20 @@ async function autoPublish(rootDir, config, tag) {
118
150
  runArgs([
119
151
  "git",
120
152
  "commit",
121
- "-m",
122
- "Version packages"
153
+ "-F",
154
+ "-"
155
+ ], {
156
+ cwd: rootDir,
157
+ input: await resolveCommitMessage(config.versionCommitMessage, plan, rootDir)
158
+ });
159
+ runArgs([
160
+ "git",
161
+ "push",
162
+ "--no-verify"
123
163
  ], { cwd: rootDir });
124
- runArgs(["git", "push"], { cwd: rootDir });
125
164
  }
126
165
  log.step("Running bumpy publish...");
127
- const { publishCommand } = await import("./publish-D_7RqEYL.mjs");
166
+ const { publishCommand } = await import("./publish-CGB4TIKD.mjs");
128
167
  await publishCommand(rootDir, { tag });
129
168
  }
130
169
  /**
@@ -138,7 +177,8 @@ async function autoPublish(rootDir, config, tag) {
138
177
  * When only the default `GITHUB_TOKEN` is available the push still succeeds,
139
178
  * but PR workflows won't be triggered automatically.
140
179
  */
141
- function pushWithToken(rootDir, branch) {
180
+ function pushWithToken(rootDir, branch, config) {
181
+ if (branch === config.baseBranch || branch === "main" || branch === "master") throw new Error(`Refusing to force-push to "${branch}" — this looks like a base branch, not a version PR branch`);
142
182
  const token = process.env.BUMPY_GH_TOKEN;
143
183
  const repo = process.env.GITHUB_REPOSITORY;
144
184
  const server = process.env.GITHUB_SERVER_URL || "https://github.com";
@@ -162,7 +202,7 @@ function pushWithToken(rootDir, branch) {
162
202
  "config",
163
203
  "--local",
164
204
  "--get-regexp",
165
- "^includeIf\\.gitdir:"
205
+ "^includeif\\.gitdir:"
166
206
  ], { cwd: rootDir });
167
207
  const savedIncludeIfs = [];
168
208
  if (includeIfRaw) for (const line of includeIfRaw.split("\n").filter(Boolean)) {
@@ -194,14 +234,20 @@ function pushWithToken(rootDir, branch) {
194
234
  "origin",
195
235
  authedUrl
196
236
  ], { cwd: rootDir });
197
- runArgs([
198
- "git",
199
- "push",
200
- "-u",
201
- "origin",
202
- branch,
203
- "--force"
204
- ], { cwd: rootDir });
237
+ try {
238
+ runArgs([
239
+ "git",
240
+ "push",
241
+ "-u",
242
+ "origin",
243
+ branch,
244
+ "--force",
245
+ "--no-verify"
246
+ ], { cwd: rootDir });
247
+ } catch (err) {
248
+ const msg = err instanceof Error ? err.message : String(err);
249
+ throw new Error(msg.replaceAll(token, "***"));
250
+ }
205
251
  } finally {
206
252
  if (originalUrl) runArgs([
207
253
  "git",
@@ -233,12 +279,13 @@ function pushWithToken(rootDir, branch) {
233
279
  "-u",
234
280
  "origin",
235
281
  branch,
236
- "--force"
282
+ "--force",
283
+ "--no-verify"
237
284
  ], { cwd: rootDir });
238
285
  if (!token && repo) log.warn("BUMPY_GH_TOKEN is not set — PR checks will not trigger automatically.\n Run `bumpy ci setup` for help.");
239
286
  }
240
287
  }
241
- async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
288
+ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, patPr) {
242
289
  const branch = validateBranchName(branchName || config.versionPr.branch);
243
290
  const baseBranch = validateBranchName(tryRunArgs([
244
291
  "git",
@@ -282,7 +329,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
282
329
  branch
283
330
  ], { cwd: rootDir });
284
331
  log.step("Running bumpy version...");
285
- const { versionCommand } = await import("./version-cAUkfYPx.mjs");
332
+ const { versionCommand } = await import("./version-BcfidiVX.mjs");
286
333
  await versionCommand(rootDir);
287
334
  runArgs([
288
335
  "git",
@@ -309,18 +356,14 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
309
356
  "-"
310
357
  ], {
311
358
  cwd: rootDir,
312
- input: [
313
- "Version packages",
314
- "",
315
- ...plan.releases.map((r) => `${r.name}@${r.newVersion}`)
316
- ].join("\n")
359
+ input: await resolveCommitMessage(config.versionCommitMessage, plan, rootDir)
317
360
  });
318
- pushWithToken(rootDir, branch);
361
+ pushWithToken(rootDir, branch, config);
319
362
  const prBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs);
320
363
  if (existingPr) {
321
364
  const validPr = validatePrNumber(existingPr);
322
365
  log.step(`Updating existing PR #${validPr}...`);
323
- await runArgsAsync([
366
+ await withPatToken(!!patPr, () => runArgsAsync([
324
367
  "gh",
325
368
  "pr",
326
369
  "edit",
@@ -332,12 +375,12 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
332
375
  ], {
333
376
  cwd: rootDir,
334
377
  input: prBody
335
- });
336
- log.success(`Updated PR #${validPr}`);
378
+ }));
379
+ log.success(`🐸 Updated PR #${validPr}`);
337
380
  } else {
338
381
  log.step("Creating version PR...");
339
382
  const prTitle = config.versionPr.title;
340
- const result = await runArgsAsync([
383
+ const result = await withPatToken(!!patPr, () => runArgsAsync([
341
384
  "gh",
342
385
  "pr",
343
386
  "create",
@@ -352,8 +395,9 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
352
395
  ], {
353
396
  cwd: rootDir,
354
397
  input: prBody
355
- });
356
- log.success(`Created PR: ${result}`);
398
+ }));
399
+ log.success(`🐸 Created PR: ${result}`);
400
+ if (!patPr) pushWithToken(rootDir, branch, config);
357
401
  }
358
402
  runArgs([
359
403
  "git",
@@ -362,7 +406,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
362
406
  ], { cwd: rootDir });
363
407
  }
364
408
  const FROG_IMG_BASE = "https://raw.githubusercontent.com/dmno-dev/bumpy/main/images";
365
- function buildAddChangesetLink(prBranch) {
409
+ function buildAddBumpFileLink(prBranch) {
366
410
  if (!prBranch) return null;
367
411
  const repo = process.env.GITHUB_REPOSITORY;
368
412
  if (!repo) return null;
@@ -383,11 +427,11 @@ function pmRunCommand(pm) {
383
427
  if (pm === "yarn") return "yarn bumpy";
384
428
  return "npx bumpy";
385
429
  }
386
- function formatReleasePlanComment(plan, changesets, prNumber, prBranch, pm) {
430
+ function formatReleasePlanComment(plan, bumpFiles, prNumber, prBranch, pm, warnings = []) {
387
431
  const repo = process.env.GITHUB_REPOSITORY;
388
432
  const lines = [];
389
433
  const preamble = [
390
- `<a href="https://github.com/dmno-dev/bumpy"><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>`,
434
+ `<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>`,
391
435
  "",
392
436
  "**The changes in this PR will be included in the next version bump.**",
393
437
  "<br clear=\"left\" />"
@@ -415,10 +459,10 @@ function formatReleasePlanComment(plan, changesets, prNumber, prBranch, pm) {
415
459
  }
416
460
  lines.push("");
417
461
  }
418
- lines.push(`#### Changesets in this PR`);
462
+ lines.push(`#### Bump files in this PR`);
419
463
  lines.push("");
420
- for (const cs of changesets) {
421
- const filename = `${cs.id}.md`;
464
+ for (const bf of bumpFiles) {
465
+ const filename = `${bf.id}.md`;
422
466
  const parts = [`\`${filename}\``];
423
467
  if (repo) {
424
468
  parts.push(`([view diff](https://github.com/${repo}/pull/${prNumber}/files#diff-.bumpy/${filename}))`);
@@ -427,32 +471,38 @@ function formatReleasePlanComment(plan, changesets, prNumber, prBranch, pm) {
427
471
  lines.push(`- ${parts.join(" ")}`);
428
472
  }
429
473
  lines.push("");
430
- const addLink = buildAddChangesetLink(prBranch);
431
- if (addLink) lines.push(`[Click here if you want to add another changeset to this PR](${addLink})\n`);
432
- else lines.push(`To add another changeset, run \`${pmRunCommand(pm)} add\`\n`);
474
+ if (warnings.length > 0) {
475
+ lines.push("#### Warnings");
476
+ lines.push("");
477
+ for (const w of warnings) lines.push(`> ⚠️ ${w}`);
478
+ lines.push("");
479
+ }
480
+ const addLink = buildAddBumpFileLink(prBranch);
481
+ if (addLink) lines.push(`[Click here if you want to add another bump file to this PR](${addLink})\n`);
482
+ else lines.push(`To add another bump file, run \`${pmRunCommand(pm)} add\`\n`);
433
483
  lines.push("---");
434
- lines.push(`_This comment is maintained by [bumpy](https://github.com/dmno-dev/bumpy)._`);
484
+ lines.push(`_This comment is maintained by [bumpy](https://bumpy.varlock.dev)._`);
435
485
  return lines.join("\n");
436
486
  }
437
- function formatNoChangesetsComment(prBranch, pm) {
487
+ function formatNoBumpFilesComment(prBranch, pm) {
438
488
  const runCmd = pmRunCommand(pm);
439
489
  const lines = [
440
- `<a href="https://github.com/dmno-dev/bumpy"><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>`,
490
+ `<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>`,
441
491
  "",
442
- "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 changeset.**",
492
+ "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.**",
443
493
  "<br clear=\"left\" />\n",
444
- "You can add a changeset by running:\n",
494
+ "You can add a bump file by running:\n",
445
495
  "```bash",
446
496
  `${runCmd} add`,
447
497
  "```"
448
498
  ];
449
- const addLink = buildAddChangesetLink(prBranch);
499
+ const addLink = buildAddBumpFileLink(prBranch);
450
500
  if (addLink) {
451
501
  lines.push("");
452
- lines.push(`Or [click here to add a changeset](${addLink}) directly on GitHub.`);
502
+ lines.push(`Or [click here to add a bump file](${addLink}) directly on GitHub.`);
453
503
  }
454
504
  lines.push("\n---");
455
- lines.push(`_This comment is maintained by [bumpy](https://github.com/dmno-dev/bumpy)._`);
505
+ lines.push(`_This comment is maintained by [bumpy](https://bumpy.varlock.dev)._`);
456
506
  return lines.join("\n");
457
507
  }
458
508
  function bumpSectionHeader(type) {
@@ -465,10 +515,7 @@ function buildDiffLinks(pkgDir) {
465
515
  return ` <sub>${[`[package.json](#diff-${sha256Hex(pkgJsonPath)})`, `[CHANGELOG.md](#diff-${sha256Hex(changelogPath)})`].join(" · ")}</sub>`;
466
516
  }
467
517
  function sha256Hex(input) {
468
- const encoder = new TextEncoder();
469
- const hasher = new Bun.CryptoHasher("sha256");
470
- hasher.update(encoder.encode(input));
471
- return hasher.digest("hex");
518
+ return createHash("sha256").update(input).digest("hex");
472
519
  }
473
520
  function formatVersionPrBody(plan, preamble, packageDirs) {
474
521
  const lines = [];
@@ -495,12 +542,12 @@ function formatVersionPrBody(plan, preamble, packageDirs) {
495
542
  const diffLinks = pkgDir ? buildDiffLinks(pkgDir) : "";
496
543
  lines.push(`#### \`${r.name}\` ${r.oldVersion} → **${r.newVersion}**${suffix}${diffLinks}`);
497
544
  lines.push("");
498
- const relevantChangesets = plan.changesets.filter((cs) => r.changesets.includes(cs.id));
499
- if (relevantChangesets.length > 0) {
500
- for (const cs of relevantChangesets) if (cs.summary) {
501
- const csLink = ` ([changeset](#diff-${sha256Hex(`.bumpy/${cs.id}.md`)}))`;
502
- const summaryLines = cs.summary.split("\n");
503
- lines.push(`- ${summaryLines[0]}${csLink}`);
545
+ const relevantBumpFiles = plan.bumpFiles.filter((bf) => r.bumpFiles.includes(bf.id));
546
+ if (relevantBumpFiles.length > 0) {
547
+ for (const bf of relevantBumpFiles) if (bf.summary) {
548
+ const bfLink = ` ([bump file](#diff-${sha256Hex(`.bumpy/${bf.id}.md`)}))`;
549
+ const summaryLines = bf.summary.split("\n");
550
+ lines.push(`- ${summaryLines[0]}${bfLink}`);
504
551
  for (let i = 1; i < summaryLines.length; i++) if (summaryLines[i].trim()) lines.push(` ${summaryLines[i]}`);
505
552
  }
506
553
  } else if (r.isDependencyBump) lines.push("- Updated dependencies");
@@ -511,7 +558,7 @@ function formatVersionPrBody(plan, preamble, packageDirs) {
511
558
  return lines.join("\n");
512
559
  }
513
560
  const COMMENT_MARKER = "<!-- bumpy-release-plan -->";
514
- async function postOrUpdatePrComment(prNumber, body, rootDir) {
561
+ async function postOrUpdatePrComment(prNumber, body, rootDir, usePat = false) {
515
562
  const validPr = validatePrNumber(prNumber);
516
563
  const markedBody = `${COMMENT_MARKER}\n${body}`;
517
564
  try {
@@ -526,7 +573,7 @@ async function postOrUpdatePrComment(prNumber, body, rootDir) {
526
573
  `.comments[] | select(.body | startswith("${COMMENT_MARKER}")) | .url | capture("issuecomment-(?<id>[0-9]+)$") | .id`
527
574
  ], { cwd: rootDir })?.split("\n")[0]?.trim();
528
575
  if (commentId) {
529
- await runArgsAsync([
576
+ await withPatToken(usePat, () => runArgsAsync([
530
577
  "gh",
531
578
  "api",
532
579
  `repos/{owner}/{repo}/issues/comments/${commentId}`,
@@ -537,10 +584,10 @@ async function postOrUpdatePrComment(prNumber, body, rootDir) {
537
584
  ], {
538
585
  cwd: rootDir,
539
586
  input: markedBody
540
- });
587
+ }));
541
588
  log.dim(" Updated PR comment");
542
589
  } else {
543
- await runArgsAsync([
590
+ await withPatToken(usePat, () => runArgsAsync([
544
591
  "gh",
545
592
  "pr",
546
593
  "comment",
@@ -550,7 +597,7 @@ async function postOrUpdatePrComment(prNumber, body, rootDir) {
550
597
  ], {
551
598
  cwd: rootDir,
552
599
  input: markedBody
553
- });
600
+ }));
554
601
  log.dim(" Posted PR comment");
555
602
  }
556
603
  } 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-DcI5TdDE.mjs";
3
- import { o as tryRunArgs } from "./shell-Dj7JRD_q.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-CDRCHrC-.mjs";
2
+ import { t as detectPackageManager } from "./package-manager-Clsmr-9r.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";
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-BkwIEaQg.mjs";
3
+ import { n as findRoot } from "./config-B-Qg3DZH.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-B0q3wEQW.mjs");
29
- await initCommand(rootDir);
28
+ const { initCommand } = await import("./init-DkTPs_WQ.mjs");
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-BjyVIUlr.mjs");
34
+ const { addCommand } = await import("./add-BmNL5VwL.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--Q8yAxQ4.mjs");
45
+ const { statusCommand } = await import("./status-EGYqULJg.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-cAUkfYPx.mjs");
58
- await versionCommand(rootDir);
57
+ const { versionCommand } = await import("./version-BcfidiVX.mjs");
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-Btrsn1qi.mjs");
63
+ const { generateCommand } = await import("./generate-DX46X-rW.mjs");
64
64
  await generateCommand(rootDir, {
65
65
  from: flags.from,
66
66
  dryRun: flags["dry-run"] === true,
@@ -68,15 +68,9 @@ async function main() {
68
68
  });
69
69
  break;
70
70
  }
71
- case "migrate": {
72
- const rootDir = await findRoot();
73
- const { migrateCommand } = await import("./migrate-CfQNwD0T.mjs");
74
- await migrateCommand(rootDir, { force: flags.force === true });
75
- break;
76
- }
77
71
  case "check": {
78
72
  const rootDir = await findRoot();
79
- const { checkCommand } = await import("./check-jIwike9F.mjs");
73
+ const { checkCommand } = await import("./check-BjWF6SJm.mjs");
80
74
  await checkCommand(rootDir);
81
75
  break;
82
76
  }
@@ -85,20 +79,22 @@ async function main() {
85
79
  const subcommand = args[1];
86
80
  const ciFlags = parseFlags(args.slice(2));
87
81
  if (subcommand === "check") {
88
- const { ciCheckCommand } = await import("./ci-D6LQbR38.mjs");
82
+ const { ciCheckCommand } = await import("./ci-DY58ugIi.mjs");
89
83
  await ciCheckCommand(rootDir, {
90
84
  comment: ciFlags.comment !== void 0 ? ciFlags.comment === true : void 0,
91
- failOnMissing: ciFlags["fail-on-missing"] === true
85
+ failOnMissing: ciFlags["fail-on-missing"] === true,
86
+ patComments: ciFlags["pat-comments"] === true
92
87
  });
93
88
  } else if (subcommand === "release") {
94
- const { ciReleaseCommand } = await import("./ci-D6LQbR38.mjs");
89
+ const { ciReleaseCommand } = await import("./ci-DY58ugIi.mjs");
95
90
  await ciReleaseCommand(rootDir, {
96
91
  mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
97
92
  tag: ciFlags.tag,
98
- branch: ciFlags.branch
93
+ branch: ciFlags.branch,
94
+ patPr: ciFlags["pat-pr"] === true
99
95
  });
100
96
  } else if (subcommand === "setup") {
101
- const { ciSetupCommand } = await import("./ci-setup-C6FlOfW5.mjs");
97
+ const { ciSetupCommand } = await import("./ci-setup-BQwktQEe.mjs");
102
98
  await ciSetupCommand(rootDir);
103
99
  } else {
104
100
  log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
@@ -108,7 +104,7 @@ async function main() {
108
104
  }
109
105
  case "publish": {
110
106
  const rootDir = await findRoot();
111
- const { publishCommand } = await import("./publish-D_7RqEYL.mjs");
107
+ const { publishCommand } = await import("./publish-CGB4TIKD.mjs");
112
108
  await publishCommand(rootDir, {
113
109
  dryRun: flags["dry-run"] === true,
114
110
  tag: flags.tag,
@@ -122,7 +118,7 @@ async function main() {
122
118
  const subcommand = args[1];
123
119
  const aiFlags = parseFlags(args.slice(2));
124
120
  if (subcommand === "setup") {
125
- const { aiSetupCommand } = await import("./ai-CQhUyHAG.mjs");
121
+ const { aiSetupCommand } = await import("./ai-sMYUf3lP.mjs");
126
122
  await aiSetupCommand(rootDir, { target: aiFlags.target });
127
123
  } else {
128
124
  log.error(`Unknown ai subcommand: ${subcommand}. Use "ai setup".`);
@@ -132,7 +128,7 @@ async function main() {
132
128
  }
133
129
  case "--version":
134
130
  case "-v":
135
- console.log(`bumpy 0.0.2`);
131
+ console.log(`bumpy 1.1.0`);
136
132
  break;
137
133
  case "help":
138
134
  case "--help":
@@ -152,41 +148,40 @@ async function main() {
152
148
  }
153
149
  function printHelp() {
154
150
  console.log(`
155
- ${colorize(`🐸 bumpy v0.0.2`, "bold")} - Modern monorepo versioning
151
+ ${colorize(`🐸 bumpy v1.1.0`, "bold")} - Modern monorepo versioning
156
152
 
157
153
  Usage: bumpy <command> [options]
158
154
 
159
155
  Commands:
160
- init Initialize .bumpy/ directory
161
- add Create a new changeset
162
- generate Generate changeset from conventional commits
156
+ init [--force] Initialize .bumpy/ (migrates from .changeset/ if found)
157
+ add Create a new bump file
158
+ generate Generate bump file from branch commits
163
159
  status Show pending releases
164
- check Verify changed packages have changesets (for pre-push hooks)
165
- version Apply changesets and bump versions
160
+ check Verify changed packages have bump files (for pre-push hooks)
161
+ version [--commit] Apply bump files and bump versions
166
162
  publish Publish versioned packages
167
163
  ci check PR check — report pending releases, comment on PR
168
164
  ci release Release — create version PR or auto-publish
169
165
  ci setup Set up a token for triggering CI on version PRs
170
- migrate Migrate from .changeset/ to .bumpy/
171
- ai setup Install AI skill for creating changesets
166
+ ai setup Install AI skill for creating bump files
172
167
 
173
168
  Add options:
174
169
  --packages <list> Package bumps (e.g., "pkg-a:minor,pkg-b:patch")
175
- --message <text> Changeset summary
176
- --name <name> Changeset filename
177
- --empty Create an empty changeset
170
+ --message <text> Bump file summary
171
+ --name <name> Bump file filename
172
+ --empty Create an empty bump file
178
173
 
179
174
  Generate options:
180
- --from <ref> Git ref to scan from (default: last version tag)
181
- --dry-run Preview without creating a changeset
182
- --name <name> Changeset filename
175
+ --from <ref> Git ref to scan from (default: branch point from baseBranch)
176
+ --dry-run Preview without creating a bump file
177
+ --name <name> Bump file filename
183
178
 
184
179
  Status options:
185
- --json Output as JSON (includes dirs, changesets, packageNames)
180
+ --json Output as JSON (includes dirs, bumpFiles, packageNames)
186
181
  --packages Output only package names, one per line
187
182
  --bump <types> Filter by bump type (e.g., "major", "minor,patch")
188
183
  --filter <names> Filter by package name/glob (e.g., "@myorg/*")
189
- --verbose Show changeset details
184
+ --verbose Show bump file details
190
185
 
191
186
  Publish options:
192
187
  --dry-run Preview without publishing
@@ -196,7 +191,7 @@ function printHelp() {
196
191
 
197
192
  CI check options:
198
193
  --comment Force PR comment on/off (auto-detected in CI)
199
- --fail-on-missing Exit 1 if no changesets found
194
+ --fail-on-missing Exit 1 if no bump files found
200
195
 
201
196
  CI release options:
202
197
  --auto-publish Version + publish directly (default: create version PR)
@@ -206,7 +201,7 @@ function printHelp() {
206
201
  AI setup options:
207
202
  --target <tool> Target AI tool: opencode, cursor, codex
208
203
 
209
- ${colorize("https://github.com/dmno-dev/bumpy", "dim")}
204
+ ${colorize("https://bumpy.varlock.dev", "dim")}
210
205
  `);
211
206
  }
212
207
  main();