@varlock/bumpy 1.13.2 → 1.14.0-rc.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 (28) hide show
  1. package/README.md +3 -1
  2. package/config-schema.json +43 -0
  3. package/dist/{add-Dt1hddMt.mjs → add-C9rU_89s.mjs} +4 -4
  4. package/dist/{apply-release-plan-DD2R7SL2.mjs → apply-release-plan-DxTsUSqa.mjs} +11 -2
  5. package/dist/{bump-file-B7hmXZlB.mjs → bump-file-mRJeReRJ.mjs} +43 -8
  6. package/dist/{changelog-CbaET5V6.mjs → changelog-DuFhnJRO.mjs} +3 -3
  7. package/dist/{changelog-github-DXDnWkrB.mjs → changelog-github-jLOtwuWj.mjs} +2 -2
  8. package/dist/channels-CFXZkyGd.mjs +75 -0
  9. package/dist/{check-Dvi0DIqC.mjs → check-DIl9Dz68.mjs} +18 -6
  10. package/dist/{ci-B7gF6CFP.mjs → ci-ChYmDuwy.mjs} +376 -23
  11. package/dist/cli.mjs +30 -15
  12. package/dist/{config-D_4GYDJi.mjs → config-0we4ISZX.mjs} +5 -1
  13. package/dist/{generate-DohUlhu3.mjs → generate-B2OMt_64.mjs} +3 -3
  14. package/dist/{git-BWPimLgc.mjs → git-DAWj8LyV.mjs} +12 -1
  15. package/dist/index.d.mts +46 -4
  16. package/dist/index.mjs +7 -7
  17. package/dist/prerelease-B2PVfXkm.mjs +205 -0
  18. package/dist/{publish-VYBhDYFM.mjs → publish-Ak6jmwi_.mjs} +105 -14
  19. package/dist/{publish-pipeline-BPedWvKS.mjs → publish-pipeline-BD8mLbL9.mjs} +2 -2
  20. package/dist/{release-plan-mK7iGeGq.mjs → release-plan-C84pcBi-.mjs} +12 -17
  21. package/dist/status-DIzi-Iai.mjs +232 -0
  22. package/dist/{types-Bkh-igOJ.mjs → types-lpiG-Zxh.mjs} +1 -0
  23. package/dist/version-CMJUopVj.mjs +192 -0
  24. package/package.json +1 -1
  25. package/dist/status-DxzKPM8d.mjs +0 -129
  26. package/dist/version-Cm0nRAFF.mjs +0 -123
  27. /package/dist/{commit-message-CSWVKPJ-.mjs → commit-message-BwsowSds.mjs} +0 -0
  28. /package/dist/{init-BCkm6Nfa.mjs → init-DkAY5hjc.mjs} +0 -0
