@varlock/bumpy 1.6.0 → 1.7.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.
Files changed (31) hide show
  1. package/dist/{add-u3h5BH8e.mjs → add-CEOjsSPY.mjs} +44 -85
  2. package/dist/{ai-C66IfTzs.mjs → ai-Bbe56gBt.mjs} +2 -2
  3. package/dist/{apply-release-plan-DNpoi7cS.mjs → apply-release-plan-CAx8E9MJ.mjs} +3 -3
  4. package/dist/{bump-file-CoaSxqne.mjs → bump-file-4cnuDyfW.mjs} +110 -6
  5. package/dist/{changelog-_gBjowzN.mjs → changelog-BubwrZfr.mjs} +3 -3
  6. package/dist/{changelog-github-B_e9JWku.mjs → changelog-github-BAUnp3ic.mjs} +2 -2
  7. package/dist/{check-B3M2S2wx.mjs → check-w-edwiNw.mjs} +9 -6
  8. package/dist/{ci-h8s-soA6.mjs → ci-Di_Tur0k.mjs} +102 -17
  9. package/dist/{ci-setup-DWxrdSK6.mjs → ci-setup-DKjyiF2-.mjs} +4 -4
  10. package/dist/{clack-CJT1JFFa.mjs → clack-W95rXis0.mjs} +6 -127
  11. package/dist/cli.mjs +20 -16
  12. package/dist/{config-D13G4-R8.mjs → config-BcmlSJJd.mjs} +2 -2
  13. package/dist/{fs-DnDogVn-.mjs → fs-CBXKZhoU.mjs} +1 -1
  14. package/dist/{generate-CxKXOBNP.mjs → generate-DU27B8co.mjs} +7 -8
  15. package/dist/{git-ukq7VTuZ.mjs → git-nTR-JccX.mjs} +1 -1
  16. package/dist/index.mjs +6 -9
  17. package/dist/{init-CUIw0jg8.mjs → init-Cs6amsw5.mjs} +14 -6
  18. package/dist/{logger-C2dEe5Su.mjs → logger-BgksGFuf.mjs} +3 -1
  19. package/dist/{package-manager-CClZtIHP.mjs → package-manager-BQPwXwu5.mjs} +1 -1
  20. package/dist/{publish-CXJ0Ggkq.mjs → publish-BJ-Cs0TR.mjs} +75 -13
  21. package/dist/{publish-pipeline-C1slMaJV.mjs → publish-pipeline-BsxtJ3-A.mjs} +6 -6
  22. package/dist/{semver-DfQyVLM_.mjs → release-plan-iZvGo-SB.mjs} +312 -2
  23. package/dist/{shell-u3bYGxNy.mjs → shell-C8KgKnMQ.mjs} +1 -1
  24. package/dist/{status-lS56U6F_.mjs → status-CpGvpJBm.mjs} +8 -10
  25. package/dist/{version-BjjnO2ii.mjs → version-nJ0vhPWw.mjs} +8 -10
  26. package/package.json +1 -1
  27. package/dist/dep-graph-E-9-eQ2J.mjs +0 -64
  28. package/dist/release-plan-C1Lz9rl_.mjs +0 -249
  29. package/dist/workspace-Yt7qwsML.mjs +0 -109
  30. /package/dist/{commit-message-3e4KhzFV.mjs → commit-message-CSWVKPJ-.mjs} +0 -0
  31. /package/dist/{names-CBy7d8K_.mjs → names-COooXAFg.mjs} +0 -0