@@ -0,0 +1,232 @@
1
+ import { n as log, t as colorize } from "./logger-BgksGFuf.mjs";
2
+ import { a as loadConfig } from "./config-0we4ISZX.mjs";
3
+ import { i as readBumpFiles, s as discoverPackages, t as filterBranchBumpFiles } from "./bump-file-mRJeReRJ.mjs";
4
+ import { o as DependencyGraph, t as assembleReleasePlan } from "./release-plan-C84pcBi-.mjs";
5
+ import { a as getChangedFiles, o as getCurrentBranch } from "./git-DAWj8LyV.mjs";
6
+ import { channelNames, resolveActiveChannel } from "./channels-CFXZkyGd.mjs";
7
+ import { t as buildChannelReleasePlan } from "./prerelease-B2PVfXkm.mjs";
8
+ //#region src/commands/status.ts
9
+ async function statusCommand(rootDir, opts) {
10
+ const config = await loadConfig(rootDir);
11
+ const packages = await discoverPackages(rootDir, config);
12
+ const depGraph = new DependencyGraph(packages);
13
+ const channel = resolveActiveChannel(rootDir, config, opts.channel);
14
+ if (channel) {
15
+ await channelStatus(rootDir, config, channel, packages, depGraph, opts);
16
+ return;
17
+ }
18
+ const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir, { channels: channelNames(config) });
19
+ if (parseErrors.length > 0) for (const err of parseErrors) log.error(err);
20
+ if (bumpFiles.length === 0) {
21
+ if (opts.json) console.log(JSON.stringify({
22
+ bumpFiles: [],
23
+ releases: [],
24
+ packageNames: []
25
+ }, null, 2));
26
+ else if (!opts.packagesOnly) log.info("No pending bump files.");
27
+ process.exit(1);
28
+ }
29
+ const plan = assembleReleasePlan(bumpFiles, packages, depGraph, config);
30
+ let branchBumpFileIds;
31
+ const currentBranch = getCurrentBranch({ cwd: rootDir });
32
+ if (currentBranch && currentBranch !== config.baseBranch) branchBumpFileIds = filterBranchBumpFiles(bumpFiles, getChangedFiles(rootDir, config.baseBranch), rootDir).branchBumpFileIds;
33
+ let releases = plan.releases;
34
+ if (opts.bumpType) {
35
+ const types = opts.bumpType.split(",").map((t) => t.trim());
36
+ releases = releases.filter((r) => types.includes(r.type));
37
+ }
38
+ if (opts.filter) {
39
+ const { matchGlob } = await import("./config-0we4ISZX.mjs").then((n) => n.t);
40
+ const patterns = opts.filter.split(",").map((p) => p.trim());
41
+ releases = releases.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
42
+ }
43
+ if (opts.json) {
44
+ const jsonOutput = {
45
+ bumpFiles: plan.bumpFiles.map((bf) => ({
46
+ id: bf.id,
47
+ summary: bf.summary,
48
+ releases: bf.releases.map((r) => ({
49
+ name: r.name,
50
+ type: r.type
51
+ })),
52
+ ...branchBumpFileIds ? { inCurrentBranch: branchBumpFileIds.has(bf.id) } : {}
53
+ })),
54
+ releases: releases.map((r) => {
55
+ const pkg = packages.get(r.name);
56
+ const pkgConfig = pkg?.bumpy || {};
57
+ return {
58
+ name: r.name,
59
+ type: r.type,
60
+ oldVersion: r.oldVersion,
61
+ newVersion: r.newVersion,
62
+ dir: pkg?.relativeDir,
63
+ bumpFiles: r.bumpFiles,
64
+ isDependencyBump: r.isDependencyBump,
65
+ isCascadeBump: r.isCascadeBump,
66
+ ...branchBumpFileIds ? { inCurrentBranch: r.bumpFiles.some((id) => branchBumpFileIds.has(id)) } : {},
67
+ publishTargets: getPublishTargets(pkg, pkgConfig, config)
68
+ };
69
+ }),
70
+ packageNames: releases.map((r) => r.name)
71
+ };
72
+ console.log(JSON.stringify(jsonOutput, null, 2));
73
+ return;
74
+ }
75
+ if (opts.packagesOnly) {
76
+ for (const r of releases) console.log(r.name);
77
+ return;
78
+ }
79
+ log.bold(`${bumpFiles.length} bump file(s) pending\n`);
80
+ if (releases.length === 0) {
81
+ log.warn("No packages match the current filters.");
82
+ return;
83
+ }
84
+ const groups = [
85
+ [
86
+ "Major",
87
+ "red",
88
+ releases.filter((r) => r.type === "major")
89
+ ],
90
+ [
91
+ "Minor",
92
+ "yellow",
93
+ releases.filter((r) => r.type === "minor")
94
+ ],
95
+ [
96
+ "Patch",
97
+ "green",
98
+ releases.filter((r) => r.type === "patch")
99
+ ]
100
+ ];
101
+ for (const [label, color, group] of groups) {
102
+ if (group.length === 0) continue;
103
+ log.bold(colorize(label, color));
104
+ for (const r of group) printRelease(r, packages);
105
+ console.log();
106
+ }
107
+ if (plan.warnings.length > 0) {
108
+ for (const w of plan.warnings) log.warn(w);
109
+ console.log();
110
+ }
111
+ if (opts.verbose) {
112
+ log.bold("Bump files:");
113
+ for (const bf of plan.bumpFiles) {
114
+ console.log(` ${colorize(bf.id, "cyan")}`);
115
+ for (const r of bf.releases) console.log(` ${r.name}: ${r.type}`);
116
+ if (bf.summary) console.log(` ${colorize(bf.summary.split("\n")[0], "dim")}`);
117
+ }
118
+ }
119
+ }
120
+ /**
121
+ * Status on a prerelease channel: shows the cycle (shipped + pending bump files)
122
+ * and the derived prerelease versions. Counters come from the registry — when it's
123
+ * unreachable, targets render with a ".?" counter placeholder.
124
+ */
125
+ async function channelStatus(rootDir, config, channel, packages, depGraph, opts) {
126
+ const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir, { channels: channelNames(config) });
127
+ for (const err of parseErrors) log.error(err);
128
+ const shipped = bumpFiles.filter((bf) => bf.channel === channel.name);
129
+ const pending = bumpFiles.filter((bf) => bf.channel !== channel.name);
130
+ if (bumpFiles.length === 0) {
131
+ if (opts.json) console.log(JSON.stringify({
132
+ channel: channel.name,
133
+ bumpFiles: [],
134
+ releases: [],
135
+ packageNames: []
136
+ }, null, 2));
137
+ else if (!opts.packagesOnly) log.info(`No bump files in the "${channel.name}" cycle.`);
138
+ process.exit(1);
139
+ }
140
+ const stablePlan = assembleReleasePlan(bumpFiles, packages, depGraph, config, { prereleasePreid: channel.preid });
141
+ let releases = stablePlan.releases;
142
+ let countersExact = false;
143
+ try {
144
+ const built = await buildChannelReleasePlan(stablePlan, channel, packages, rootDir, { forDisplay: true });
145
+ if (built.plan.releases.length > 0) {
146
+ releases = built.plan.releases;
147
+ countersExact = true;
148
+ }
149
+ } catch {}
150
+ if (!countersExact) releases = releases.map((r) => ({
151
+ ...r,
152
+ newVersion: `${r.newVersion}-${channel.preid}.?`
153
+ }));
154
+ if (opts.bumpType) {
155
+ const types = opts.bumpType.split(",").map((t) => t.trim());
156
+ releases = releases.filter((r) => types.includes(r.type));
157
+ }
158
+ if (opts.filter) {
159
+ const { matchGlob } = await import("./config-0we4ISZX.mjs").then((n) => n.t);
160
+ const patterns = opts.filter.split(",").map((p) => p.trim());
161
+ releases = releases.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
162
+ }
163
+ if (opts.json) {
164
+ console.log(JSON.stringify({
165
+ channel: channel.name,
166
+ preid: channel.preid,
167
+ tag: channel.tag,
168
+ bumpFiles: bumpFiles.map((bf) => ({
169
+ id: bf.id,
170
+ summary: bf.summary,
171
+ releases: bf.releases.map((r) => ({
172
+ name: r.name,
173
+ type: r.type
174
+ })),
175
+ shipped: bf.channel === channel.name
176
+ })),
177
+ releases: releases.map((r) => {
178
+ const pkg = packages.get(r.name);
179
+ return {
180
+ name: r.name,
181
+ type: r.type,
182
+ oldVersion: r.oldVersion,
183
+ newVersion: r.newVersion,
184
+ dir: pkg?.relativeDir,
185
+ bumpFiles: r.bumpFiles,
186
+ isDependencyBump: r.isDependencyBump,
187
+ isCascadeBump: r.isCascadeBump,
188
+ publishTargets: getPublishTargets(pkg, pkg?.bumpy || {}, config)
189
+ };
190
+ }),
191
+ packageNames: releases.map((r) => r.name)
192
+ }, null, 2));
193
+ return;
194
+ }
195
+ if (opts.packagesOnly) {
196
+ for (const r of releases) console.log(r.name);
197
+ return;
198
+ }
199
+ log.bold(`Channel "${channel.name}" — preid "-${channel.preid}.N", dist-tag @${channel.tag}\n`);
200
+ printBumpFileGroup(`Shipped on this channel (.bumpy/${channel.name}/)`, shipped);
201
+ printBumpFileGroup("Pending (next prerelease)", pending);
202
+ log.bold(`Cycle releases${countersExact ? "" : colorize(" (registry unreachable — counters unknown)", "dim")}`);
203
+ for (const r of releases) printRelease(r, packages);
204
+ console.log();
205
+ if (stablePlan.warnings.length > 0) for (const w of stablePlan.warnings) log.warn(w);
206
+ }
207
+ function printBumpFileGroup(label, files) {
208
+ log.bold(label);
209
+ if (files.length === 0) console.log(colorize(" (none)", "dim"));
210
+ for (const bf of files) {
211
+ const summary = bf.summary ? colorize(` — ${bf.summary.split("\n")[0]}`, "dim") : "";
212
+ console.log(` ${colorize(`${bf.id}.md`, "cyan")}${summary}`);
213
+ }
214
+ console.log();
215
+ }
216
+ function printRelease(r, packages) {
217
+ const pkg = packages.get(r.name);
218
+ const dir = pkg ? colorize(` (${pkg.relativeDir})`, "dim") : "";
219
+ const suffix = r.isDependencyBump ? colorize(" ← dependency bump", "dim") : r.isCascadeBump ? colorize(" ← cascade", "dim") : "";
220
+ console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${suffix}${dir}`);
221
+ }
222
+ /** Determine which publish targets a package will use */
223
+ function getPublishTargets(pkg, pkgConfig, _config) {
224
+ if (!pkg) return [];
225
+ if (pkg.private && !pkgConfig.publishCommand) return [];
226
+ const targets = [];
227
+ if (pkgConfig.publishCommand) targets.push({ type: "custom" });
228
+ if (!pkgConfig.publishCommand && !pkgConfig.skipNpmPublish) targets.push({ type: "npm" });
229
+ return targets;
230
+ }
231
+ //#endregion
232
+ export { statusCommand };
@@ -56,6 +56,7 @@ const DEFAULT_PUBLISH_CONFIG = {
56
56
  const DEFAULT_CONFIG = {
57
57
  baseBranch: "main",
58
58
  access: "public",
59
+ channels: {},
59
60
  versionCommitMessage: void 0,
60
61
  changedFilePatterns: ["**"],
61
62
  changelog: "default",
@@ -0,0 +1,192 @@
1
+ import { n as log, t as colorize } from "./logger-BgksGFuf.mjs";
2
+ import { a as loadConfig } from "./config-0we4ISZX.mjs";
3
+ import { r as detectWorkspaces } from "./package-manager-Db_vTztt.mjs";
4
+ import { i as readBumpFiles, n as moveBumpFilesToChannel, s as discoverPackages } from "./bump-file-mRJeReRJ.mjs";
5
+ import { o as DependencyGraph, t as assembleReleasePlan } from "./release-plan-C84pcBi-.mjs";
6
+ import { n as runArgs, s as tryRunArgs } from "./shell-C8KgKnMQ.mjs";
7
+ import { t as applyReleasePlan } from "./apply-release-plan-DxTsUSqa.mjs";
8
+ import { channelNames, resolveActiveChannel } from "./channels-CFXZkyGd.mjs";
9
+ import { t as resolveCommitMessage } from "./commit-message-BwsowSds.mjs";
10
+ //#region src/commands/version.ts
11
+ async function versionCommand(rootDir, opts = {}) {
12
+ const config = await loadConfig(rootDir);
13
+ const channel = resolveActiveChannel(rootDir, config, opts.channel);
14
+ if (channel) {
15
+ await channelVersion(rootDir, config, channel, { commit: opts.commit });
16
+ return;
17
+ }
18
+ const packages = await discoverPackages(rootDir, config);
19
+ const depGraph = new DependencyGraph(packages);
20
+ const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir, { channels: channelNames(config) });
21
+ if (parseErrors.length > 0) {
22
+ for (const err of parseErrors) log.error(err);
23
+ throw new Error("Bump file parse errors must be fixed before versioning.");
24
+ }
25
+ if (bumpFiles.length === 0) {
26
+ log.info("No pending bump files.");
27
+ return;
28
+ }
29
+ const plan = assembleReleasePlan(bumpFiles, packages, depGraph, config);
30
+ if (plan.releases.length === 0) {
31
+ log.warn("Bump files found but no packages would be released.");
32
+ return;
33
+ }
34
+ if (plan.warnings.length > 0) {
35
+ for (const w of plan.warnings) log.warn(w);
36
+ console.log();
37
+ }
38
+ log.step("Applying version bumps:");
39
+ for (const r of plan.releases) {
40
+ const tag = r.isDependencyBump ? " (dep)" : r.isCascadeBump ? " (cascade)" : "";
41
+ console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${tag}`);
42
+ }
43
+ await applyReleasePlan(plan, packages, rootDir, config);
44
+ log.success(`🐸 Updated ${plan.releases.length} package(s)`);
45
+ log.dim(` Deleted ${bumpFiles.length} bump file(s)`);
46
+ await updateLockfile(rootDir);
47
+ if (opts.commit) try {
48
+ runArgs([
49
+ "git",
50
+ "add",
51
+ "-A",
52
+ ".bumpy/"
53
+ ], { cwd: rootDir });
54
+ for (const r of plan.releases) {
55
+ const pkg = packages.get(r.name);
56
+ runArgs([
57
+ "git",
58
+ "add",
59
+ "--",
60
+ `${pkg.relativeDir}/package.json`
61
+ ], { cwd: rootDir });
62
+ runArgs([
63
+ "git",
64
+ "add",
65
+ "--",
66
+ `${pkg.relativeDir}/CHANGELOG.md`
67
+ ], { cwd: rootDir });
68
+ }
69
+ for (const lockfile of [
70
+ "bun.lock",
71
+ "bun.lockb",
72
+ "pnpm-lock.yaml",
73
+ "yarn.lock",
74
+ "package-lock.json"
75
+ ]) tryRunArgs([
76
+ "git",
77
+ "add",
78
+ "--",
79
+ lockfile
80
+ ], { cwd: rootDir });
81
+ runArgs([
82
+ "git",
83
+ "commit",
84
+ "-F",
85
+ "-"
86
+ ], {
87
+ cwd: rootDir,
88
+ input: await resolveCommitMessage(config.versionCommitMessage, plan, rootDir)
89
+ });
90
+ log.success("Created git commit");
91
+ } catch (e) {
92
+ log.warn(`Git commit failed: ${e}`);
93
+ }
94
+ }
95
+ /**
96
+ * "Versioning" on a prerelease channel never writes versions or changelogs — those
97
+ * are derived at publish time. It only moves pending bump files (root + other
98
+ * channels' dirs) into this channel's `.bumpy/<channel>/` directory, marking them
99
+ * as shipped on this channel.
100
+ */
101
+ async function channelVersion(rootDir, config, channel, opts = {}) {
102
+ const packages = await discoverPackages(rootDir, config);
103
+ const depGraph = new DependencyGraph(packages);
104
+ const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir, { channels: channelNames(config) });
105
+ if (parseErrors.length > 0) {
106
+ for (const err of parseErrors) log.error(err);
107
+ throw new Error("Bump file parse errors must be fixed before versioning.");
108
+ }
109
+ const pending = bumpFiles.filter((bf) => bf.channel !== channel.name);
110
+ if (pending.length === 0) {
111
+ log.info(`No pending bump files for channel "${channel.name}".`);
112
+ return null;
113
+ }
114
+ const cyclePlan = assembleReleasePlan(bumpFiles, packages, depGraph, config, { prereleasePreid: channel.preid });
115
+ if (cyclePlan.warnings.length > 0) {
116
+ for (const w of cyclePlan.warnings) log.warn(w);
117
+ console.log();
118
+ }
119
+ log.step(`Channel "${channel.name}" — moving ${pending.length} bump file(s) into .bumpy/${channel.name}/:`);
120
+ for (const bf of pending) {
121
+ const from = bf.channel ? `.bumpy/${bf.channel}/` : ".bumpy/";
122
+ console.log(` ${from}${bf.id}.md → .bumpy/${channel.name}/${bf.id}.md`);
123
+ }
124
+ console.log();
125
+ log.step("Cycle targets (counters are derived from the registry at publish time):");
126
+ for (const r of cyclePlan.releases) {
127
+ const tag = r.isDependencyBump ? " (dep)" : r.isCascadeBump ? " (cascade)" : "";
128
+ console.log(` ${r.name}: ${r.oldVersion} → ${colorize(`${r.newVersion}-${channel.preid}.x`, "cyan")}${tag}`);
129
+ }
130
+ await moveBumpFilesToChannel(rootDir, pending, channel.name);
131
+ log.success(`🐸 Moved ${pending.length} bump file(s) — no versions written (prereleases are derived, not committed)`);
132
+ if (opts.commit) try {
133
+ runArgs([
134
+ "git",
135
+ "add",
136
+ "-A",
137
+ ".bumpy/"
138
+ ], { cwd: rootDir });
139
+ const summary = pending.map((bf) => `${bf.id}.md`).join(", ");
140
+ runArgs([
141
+ "git",
142
+ "commit",
143
+ "-F",
144
+ "-"
145
+ ], {
146
+ cwd: rootDir,
147
+ input: `Version prerelease (${channel.name})\n\nShipped: ${summary}`
148
+ });
149
+ log.success("Created git commit");
150
+ } catch (e) {
151
+ log.warn(`Git commit failed: ${e}`);
152
+ }
153
+ return {
154
+ cyclePlan,
155
+ movedFiles: pending
156
+ };
157
+ }
158
+ /** Run the package manager's install to update the lockfile */
159
+ async function updateLockfile(rootDir) {
160
+ const { packageManager } = await detectWorkspaces(rootDir);
161
+ const installArgs = getInstallArgs(packageManager);
162
+ log.step(`Updating lockfile (${installArgs.join(" ")})...`);
163
+ try {
164
+ runArgs(installArgs, { cwd: rootDir });
165
+ log.dim(" Lockfile updated");
166
+ } catch (err) {
167
+ log.warn(` Lockfile update failed: ${err instanceof Error ? err.message : err}`);
168
+ }
169
+ }
170
+ function getInstallArgs(pm) {
171
+ switch (pm) {
172
+ case "pnpm": return [
173
+ "pnpm",
174
+ "install",
175
+ "--lockfile-only"
176
+ ];
177
+ case "bun": return ["bun", "install"];
178
+ case "yarn": return [
179
+ "yarn",
180
+ "install",
181
+ "--mode",
182
+ "update-lockfile"
183
+ ];
184
+ default: return [
185
+ "npm",
186
+ "install",
187
+ "--package-lock-only"
188
+ ];
189
+ }
190
+ }
191
+ //#endregion
192
+ export { channelVersion, versionCommand };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@varlock/bumpy",
3
- "version": "1.13.2",
3
+ "version": "1.14.0-rc.1",
4
4
  "description": "Modern monorepo versioning and changelog tool",
5
5
  "keywords": [
6
6
  "bump",
@@ -1,129 +0,0 @@
1
- import { n as log, t as colorize } from "./logger-BgksGFuf.mjs";
2
- import { a as loadConfig } from "./config-D_4GYDJi.mjs";
3
- import { o as discoverPackages, r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-B7hmXZlB.mjs";
4
- import { a as DependencyGraph, t as assembleReleasePlan } from "./release-plan-mK7iGeGq.mjs";
5
- import { a as getChangedFiles, o as getCurrentBranch } from "./git-BWPimLgc.mjs";
6
- //#region src/commands/status.ts
7
- async function statusCommand(rootDir, opts) {
8
- const config = await loadConfig(rootDir);
9
- const packages = await discoverPackages(rootDir, config);
10
- const depGraph = new DependencyGraph(packages);
11
- const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir);
12
- if (parseErrors.length > 0) for (const err of parseErrors) log.error(err);
13
- if (bumpFiles.length === 0) {
14
- if (opts.json) console.log(JSON.stringify({
15
- bumpFiles: [],
16
- releases: [],
17
- packageNames: []
18
- }, null, 2));
19
- else if (!opts.packagesOnly) log.info("No pending bump files.");
20
- process.exit(1);
21
- }
22
- const plan = assembleReleasePlan(bumpFiles, packages, depGraph, config);
23
- let branchBumpFileIds;
24
- const currentBranch = getCurrentBranch({ cwd: rootDir });
25
- if (currentBranch && currentBranch !== config.baseBranch) branchBumpFileIds = filterBranchBumpFiles(bumpFiles, getChangedFiles(rootDir, config.baseBranch), rootDir).branchBumpFileIds;
26
- let releases = plan.releases;
27
- if (opts.bumpType) {
28
- const types = opts.bumpType.split(",").map((t) => t.trim());
29
- releases = releases.filter((r) => types.includes(r.type));
30
- }
31
- if (opts.filter) {
32
- const { matchGlob } = await import("./config-D_4GYDJi.mjs").then((n) => n.t);
33
- const patterns = opts.filter.split(",").map((p) => p.trim());
34
- releases = releases.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
35
- }
36
- if (opts.json) {
37
- const jsonOutput = {
38
- bumpFiles: plan.bumpFiles.map((bf) => ({
39
- id: bf.id,
40
- summary: bf.summary,
41
- releases: bf.releases.map((r) => ({
42
- name: r.name,
43
- type: r.type
44
- })),
45
- ...branchBumpFileIds ? { inCurrentBranch: branchBumpFileIds.has(bf.id) } : {}
46
- })),
47
- releases: releases.map((r) => {
48
- const pkg = packages.get(r.name);
49
- const pkgConfig = pkg?.bumpy || {};
50
- return {
51
- name: r.name,
52
- type: r.type,
53
- oldVersion: r.oldVersion,
54
- newVersion: r.newVersion,
55
- dir: pkg?.relativeDir,
56
- bumpFiles: r.bumpFiles,
57
- isDependencyBump: r.isDependencyBump,
58
- isCascadeBump: r.isCascadeBump,
59
- ...branchBumpFileIds ? { inCurrentBranch: r.bumpFiles.some((id) => branchBumpFileIds.has(id)) } : {},
60
- publishTargets: getPublishTargets(pkg, pkgConfig, config)
61
- };
62
- }),
63
- packageNames: releases.map((r) => r.name)
64
- };
65
- console.log(JSON.stringify(jsonOutput, null, 2));
66
- return;
67
- }
68
- if (opts.packagesOnly) {
69
- for (const r of releases) console.log(r.name);
70
- return;
71
- }
72
- log.bold(`${bumpFiles.length} bump file(s) pending\n`);
73
- if (releases.length === 0) {
74
- log.warn("No packages match the current filters.");
75
- return;
76
- }
77
- const groups = [
78
- [
79
- "Major",
80
- "red",
81
- releases.filter((r) => r.type === "major")
82
- ],
83
- [
84
- "Minor",
85
- "yellow",
86
- releases.filter((r) => r.type === "minor")
87
- ],
88
- [
89
- "Patch",
90
- "green",
91
- releases.filter((r) => r.type === "patch")
92
- ]
93
- ];
94
- for (const [label, color, group] of groups) {
95
- if (group.length === 0) continue;
96
- log.bold(colorize(label, color));
97
- for (const r of group) printRelease(r, packages);
98
- console.log();
99
- }
100
- if (plan.warnings.length > 0) {
101
- for (const w of plan.warnings) log.warn(w);
102
- console.log();
103
- }
104
- if (opts.verbose) {
105
- log.bold("Bump files:");
106
- for (const bf of plan.bumpFiles) {
107
- console.log(` ${colorize(bf.id, "cyan")}`);
108
- for (const r of bf.releases) console.log(` ${r.name}: ${r.type}`);
109
- if (bf.summary) console.log(` ${colorize(bf.summary.split("\n")[0], "dim")}`);
110
- }
111
- }
112
- }
113
- function printRelease(r, packages) {
114
- const pkg = packages.get(r.name);
115
- const dir = pkg ? colorize(` (${pkg.relativeDir})`, "dim") : "";
116
- const suffix = r.isDependencyBump ? colorize(" ← dependency bump", "dim") : r.isCascadeBump ? colorize(" ← cascade", "dim") : "";
117
- console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${suffix}${dir}`);
118
- }
119
- /** Determine which publish targets a package will use */
120
- function getPublishTargets(pkg, pkgConfig, _config) {
121
- if (!pkg) return [];
122
- if (pkg.private && !pkgConfig.publishCommand) return [];
123
- const targets = [];
124
- if (pkgConfig.publishCommand) targets.push({ type: "custom" });
125
- if (!pkgConfig.publishCommand && !pkgConfig.skipNpmPublish) targets.push({ type: "npm" });
126
- return targets;
127
- }
128
- //#endregion
129
- export { statusCommand };
@@ -1,123 +0,0 @@
1
- import { n as log, t as colorize } from "./logger-BgksGFuf.mjs";
2
- import { a as loadConfig } from "./config-D_4GYDJi.mjs";
3
- import { r as detectWorkspaces } from "./package-manager-Db_vTztt.mjs";
4
- import { o as discoverPackages, r as readBumpFiles } from "./bump-file-B7hmXZlB.mjs";
5
- import { a as DependencyGraph, t as assembleReleasePlan } from "./release-plan-mK7iGeGq.mjs";
6
- import { n as runArgs, s as tryRunArgs } from "./shell-C8KgKnMQ.mjs";
7
- import { t as applyReleasePlan } from "./apply-release-plan-DD2R7SL2.mjs";
8
- import { t as resolveCommitMessage } from "./commit-message-CSWVKPJ-.mjs";
9
- //#region src/commands/version.ts
10
- async function versionCommand(rootDir, opts = {}) {
11
- const config = await loadConfig(rootDir);
12
- const packages = await discoverPackages(rootDir, config);
13
- const depGraph = new DependencyGraph(packages);
14
- const { bumpFiles, errors: parseErrors } = await readBumpFiles(rootDir);
15
- if (parseErrors.length > 0) {
16
- for (const err of parseErrors) log.error(err);
17
- throw new Error("Bump file parse errors must be fixed before versioning.");
18
- }
19
- if (bumpFiles.length === 0) {
20
- log.info("No pending bump files.");
21
- return;
22
- }
23
- const plan = assembleReleasePlan(bumpFiles, packages, depGraph, config);
24
- if (plan.releases.length === 0) {
25
- log.warn("Bump files found but no packages would be released.");
26
- return;
27
- }
28
- if (plan.warnings.length > 0) {
29
- for (const w of plan.warnings) log.warn(w);
30
- console.log();
31
- }
32
- log.step("Applying version bumps:");
33
- for (const r of plan.releases) {
34
- const tag = r.isDependencyBump ? " (dep)" : r.isCascadeBump ? " (cascade)" : "";
35
- console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${tag}`);
36
- }
37
- await applyReleasePlan(plan, packages, rootDir, config);
38
- log.success(`🐸 Updated ${plan.releases.length} package(s)`);
39
- log.dim(` Deleted ${bumpFiles.length} bump file(s)`);
40
- await updateLockfile(rootDir);
41
- if (opts.commit) try {
42
- runArgs([
43
- "git",
44
- "add",
45
- "-A",
46
- ".bumpy/"
47
- ], { cwd: rootDir });
48
- for (const r of plan.releases) {
49
- const pkg = packages.get(r.name);
50
- runArgs([
51
- "git",
52
- "add",
53
- "--",
54
- `${pkg.relativeDir}/package.json`
55
- ], { cwd: rootDir });
56
- runArgs([
57
- "git",
58
- "add",
59
- "--",
60
- `${pkg.relativeDir}/CHANGELOG.md`
61
- ], { cwd: rootDir });
62
- }
63
- for (const lockfile of [
64
- "bun.lock",
65
- "bun.lockb",
66
- "pnpm-lock.yaml",
67
- "yarn.lock",
68
- "package-lock.json"
69
- ]) tryRunArgs([
70
- "git",
71
- "add",
72
- "--",
73
- lockfile
74
- ], { cwd: rootDir });
75
- runArgs([
76
- "git",
77
- "commit",
78
- "-F",
79
- "-"
80
- ], {
81
- cwd: rootDir,
82
- input: await resolveCommitMessage(config.versionCommitMessage, plan, rootDir)
83
- });
84
- log.success("Created git commit");
85
- } catch (e) {
86
- log.warn(`Git commit failed: ${e}`);
87
- }
88
- }
89
- /** Run the package manager's install to update the lockfile */
90
- async function updateLockfile(rootDir) {
91
- const { packageManager } = await detectWorkspaces(rootDir);
92
- const installArgs = getInstallArgs(packageManager);
93
- log.step(`Updating lockfile (${installArgs.join(" ")})...`);
94
- try {
95
- runArgs(installArgs, { cwd: rootDir });
96
- log.dim(" Lockfile updated");
97
- } catch (err) {
98
- log.warn(` Lockfile update failed: ${err instanceof Error ? err.message : err}`);
99
- }
100
- }
101
- function getInstallArgs(pm) {
102
- switch (pm) {
103
- case "pnpm": return [
104
- "pnpm",
105
- "install",
106
- "--lockfile-only"
107
- ];
108
- case "bun": return ["bun", "install"];
109
- case "yarn": return [
110
- "yarn",
111
- "install",
112
- "--mode",
113
- "update-lockfile"
114
- ];
115
- default: return [
116
- "npm",
117
- "install",
118
- "--package-lock-only"
119
- ];
120
- }
121
- }
122
- //#endregion
123
- export { versionCommand };
File without changes