@@ -1,19 +1,18 @@
1
- import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
2
- import { n as exists, t as ensureDir } from "./fs-DnDogVn-.mjs";
3
- import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir, s as matchGlob } from "./config-D13G4-R8.mjs";
4
- import { n as discoverWorkspace, t as discoverPackages } from "./workspace-Yt7qwsML.mjs";
5
- import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
6
- import { i as writeBumpFile } from "./bump-file-CoaSxqne.mjs";
7
- import { r as getChangedFiles } from "./git-ukq7VTuZ.mjs";
8
- import { c as ot, d as yt, i as _t, l as pt, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-CJT1JFFa.mjs";
9
- import { n as slugify, t as randomName } from "./names-CBy7d8K_.mjs";
10
- import { findChangedPackages, t as require_picomatch } from "./check-B3M2S2wx.mjs";
1
+ import { n as log, r as require_picocolors, s as __toESM } from "./logger-BgksGFuf.mjs";
2
+ import { n as exists, t as ensureDir } from "./fs-CBXKZhoU.mjs";
3
+ import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir } from "./config-BcmlSJJd.mjs";
4
+ import { a as discoverPackages, i as writeBumpFile, o as discoverWorkspace, r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-4cnuDyfW.mjs";
5
+ import { r as getChangedFiles } from "./git-nTR-JccX.mjs";
6
+ import { l as pt, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-W95rXis0.mjs";
7
+ import { n as slugify, t as randomName } from "./names-COooXAFg.mjs";
8
+ import { n as findChangedPackages, r as require_picomatch } from "./check-w-edwiNw.mjs";
11
9
  import { relative, resolve } from "node:path";
12
10
  import * as readline from "node:readline";
13
11
  //#region src/prompts/bump-select.ts
14
12
  var import_picomatch = /* @__PURE__ */ __toESM(require_picomatch(), 1);
15
13
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
16
14
  const LEVELS = [
15
+ "skip",
17
16
  "none",
18
17
  "patch",
19
18
  "minor",
@@ -38,7 +37,7 @@ async function bumpSelectPrompt(items) {
38
37
  })).filter(({ item }) => !item.changed);
39
38
  const displayOrder = [...changedEntries, ...unchangedEntries];
40
39
  let cursor = 0;
41
- const levels = items.map((item) => item.changed ? "patch" : "none");
40
+ const levels = items.map((item) => item.initialLevel !== void 0 ? item.initialLevel : item.changed ? "patch" : "skip");
42
41
  return new Promise((resolve) => {
43
42
  const { stdin, stdout } = process;
44
43
  const rl = readline.createInterface({
@@ -55,14 +54,14 @@ async function bumpSelectPrompt(items) {
55
54
  const lines = [];
56
55
  if (final) {
57
56
  lines.push(`${import_picocolors.default.green("◇")} Bump levels selected`);
58
- const selected = displayOrder.filter(({ idx }) => levels[idx] !== "none");
59
- if (selected.length === 0) lines.push(`${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("(none)")}`);
57
+ const selected = displayOrder.filter(({ idx }) => levels[idx] !== "skip");
58
+ if (selected.length === 0) lines.push(`${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("(none selected)")}`);
60
59
  else for (const { item, idx } of selected) lines.push(`${import_picocolors.default.dim("│")} ${import_picocolors.default.cyan(item.name)} ${import_picocolors.default.dim("→")} ${import_picocolors.default.bold(levels[idx])}`);
61
60
  lines.push(import_picocolors.default.dim("│"));
62
61
  } else {
63
62
  lines.push(`${import_picocolors.default.cyan("◆")} Select bump levels`);
64
63
  lines.push(`${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("↑/↓ navigate · ←/→ change level · enter to confirm")}`);
65
- lines.push(`${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("0 clear current · x clear all · r reset all to defaults")}`);
64
+ lines.push(`${import_picocolors.default.dim("│")} ${import_picocolors.default.dim("0 skip current · x skip all · r reset all to defaults")}`);
66
65
  lines.push(import_picocolors.default.dim("│"));
67
66
  let displayIdx = 0;
68
67
  if (changedEntries.length > 0) {
@@ -81,7 +80,7 @@ async function bumpSelectPrompt(items) {
81
80
  }
82
81
  }
83
82
  lines.push(import_picocolors.default.dim("│"));
84
- const selectedCount = levels.filter((l) => l !== "none").length;
83
+ const selectedCount = levels.filter((l) => l !== "skip").length;
85
84
  lines.push(`${import_picocolors.default.dim("│")} ${import_picocolors.default.dim(`${selectedCount} package${selectedCount !== 1 ? "s" : ""} selected`)}`);
86
85
  lines.push(`${import_picocolors.default.dim("└")}`);
87
86
  }
@@ -90,6 +89,7 @@ async function bumpSelectPrompt(items) {
90
89
  renderedLines = lines.length;
91
90
  }
92
91
  function cleanup() {
92
+ stdin.removeListener("keypress", onKeypress);
93
93
  rl.close();
94
94
  stdout.write("\x1B[?25h");
95
95
  if (stdin.isTTY) stdin.setRawMode(false);
@@ -99,10 +99,11 @@ async function bumpSelectPrompt(items) {
99
99
  cleanup();
100
100
  resolve(result);
101
101
  }
102
+ readline.emitKeypressEvents(stdin, rl);
102
103
  if (stdin.isTTY) stdin.setRawMode(true);
103
104
  stdin.resume();
104
105
  render();
105
- stdin.on("keypress", (_str, key) => {
106
+ function onKeypress(_str, key) {
106
107
  if (!key) return;
107
108
  if (key.name === "escape" || key.ctrl && key.name === "c") {
108
109
  cleanup();
@@ -116,7 +117,7 @@ async function bumpSelectPrompt(items) {
116
117
  }
117
118
  if (key.name === "return") {
118
119
  const results = [];
119
- for (let i = 0; i < items.length; i++) if (levels[i] !== "none") results.push({
120
+ for (let i = 0; i < items.length; i++) if (levels[i] !== "skip") results.push({
120
121
  name: items[i].name,
121
122
  type: levels[i]
122
123
  });
@@ -135,12 +136,12 @@ async function bumpSelectPrompt(items) {
135
136
  if (currentLevel > 0) levels[entry.idx] = LEVELS[currentLevel - 1];
136
137
  } else if (_str === "0" || key.name === "backspace") {
137
138
  const entry = displayOrder[cursor];
138
- levels[entry.idx] = "none";
139
- } else if (_str === "r") for (let i = 0; i < items.length; i++) levels[i] = items[i].changed ? "patch" : "none";
140
- else if (_str === "x") for (let i = 0; i < items.length; i++) levels[i] = "none";
139
+ levels[entry.idx] = "skip";
140
+ } else if (_str === "r") for (let i = 0; i < items.length; i++) levels[i] = items[i].initialLevel !== void 0 ? items[i].initialLevel : items[i].changed ? "patch" : "skip";
141
+ else if (_str === "x") for (let i = 0; i < items.length; i++) levels[i] = "skip";
141
142
  render();
142
- });
143
- readline.emitKeypressEvents(stdin, rl);
143
+ }
144
+ stdin.on("keypress", onKeypress);
144
145
  });
145
146
  }
146
147
  function formatRow(item, level, focused) {
@@ -148,13 +149,15 @@ function formatRow(item, level, focused) {
148
149
  }
149
150
  function formatLevel(level, focused) {
150
151
  if (!focused) {
151
- if (level === "none") return import_picocolors.default.dim("·");
152
+ if (level === "skip") return import_picocolors.default.dim("·");
153
+ if (level === "none") return import_picocolors.default.dim("none");
152
154
  if (level === "major") return import_picocolors.default.red(level);
153
155
  if (level === "minor") return import_picocolors.default.yellow(level);
154
156
  return import_picocolors.default.green(level);
155
157
  }
156
158
  return `◄ ${LEVELS.map((l) => {
157
159
  if (l === level) {
160
+ if (l === "skip") return import_picocolors.default.bold(import_picocolors.default.dim("[skip]"));
158
161
  if (l === "none") return import_picocolors.default.bold(import_picocolors.default.dim("[none]"));
159
162
  if (l === "major") return import_picocolors.default.bold(import_picocolors.default.red(`[${l}]`));
160
163
  if (l === "minor") return import_picocolors.default.bold(import_picocolors.default.yellow(`[${l}]`));
@@ -165,20 +168,6 @@ function formatLevel(level, focused) {
165
168
  }
166
169
  //#endregion
167
170
  //#region src/commands/add.ts
168
- const CASCADE_CHOICES = [
169
- {
170
- label: "patch",
171
- value: "patch"
172
- },
173
- {
174
- label: "minor",
175
- value: "minor"
176
- },
177
- {
178
- label: "major",
179
- value: "major"
180
- }
181
- ];
182
171
  async function addCommand(rootDir, opts) {
183
172
  const config = await loadConfig(rootDir);
184
173
  const bumpyDir = getBumpyDir(rootDir);
@@ -186,7 +175,7 @@ async function addCommand(rootDir, opts) {
186
175
  if (opts.empty) {
187
176
  const filename = opts.name ? slugify(opts.name) : randomName();
188
177
  const filePath = resolve(bumpyDir, `${filename}.md`);
189
- const { writeText } = await import("./fs-DnDogVn-.mjs").then((n) => n.r);
178
+ const { writeText } = await import("./fs-CBXKZhoU.mjs").then((n) => n.r);
190
179
  await writeText(filePath, "---\n---\n");
191
180
  log.success(`🐸 Created empty bump file: .bumpy/${filename}.md`);
192
181
  return;
@@ -220,7 +209,6 @@ async function addCommand(rootDir, opts) {
220
209
  } else {
221
210
  mt(import_picocolors.default.bgCyan(import_picocolors.default.black(" bumpy add ")));
222
211
  const pkgs = await discoverPackages(rootDir, config);
223
- const depGraph = new DependencyGraph(pkgs);
224
212
  if (pkgs.size === 0) {
225
213
  pt("No managed packages found in this workspace.");
226
214
  process.exit(1);
@@ -240,11 +228,19 @@ async function addCommand(rootDir, opts) {
240
228
  if (matchers.get(name)(relToPackage)) changedPackageNames.add(name);
241
229
  }
242
230
  }
243
- const bumpSelectResult = await bumpSelectPrompt([...pkgs.values()].map((pkg) => ({
244
- name: pkg.name,
245
- version: pkg.version,
246
- changed: changedPackageNames.has(pkg.name)
247
- })));
231
+ const { bumpFiles: allBumpFiles } = await readBumpFiles(rootDir);
232
+ const { branchBumpFiles } = filterBranchBumpFiles(allBumpFiles, changedFiles, rootDir);
233
+ const alreadyCoveredPackages = /* @__PURE__ */ new Map();
234
+ for (const bf of branchBumpFiles) for (const release of bf.releases) alreadyCoveredPackages.set(release.name, release.type === "none" ? "none" : release.type);
235
+ const bumpSelectResult = await bumpSelectPrompt([...pkgs.values()].map((pkg) => {
236
+ const item = {
237
+ name: pkg.name,
238
+ version: pkg.version,
239
+ changed: changedPackageNames.has(pkg.name)
240
+ };
241
+ if (alreadyCoveredPackages.has(pkg.name)) item.initialLevel = "skip";
242
+ return item;
243
+ }));
248
244
  if (typeof bumpSelectResult === "symbol") {
249
245
  pt("Aborted");
250
246
  process.exit(0);
@@ -254,47 +250,10 @@ async function addCommand(rootDir, opts) {
254
250
  pt("No packages selected.");
255
251
  process.exit(0);
256
252
  }
257
- releases = [];
258
- for (const { name, type: bumpType } of bumpSelections) {
259
- const release = {
260
- name,
261
- type: bumpType
262
- };
263
- {
264
- const dependents = depGraph.getDependents(name);
265
- const cascadeTargets = pkgs.get(name).bumpy?.cascadeTo;
266
- if (dependents.length > 0 || cascadeTargets) {
267
- if (unwrap(await ot({
268
- message: `${import_picocolors.default.cyan(name)} has ${import_picocolors.default.bold(String(dependents.length))} dependents. Specify explicit cascades?`,
269
- initialValue: false
270
- }))) {
271
- const allTargets = /* @__PURE__ */ new Set();
272
- for (const d of dependents) allTargets.add(d.name);
273
- if (cascadeTargets) {
274
- for (const pattern of Object.keys(cascadeTargets)) for (const [pName] of pkgs) if (matchGlob(pName, pattern)) allTargets.add(pName);
275
- }
276
- const cascadeSelected = unwrap(await yt({
277
- message: "Which packages should cascade?",
278
- options: [...allTargets].map((n) => ({
279
- label: n,
280
- value: n
281
- })),
282
- required: false
283
- }));
284
- if (cascadeSelected.length > 0) {
285
- const cascadeBump = unwrap(await _t({
286
- message: "Cascade bump type",
287
- options: CASCADE_CHOICES
288
- }));
289
- const cascade = {};
290
- for (const target of cascadeSelected) cascade[target] = cascadeBump;
291
- release.cascade = cascade;
292
- }
293
- }
294
- }
295
- }
296
- releases.push(release);
297
- }
253
+ releases = bumpSelections.map(({ name, type }) => ({
254
+ name,
255
+ type
256
+ }));
298
257
  summary = unwrap(await Ot({
299
258
  message: "Summary (what changed and why)",
300
259
  placeholder: "A short description of the change",
@@ -1,5 +1,5 @@
1
- import { n as log } from "./logger-C2dEe5Su.mjs";
2
- import { f as writeText, n as exists, t as ensureDir } from "./fs-DnDogVn-.mjs";
1
+ import { n as log } from "./logger-BgksGFuf.mjs";
2
+ import { f as writeText, n as exists, t as ensureDir } from "./fs-CBXKZhoU.mjs";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import { execSync } from "node:child_process";
@@ -1,6 +1,6 @@
1
- import { a as readJson, c as removeFile, f as writeText, i as listFiles, l as updateJsonFields, n as exists, s as readText, u as updateJsonNestedField } from "./fs-DnDogVn-.mjs";
2
- import { r as getBumpyDir } from "./config-D13G4-R8.mjs";
3
- import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry } from "./changelog-_gBjowzN.mjs";
1
+ import { a as readJson, c as removeFile, f as writeText, i as listFiles, l as updateJsonFields, n as exists, s as readText, u as updateJsonNestedField } from "./fs-CBXKZhoU.mjs";
2
+ import { r as getBumpyDir } from "./config-BcmlSJJd.mjs";
3
+ import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry } from "./changelog-BubwrZfr.mjs";
4
4
  import { resolve } from "node:path";
5
5
  //#region src/core/apply-release-plan.ts
6
6
  /** Apply the release plan: bump versions, update changelogs, delete bump files */
@@ -1,9 +1,113 @@
1
- import { f as writeText, i as listFiles, s as readText } from "./fs-DnDogVn-.mjs";
2
- import { r as getBumpyDir } from "./config-D13G4-R8.mjs";
3
- import { i as jsYaml } from "./package-manager-CClZtIHP.mjs";
4
- import { s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
5
- import { resolve } from "node:path";
1
+ import { a as readJson, f as writeText, i as listFiles, n as exists, s as readText } from "./fs-CBXKZhoU.mjs";
2
+ import { i as isPackageManaged, o as loadPackageConfig, r as getBumpyDir } from "./config-BcmlSJJd.mjs";
3
+ import { i as jsYaml, n as detectWorkspaces } from "./package-manager-BQPwXwu5.mjs";
4
+ import { s as tryRunArgs } from "./shell-C8KgKnMQ.mjs";
5
+ import { relative, resolve } from "node:path";
6
+ import { readdir, stat } from "node:fs/promises";
6
7
  import { existsSync } from "node:fs";
8
+ //#region src/core/workspace.ts
9
+ /** Discover all workspace packages and catalogs in a monorepo or single-package repo */
10
+ async function discoverWorkspace(rootDir, config) {
11
+ const { globs, catalogs } = await detectWorkspaces(rootDir);
12
+ const packages = /* @__PURE__ */ new Map();
13
+ if (globs.length === 0) {
14
+ const pkg = await loadWorkspacePackage(rootDir, rootDir, config);
15
+ if (pkg && isPackageManaged(pkg.name, pkg.private, config, pkg.bumpy)) packages.set(pkg.name, pkg);
16
+ } else for (const glob of globs) {
17
+ const dirs = await resolveGlob(rootDir, glob);
18
+ for (const dir of dirs) {
19
+ const pkg = await loadWorkspacePackage(dir, rootDir, config);
20
+ if (pkg) {
21
+ if (!isPackageManaged(pkg.name, pkg.private, config, pkg.bumpy)) continue;
22
+ packages.set(pkg.name, pkg);
23
+ }
24
+ }
25
+ }
26
+ return {
27
+ packages,
28
+ catalogs
29
+ };
30
+ }
31
+ /** Convenience wrapper that returns just packages (backwards compat) */
32
+ async function discoverPackages(rootDir, config) {
33
+ const { packages } = await discoverWorkspace(rootDir, config);
34
+ return packages;
35
+ }
36
+ /** Resolve a workspace glob pattern to directories containing package.json */
37
+ async function resolveGlob(rootDir, pattern) {
38
+ return expandGlob(rootDir, pattern.split("/"));
39
+ }
40
+ async function expandGlob(baseDir, parts) {
41
+ if (parts.length === 0) {
42
+ if (await exists(resolve(baseDir, "package.json"))) return [baseDir];
43
+ return [];
44
+ }
45
+ const [current, ...rest] = parts;
46
+ if (current === "*") {
47
+ const entries = await safeReaddir(baseDir);
48
+ const results = [];
49
+ for (const entry of entries) {
50
+ const entryPath = resolve(baseDir, entry);
51
+ if (await isDirectory(entryPath)) results.push(...await expandGlob(entryPath, rest));
52
+ }
53
+ return results;
54
+ } else if (current === "**") {
55
+ const results = [];
56
+ results.push(...await expandGlob(baseDir, rest));
57
+ const entries = await safeReaddir(baseDir);
58
+ for (const entry of entries) {
59
+ if (entry.startsWith(".") || entry === "node_modules") continue;
60
+ const entryPath = resolve(baseDir, entry);
61
+ if (await isDirectory(entryPath)) results.push(...await expandGlob(entryPath, parts));
62
+ }
63
+ return results;
64
+ } else {
65
+ const next = resolve(baseDir, current);
66
+ if (await isDirectory(next)) return expandGlob(next, rest);
67
+ return [];
68
+ }
69
+ }
70
+ async function safeReaddir(dir) {
71
+ try {
72
+ return await readdir(dir);
73
+ } catch {
74
+ return [];
75
+ }
76
+ }
77
+ async function isDirectory(path) {
78
+ try {
79
+ return (await stat(path)).isDirectory();
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+ async function loadWorkspacePackage(dir, rootDir, config) {
85
+ const pkgPath = resolve(dir, "package.json");
86
+ if (!await exists(pkgPath)) return null;
87
+ let pkg;
88
+ try {
89
+ pkg = await readJson(pkgPath);
90
+ } catch {
91
+ return null;
92
+ }
93
+ const name = pkg.name;
94
+ if (!name) return null;
95
+ const bumpy = await loadPackageConfig(dir, config, name);
96
+ return {
97
+ name,
98
+ version: pkg.version || "0.0.0",
99
+ dir: resolve(dir),
100
+ relativeDir: relative(rootDir, dir) || ".",
101
+ packageJson: pkg,
102
+ private: !!pkg.private,
103
+ dependencies: pkg.dependencies || {},
104
+ devDependencies: pkg.devDependencies || {},
105
+ peerDependencies: pkg.peerDependencies || {},
106
+ optionalDependencies: pkg.optionalDependencies || {},
107
+ bumpy
108
+ };
109
+ }
110
+ //#endregion
7
111
  //#region src/core/bump-file.ts
8
112
  const VALID_BUMP_TYPES = new Set([
9
113
  "major",
@@ -205,4 +309,4 @@ function filterBranchBumpFiles(allBumpFiles, changedFiles, rootDir, parseErrors
205
309
  };
206
310
  }
207
311
  //#endregion
208
- export { writeBumpFile as i, parseBumpFile as n, readBumpFiles as r, filterBranchBumpFiles as t };
312
+ export { discoverPackages as a, writeBumpFile as i, parseBumpFile as n, discoverWorkspace as o, readBumpFiles as r, filterBranchBumpFiles as t };
@@ -1,4 +1,4 @@
1
- import { n as log } from "./logger-C2dEe5Su.mjs";
1
+ import { n as log } from "./logger-BgksGFuf.mjs";
2
2
  import { c as maxBump, t as BUMP_LEVELS } from "./types-BX4pfmKh.mjs";
3
3
  import { relative, resolve } from "node:path";
4
4
  import { realpathSync } from "node:fs";
@@ -45,7 +45,7 @@ const defaultFormatter = (ctx) => {
45
45
  const BUILTIN_FORMATTERS = {
46
46
  default: defaultFormatter,
47
47
  github: async () => {
48
- const { createGithubFormatter } = await import("./changelog-github-B_e9JWku.mjs");
48
+ const { createGithubFormatter } = await import("./changelog-github-BAUnp3ic.mjs");
49
49
  return createGithubFormatter();
50
50
  }
51
51
  };
@@ -56,7 +56,7 @@ const BUILTIN_FORMATTERS = {
56
56
  async function loadFormatter(changelog, rootDir) {
57
57
  const [name, options] = Array.isArray(changelog) ? changelog : [changelog, {}];
58
58
  if (name === "github") {
59
- const { createGithubFormatter } = await import("./changelog-github-B_e9JWku.mjs");
59
+ const { createGithubFormatter } = await import("./changelog-github-BAUnp3ic.mjs");
60
60
  return createGithubFormatter(options);
61
61
  }
62
62
  if (typeof name === "string" && BUILTIN_FORMATTERS[name]) {
@@ -1,6 +1,6 @@
1
1
  import { c as maxBump } from "./types-BX4pfmKh.mjs";
2
- import { s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
3
- import { o as sortBumpFilesByType, r as getBumpTypeForPackage } from "./changelog-_gBjowzN.mjs";
2
+ import { s as tryRunArgs } from "./shell-C8KgKnMQ.mjs";
3
+ import { o as sortBumpFilesByType, r as getBumpTypeForPackage } from "./changelog-BubwrZfr.mjs";
4
4
  //#region src/core/changelog-github.ts
5
5
  /** Authors filtered from "Thanks" attribution by default (e.g. bots) */
6
6
  /** Authors filtered from "Thanks" attribution by default (e.g. AI/automation bots) */
@@ -1,8 +1,7 @@
1
- import { i as __commonJSMin, n as log, o as __toESM, t as colorize } from "./logger-C2dEe5Su.mjs";
2
- import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir } from "./config-D13G4-R8.mjs";
3
- import { n as discoverWorkspace } from "./workspace-Yt7qwsML.mjs";
4
- import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-CoaSxqne.mjs";
5
- import { a as getFileStatuses, r as getChangedFiles } from "./git-ukq7VTuZ.mjs";
1
+ import { a as __exportAll, i as __commonJSMin, n as log, s as __toESM, t as colorize } from "./logger-BgksGFuf.mjs";
2
+ import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir } from "./config-BcmlSJJd.mjs";
3
+ import { o as discoverWorkspace, r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-4cnuDyfW.mjs";
4
+ import { a as getFileStatuses, r as getChangedFiles } from "./git-nTR-JccX.mjs";
6
5
  import { relative } from "node:path";
7
6
  //#region ../../node_modules/.bun/picomatch@4.0.4/node_modules/picomatch/lib/constants.js
8
7
  var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -1873,6 +1872,10 @@ var require_picomatch = /* @__PURE__ */ __commonJSMin(((exports, module) => {
1873
1872
  }));
1874
1873
  //#endregion
1875
1874
  //#region src/commands/check.ts
1875
+ var check_exports = /* @__PURE__ */ __exportAll({
1876
+ checkCommand: () => checkCommand,
1877
+ findChangedPackages: () => findChangedPackages
1878
+ });
1876
1879
  var import_picomatch = /* @__PURE__ */ __toESM(require_picomatch(), 1);
1877
1880
  /**
1878
1881
  * Local check: detect which packages have changed on this branch
@@ -1996,4 +1999,4 @@ async function findChangedPackages(changedFiles, packages, rootDir, config) {
1996
1999
  return [...changed];
1997
2000
  }
1998
2001
  //#endregion
1999
- export { checkCommand, findChangedPackages, require_picomatch as t };
2002
+ export { findChangedPackages as n, require_picomatch as r, check_exports as t };
@@ -1,15 +1,14 @@
1
- import { n as log, t as colorize } from "./logger-C2dEe5Su.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-Yt7qwsML.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-C1Lz9rl_.mjs";
9
- import { r as getChangedFiles } from "./git-ukq7VTuZ.mjs";
10
- import { t as randomName } from "./names-CBy7d8K_.mjs";
11
- import { findChangedPackages } from "./check-B3M2S2wx.mjs";
12
- import { t as resolveCommitMessage } from "./commit-message-3e4KhzFV.mjs";
1
+ import { n as log, t as colorize } from "./logger-BgksGFuf.mjs";
2
+ import { a as loadConfig } from "./config-BcmlSJJd.mjs";
3
+ import { t as detectPackageManager } from "./package-manager-BQPwXwu5.mjs";
4
+ import { o as discoverWorkspace, r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-4cnuDyfW.mjs";
5
+ import { a as DependencyGraph, t as assembleReleasePlan } from "./release-plan-iZvGo-SB.mjs";
6
+ import { n as runArgs, r as runArgsAsync, s as tryRunArgs } from "./shell-C8KgKnMQ.mjs";
7
+ import { r as getChangedFiles } from "./git-nTR-JccX.mjs";
8
+ import { t as randomName } from "./names-COooXAFg.mjs";
9
+ import { n as findChangedPackages } from "./check-w-edwiNw.mjs";
10
+ import { t as resolveCommitMessage } from "./commit-message-CSWVKPJ-.mjs";
11
+ import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
13
12
  import { createHash } from "node:crypto";
14
13
  //#region src/commands/ci.ts
15
14
  /**
@@ -124,6 +123,92 @@ async function ciCheckCommand(rootDir, opts) {
124
123
  if (willFail) process.exit(1);
125
124
  }
126
125
  }
126
+ /** Path (relative to rootDir) where ci plan caches its output for ci release to reuse */
127
+ const CI_PLAN_CACHE_PATH = "node_modules/.cache/bumpy/ci-plan.json";
128
+ /**
129
+ * CI plan: report what `ci release` would do, without acting.
130
+ * Outputs JSON to stdout and sets GitHub Actions outputs when detected.
131
+ */
132
+ async function ciPlanCommand(rootDir) {
133
+ const config = await loadConfig(rootDir);
134
+ const { packages } = await discoverWorkspace(rootDir, config);
135
+ const depGraph = new DependencyGraph(packages);
136
+ const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir);
137
+ if (parseErrors.length > 0) {
138
+ for (const err of parseErrors) log.error(err);
139
+ throw new Error("Bump file parse errors must be fixed before planning.");
140
+ }
141
+ let output;
142
+ if (bumpFiles.length > 0) {
143
+ const plan = assembleReleasePlan(bumpFiles, packages, depGraph, config);
144
+ output = {
145
+ mode: "version-pr",
146
+ bumpFiles: plan.bumpFiles.map((bf) => ({
147
+ id: bf.id,
148
+ summary: bf.summary,
149
+ releases: bf.releases.map((r) => ({
150
+ name: r.name,
151
+ type: r.type
152
+ }))
153
+ })),
154
+ releases: plan.releases.map((r) => formatPlanRelease(r, packages, config)),
155
+ packageNames: plan.releases.map((r) => r.name)
156
+ };
157
+ } else {
158
+ const { findUnpublishedPackages } = await import("./publish-BJ-Cs0TR.mjs");
159
+ const unpublished = await findUnpublishedPackages(packages, config);
160
+ if (unpublished.length > 0) output = {
161
+ mode: "publish",
162
+ bumpFiles: [],
163
+ releases: unpublished.map((r) => formatPlanRelease(r, packages, config)),
164
+ packageNames: unpublished.map((r) => r.name)
165
+ };
166
+ else output = {
167
+ mode: "nothing",
168
+ bumpFiles: [],
169
+ releases: [],
170
+ packageNames: []
171
+ };
172
+ }
173
+ const json = JSON.stringify(output, null, 2);
174
+ console.log(json);
175
+ const cachePath = `${rootDir}/${CI_PLAN_CACHE_PATH}`;
176
+ mkdirSync(cachePath.slice(0, cachePath.lastIndexOf("/")), { recursive: true });
177
+ writeFileSync(cachePath, json, "utf-8");
178
+ writeGitHubOutput("mode", output.mode);
179
+ writeGitHubOutput("packages", JSON.stringify(output.packageNames));
180
+ writeGitHubOutput("json", JSON.stringify(output));
181
+ }
182
+ function formatPlanRelease(r, packages, config) {
183
+ const pkg = packages.get(r.name);
184
+ return {
185
+ name: r.name,
186
+ type: r.type,
187
+ oldVersion: r.oldVersion,
188
+ newVersion: r.newVersion,
189
+ dir: pkg?.relativeDir,
190
+ bumpFiles: r.bumpFiles,
191
+ isDependencyBump: r.isDependencyBump,
192
+ isCascadeBump: r.isCascadeBump,
193
+ publishTargets: getPublishTargets(pkg, config)
194
+ };
195
+ }
196
+ function getPublishTargets(pkg, _config) {
197
+ if (!pkg) return [];
198
+ const pkgConfig = pkg.bumpy || {};
199
+ if (pkg.private && !pkgConfig.publishCommand) return [];
200
+ const targets = [];
201
+ if (pkgConfig.publishCommand) targets.push({ type: "custom" });
202
+ if (!pkgConfig.publishCommand && !pkgConfig.skipNpmPublish) targets.push({ type: "npm" });
203
+ return targets;
204
+ }
205
+ /** Write a key=value pair to $GITHUB_OUTPUT if available */
206
+ function writeGitHubOutput(key, value) {
207
+ const outputFile = process.env.GITHUB_OUTPUT;
208
+ if (!outputFile) return;
209
+ const delimiter = `ghadelimiter_${Date.now()}`;
210
+ appendFileSync(outputFile, `${key}<<${delimiter}\n${value}\n${delimiter}\n`);
211
+ }
127
212
  /**
128
213
  * CI release: either auto-publish or create a version PR.
129
214
  * Designed for merge-to-main workflows.
@@ -140,7 +225,7 @@ async function ciReleaseCommand(rootDir, opts) {
140
225
  }
141
226
  if (bumpFiles.length === 0) {
142
227
  log.info("No pending bump files — checking for unpublished packages...");
143
- const { publishCommand } = await import("./publish-CXJ0Ggkq.mjs");
228
+ const { publishCommand } = await import("./publish-BJ-Cs0TR.mjs");
144
229
  await publishCommand(rootDir, { tag: opts.tag });
145
230
  return;
146
231
  }
@@ -154,7 +239,7 @@ async function ciReleaseCommand(rootDir, opts) {
154
239
  }
155
240
  async function autoPublish(rootDir, config, plan, tag) {
156
241
  log.step("Running bumpy version...");
157
- const { versionCommand } = await import("./version-BjjnO2ii.mjs");
242
+ const { versionCommand } = await import("./version-nJ0vhPWw.mjs");
158
243
  await versionCommand(rootDir);
159
244
  log.step("Committing version changes...");
160
245
  runArgs([
@@ -183,7 +268,7 @@ async function autoPublish(rootDir, config, plan, tag) {
183
268
  ], { cwd: rootDir });
184
269
  }
185
270
  log.step("Running bumpy publish...");
186
- const { publishCommand } = await import("./publish-CXJ0Ggkq.mjs");
271
+ const { publishCommand } = await import("./publish-BJ-Cs0TR.mjs");
187
272
  await publishCommand(rootDir, { tag });
188
273
  }
189
274
  /**
@@ -349,7 +434,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
349
434
  branch
350
435
  ], { cwd: rootDir });
351
436
  log.step("Running bumpy version...");
352
- const { versionCommand } = await import("./version-BjjnO2ii.mjs");
437
+ const { versionCommand } = await import("./version-nJ0vhPWw.mjs");
353
438
  await versionCommand(rootDir);
354
439
  runArgs([
355
440
  "git",
@@ -736,4 +821,4 @@ function detectPrNumber() {
736
821
  return envPr;
737
822
  }
738
823
  //#endregion
739
- export { ciCheckCommand, ciReleaseCommand };
824
+ export { CI_PLAN_CACHE_PATH, ciCheckCommand, ciPlanCommand, ciReleaseCommand };
@@ -1,7 +1,7 @@
1
- import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.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";
1
+ import { n as log, r as require_picocolors, s as __toESM } from "./logger-BgksGFuf.mjs";
2
+ import { t as detectPackageManager } from "./package-manager-BQPwXwu5.mjs";
3
+ import { s as tryRunArgs } from "./shell-C8KgKnMQ.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-W95rXis0.mjs";
5
5
  //#region src/commands/ci-setup.ts
6
6
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
7
7
  const PAT_PERMISSIONS = [