@varlock/bumpy 1.0.0 → 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.
- package/config-schema.json +327 -0
- package/dist/{add-CgCjs4d-.mjs → add-BmNL5VwL.mjs} +21 -11
- package/dist/{apply-release-plan-CczGWJTk.mjs → apply-release-plan-0kH62jhu.mjs} +12 -7
- package/dist/{bump-file-CCLXMLA8.mjs → bump-file-DVqR3k67.mjs} +24 -10
- package/dist/{changelog-github-Cd8uJHZI.mjs → changelog-github-DkACMj0j.mjs} +1 -1
- package/dist/check-BjWF6SJm.mjs +65 -0
- package/dist/{ci-Bhx--Tj6.mjs → ci-DY58ugIi.mjs} +35 -32
- package/dist/{ci-setup-qz4Y3v7T.mjs → ci-setup-BQwktQEe.mjs} +3 -3
- package/dist/cli.mjs +20 -27
- package/dist/commit-message-BwsowSds.mjs +23 -0
- package/dist/{config-XZWUL3ma.mjs → config-B-Qg3DZH.mjs} +4 -3
- package/dist/{generate-gYKTpvex.mjs → generate-DX46X-rW.mjs} +73 -64
- package/dist/{git-CGHVXXKw.mjs → git-YDedMddc.mjs} +54 -2
- package/dist/index.d.mts +13 -2
- package/dist/index.mjs +8 -8
- package/dist/init-DkTPs_WQ.mjs +196 -0
- package/dist/{js-yaml-DpZfOoD4.mjs → package-manager-Clsmr-9r.mjs} +79 -1
- package/dist/picomatch-DMmqYjgq.mjs +1870 -0
- package/dist/{publish-Cun-zQ1b.mjs → publish-CGB4TIKD.mjs} +10 -10
- package/dist/{publish-pipeline-BwBuKCIk.mjs → publish-pipeline-CXuqce1N.mjs} +4 -4
- package/dist/{release-plan-Bi5QNSEo.mjs → release-plan-JNir7bSM.mjs} +2 -2
- package/dist/{shell-Dj7JRD_q.mjs → shell-CY7OD48z.mjs} +20 -2
- package/dist/{status-CfE63ti5.mjs → status-EGYqULJg.mjs} +6 -6
- package/dist/{version-19vVt9dv.mjs → version-BcfidiVX.mjs} +13 -16
- package/dist/{workspace-C5ULTyUN.mjs → workspace-DWXlwcH4.mjs} +2 -2
- package/package.json +4 -1
- package/skills/add-change/SKILL.md +11 -3
- package/dist/check-BOoxpWqk.mjs +0 -51
- package/dist/init-lA9E5pEc.mjs +0 -22
- package/dist/migrate-DmOYgmfD.mjs +0 -121
- package/dist/package-manager-VCe10bjc.mjs +0 -80
- /package/dist/{clack-CDRCHrC-.mjs → clack-C6bVkGxf.mjs} +0 -0
- /package/dist/{dep-graph-E-9-eQ2J.mjs → dep-graph-DiLeAhl9.mjs} +0 -0
- /package/dist/{names-9VubBmL0.mjs → names-C-TuOPbd.mjs} +0 -0
- /package/dist/{semver-DfQyVLM_.mjs → semver-BJzWIuRz.mjs} +0 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
3
|
-
import { t as detectPackageManager } from "./package-manager-
|
|
4
|
-
import { n as discoverWorkspace } from "./workspace-
|
|
5
|
-
import { t as DependencyGraph } from "./dep-graph-
|
|
6
|
-
import { n as
|
|
7
|
-
import { r as readBumpFiles } from "./bump-file-
|
|
8
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
9
|
-
import {
|
|
10
|
-
import { t as randomName } from "./names-
|
|
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";
|
|
11
12
|
import { createHash } from "node:crypto";
|
|
12
13
|
//#region src/commands/ci.ts
|
|
13
14
|
/**
|
|
@@ -86,9 +87,12 @@ async function ciCheckCommand(rootDir, opts) {
|
|
|
86
87
|
const shouldComment = opts.comment ?? inCI;
|
|
87
88
|
const prNumber = detectPrNumber();
|
|
88
89
|
const pm = await detectPackageManager(rootDir);
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
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
|
+
}
|
|
92
96
|
if (prBumpFiles.length === 0) {
|
|
93
97
|
log.info("No bump files found in this PR.");
|
|
94
98
|
if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatNoBumpFilesComment(detectPrBranch(rootDir), pm), rootDir, opts.patComments);
|
|
@@ -116,7 +120,7 @@ async function ciReleaseCommand(rootDir, opts) {
|
|
|
116
120
|
const bumpFiles = await readBumpFiles(rootDir);
|
|
117
121
|
if (bumpFiles.length === 0) {
|
|
118
122
|
log.info("No pending bump files — checking for unpublished packages...");
|
|
119
|
-
const { publishCommand } = await import("./publish-
|
|
123
|
+
const { publishCommand } = await import("./publish-CGB4TIKD.mjs");
|
|
120
124
|
await publishCommand(rootDir, { tag: opts.tag });
|
|
121
125
|
return;
|
|
122
126
|
}
|
|
@@ -125,12 +129,12 @@ async function ciReleaseCommand(rootDir, opts) {
|
|
|
125
129
|
log.info("Bump files found but no packages would be released.");
|
|
126
130
|
return;
|
|
127
131
|
}
|
|
128
|
-
if (opts.mode === "auto-publish") await autoPublish(rootDir, config, opts.tag);
|
|
132
|
+
if (opts.mode === "auto-publish") await autoPublish(rootDir, config, plan, opts.tag);
|
|
129
133
|
else await createVersionPr(rootDir, plan, config, new Map([...packages.values()].map((p) => [p.name, p.relativeDir])), opts.branch, opts.patPr);
|
|
130
134
|
}
|
|
131
|
-
async function autoPublish(rootDir, config, tag) {
|
|
135
|
+
async function autoPublish(rootDir, config, plan, tag) {
|
|
132
136
|
log.step("Running bumpy version...");
|
|
133
|
-
const { versionCommand } = await import("./version-
|
|
137
|
+
const { versionCommand } = await import("./version-BcfidiVX.mjs");
|
|
134
138
|
await versionCommand(rootDir);
|
|
135
139
|
log.step("Committing version changes...");
|
|
136
140
|
runArgs([
|
|
@@ -146,9 +150,12 @@ async function autoPublish(rootDir, config, tag) {
|
|
|
146
150
|
runArgs([
|
|
147
151
|
"git",
|
|
148
152
|
"commit",
|
|
149
|
-
"-
|
|
150
|
-
"
|
|
151
|
-
], {
|
|
153
|
+
"-F",
|
|
154
|
+
"-"
|
|
155
|
+
], {
|
|
156
|
+
cwd: rootDir,
|
|
157
|
+
input: await resolveCommitMessage(config.versionCommitMessage, plan, rootDir)
|
|
158
|
+
});
|
|
152
159
|
runArgs([
|
|
153
160
|
"git",
|
|
154
161
|
"push",
|
|
@@ -156,7 +163,7 @@ async function autoPublish(rootDir, config, tag) {
|
|
|
156
163
|
], { cwd: rootDir });
|
|
157
164
|
}
|
|
158
165
|
log.step("Running bumpy publish...");
|
|
159
|
-
const { publishCommand } = await import("./publish-
|
|
166
|
+
const { publishCommand } = await import("./publish-CGB4TIKD.mjs");
|
|
160
167
|
await publishCommand(rootDir, { tag });
|
|
161
168
|
}
|
|
162
169
|
/**
|
|
@@ -322,7 +329,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
|
|
|
322
329
|
branch
|
|
323
330
|
], { cwd: rootDir });
|
|
324
331
|
log.step("Running bumpy version...");
|
|
325
|
-
const { versionCommand } = await import("./version-
|
|
332
|
+
const { versionCommand } = await import("./version-BcfidiVX.mjs");
|
|
326
333
|
await versionCommand(rootDir);
|
|
327
334
|
runArgs([
|
|
328
335
|
"git",
|
|
@@ -349,11 +356,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
|
|
|
349
356
|
"-"
|
|
350
357
|
], {
|
|
351
358
|
cwd: rootDir,
|
|
352
|
-
input:
|
|
353
|
-
"Version packages",
|
|
354
|
-
"",
|
|
355
|
-
...plan.releases.map((r) => `${r.name}@${r.newVersion}`)
|
|
356
|
-
].join("\n")
|
|
359
|
+
input: await resolveCommitMessage(config.versionCommitMessage, plan, rootDir)
|
|
357
360
|
});
|
|
358
361
|
pushWithToken(rootDir, branch, config);
|
|
359
362
|
const prBody = formatVersionPrBody(plan, config.versionPr.preamble, packageDirs);
|
|
@@ -373,7 +376,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
|
|
|
373
376
|
cwd: rootDir,
|
|
374
377
|
input: prBody
|
|
375
378
|
}));
|
|
376
|
-
log.success(
|
|
379
|
+
log.success(`🐸 Updated PR #${validPr}`);
|
|
377
380
|
} else {
|
|
378
381
|
log.step("Creating version PR...");
|
|
379
382
|
const prTitle = config.versionPr.title;
|
|
@@ -393,7 +396,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName, p
|
|
|
393
396
|
cwd: rootDir,
|
|
394
397
|
input: prBody
|
|
395
398
|
}));
|
|
396
|
-
log.success(
|
|
399
|
+
log.success(`🐸 Created PR: ${result}`);
|
|
397
400
|
if (!patPr) pushWithToken(rootDir, branch, config);
|
|
398
401
|
}
|
|
399
402
|
runArgs([
|
|
@@ -428,7 +431,7 @@ function formatReleasePlanComment(plan, bumpFiles, prNumber, prBranch, pm, warni
|
|
|
428
431
|
const repo = process.env.GITHUB_REPOSITORY;
|
|
429
432
|
const lines = [];
|
|
430
433
|
const preamble = [
|
|
431
|
-
`<a href="https://
|
|
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>`,
|
|
432
435
|
"",
|
|
433
436
|
"**The changes in this PR will be included in the next version bump.**",
|
|
434
437
|
"<br clear=\"left\" />"
|
|
@@ -478,13 +481,13 @@ function formatReleasePlanComment(plan, bumpFiles, prNumber, prBranch, pm, warni
|
|
|
478
481
|
if (addLink) lines.push(`[Click here if you want to add another bump file to this PR](${addLink})\n`);
|
|
479
482
|
else lines.push(`To add another bump file, run \`${pmRunCommand(pm)} add\`\n`);
|
|
480
483
|
lines.push("---");
|
|
481
|
-
lines.push(`_This comment is maintained by [bumpy](https://
|
|
484
|
+
lines.push(`_This comment is maintained by [bumpy](https://bumpy.varlock.dev)._`);
|
|
482
485
|
return lines.join("\n");
|
|
483
486
|
}
|
|
484
487
|
function formatNoBumpFilesComment(prBranch, pm) {
|
|
485
488
|
const runCmd = pmRunCommand(pm);
|
|
486
489
|
const lines = [
|
|
487
|
-
`<a href="https://
|
|
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>`,
|
|
488
491
|
"",
|
|
489
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.**",
|
|
490
493
|
"<br clear=\"left\" />\n",
|
|
@@ -499,7 +502,7 @@ function formatNoBumpFilesComment(prBranch, pm) {
|
|
|
499
502
|
lines.push(`Or [click here to add a bump file](${addLink}) directly on GitHub.`);
|
|
500
503
|
}
|
|
501
504
|
lines.push("\n---");
|
|
502
|
-
lines.push(`_This comment is maintained by [bumpy](https://
|
|
505
|
+
lines.push(`_This comment is maintained by [bumpy](https://bumpy.varlock.dev)._`);
|
|
503
506
|
return lines.join("\n");
|
|
504
507
|
}
|
|
505
508
|
function bumpSectionHeader(type) {
|
|
@@ -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-
|
|
3
|
-
import {
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-DmOYgmfD.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-
|
|
73
|
+
const { checkCommand } = await import("./check-BjWF6SJm.mjs");
|
|
80
74
|
await checkCommand(rootDir);
|
|
81
75
|
break;
|
|
82
76
|
}
|
|
@@ -85,14 +79,14 @@ 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-
|
|
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
85
|
failOnMissing: ciFlags["fail-on-missing"] === true,
|
|
92
86
|
patComments: ciFlags["pat-comments"] === true
|
|
93
87
|
});
|
|
94
88
|
} else if (subcommand === "release") {
|
|
95
|
-
const { ciReleaseCommand } = await import("./ci-
|
|
89
|
+
const { ciReleaseCommand } = await import("./ci-DY58ugIi.mjs");
|
|
96
90
|
await ciReleaseCommand(rootDir, {
|
|
97
91
|
mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
|
|
98
92
|
tag: ciFlags.tag,
|
|
@@ -100,7 +94,7 @@ async function main() {
|
|
|
100
94
|
patPr: ciFlags["pat-pr"] === true
|
|
101
95
|
});
|
|
102
96
|
} else if (subcommand === "setup") {
|
|
103
|
-
const { ciSetupCommand } = await import("./ci-setup-
|
|
97
|
+
const { ciSetupCommand } = await import("./ci-setup-BQwktQEe.mjs");
|
|
104
98
|
await ciSetupCommand(rootDir);
|
|
105
99
|
} else {
|
|
106
100
|
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
|
|
@@ -110,7 +104,7 @@ async function main() {
|
|
|
110
104
|
}
|
|
111
105
|
case "publish": {
|
|
112
106
|
const rootDir = await findRoot();
|
|
113
|
-
const { publishCommand } = await import("./publish-
|
|
107
|
+
const { publishCommand } = await import("./publish-CGB4TIKD.mjs");
|
|
114
108
|
await publishCommand(rootDir, {
|
|
115
109
|
dryRun: flags["dry-run"] === true,
|
|
116
110
|
tag: flags.tag,
|
|
@@ -134,7 +128,7 @@ async function main() {
|
|
|
134
128
|
}
|
|
135
129
|
case "--version":
|
|
136
130
|
case "-v":
|
|
137
|
-
console.log(`bumpy 1.
|
|
131
|
+
console.log(`bumpy 1.1.0`);
|
|
138
132
|
break;
|
|
139
133
|
case "help":
|
|
140
134
|
case "--help":
|
|
@@ -154,22 +148,21 @@ async function main() {
|
|
|
154
148
|
}
|
|
155
149
|
function printHelp() {
|
|
156
150
|
console.log(`
|
|
157
|
-
${colorize(`🐸 bumpy v1.
|
|
151
|
+
${colorize(`🐸 bumpy v1.1.0`, "bold")} - Modern monorepo versioning
|
|
158
152
|
|
|
159
153
|
Usage: bumpy <command> [options]
|
|
160
154
|
|
|
161
155
|
Commands:
|
|
162
|
-
init
|
|
156
|
+
init [--force] Initialize .bumpy/ (migrates from .changeset/ if found)
|
|
163
157
|
add Create a new bump file
|
|
164
|
-
generate Generate bump file from
|
|
158
|
+
generate Generate bump file from branch commits
|
|
165
159
|
status Show pending releases
|
|
166
160
|
check Verify changed packages have bump files (for pre-push hooks)
|
|
167
|
-
version
|
|
161
|
+
version [--commit] Apply bump files and bump versions
|
|
168
162
|
publish Publish versioned packages
|
|
169
163
|
ci check PR check — report pending releases, comment on PR
|
|
170
164
|
ci release Release — create version PR or auto-publish
|
|
171
165
|
ci setup Set up a token for triggering CI on version PRs
|
|
172
|
-
migrate Migrate from .changeset/ to .bumpy/
|
|
173
166
|
ai setup Install AI skill for creating bump files
|
|
174
167
|
|
|
175
168
|
Add options:
|
|
@@ -179,7 +172,7 @@ function printHelp() {
|
|
|
179
172
|
--empty Create an empty bump file
|
|
180
173
|
|
|
181
174
|
Generate options:
|
|
182
|
-
--from <ref> Git ref to scan from (default:
|
|
175
|
+
--from <ref> Git ref to scan from (default: branch point from baseBranch)
|
|
183
176
|
--dry-run Preview without creating a bump file
|
|
184
177
|
--name <name> Bump file filename
|
|
185
178
|
|
|
@@ -208,7 +201,7 @@ function printHelp() {
|
|
|
208
201
|
AI setup options:
|
|
209
202
|
--target <tool> Target AI tool: opencode, cursor, codex
|
|
210
203
|
|
|
211
|
-
${colorize("https://
|
|
204
|
+
${colorize("https://bumpy.varlock.dev", "dim")}
|
|
212
205
|
`);
|
|
213
206
|
}
|
|
214
207
|
main();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
//#region src/core/commit-message.ts
|
|
3
|
+
/** Build the default version commit message */
|
|
4
|
+
function defaultCommitMessage(plan) {
|
|
5
|
+
return [
|
|
6
|
+
"Version packages",
|
|
7
|
+
"",
|
|
8
|
+
...plan.releases.map((r) => `${r.name}@${r.newVersion}`)
|
|
9
|
+
].join("\n");
|
|
10
|
+
}
|
|
11
|
+
/** Resolve the commit message from config, falling back to the default */
|
|
12
|
+
async function resolveCommitMessage(config, plan, rootDir) {
|
|
13
|
+
if (!config) return defaultCommitMessage(plan);
|
|
14
|
+
if (config.startsWith("./") || config.startsWith("../")) {
|
|
15
|
+
const mod = await import(resolve(rootDir, config));
|
|
16
|
+
const fn = mod.default ?? mod;
|
|
17
|
+
if (typeof fn !== "function") throw new Error(`versionCommitMessage module "${config}" must export a function`);
|
|
18
|
+
return fn(plan);
|
|
19
|
+
}
|
|
20
|
+
return config;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { resolveCommitMessage as t };
|
|
@@ -44,7 +44,8 @@ const DEFAULT_PUBLISH_CONFIG = {
|
|
|
44
44
|
const DEFAULT_CONFIG = {
|
|
45
45
|
baseBranch: "main",
|
|
46
46
|
access: "public",
|
|
47
|
-
|
|
47
|
+
versionCommitMessage: void 0,
|
|
48
|
+
changedFilePatterns: ["**"],
|
|
48
49
|
changelog: "default",
|
|
49
50
|
fixed: [],
|
|
50
51
|
linked: [],
|
|
@@ -68,9 +69,9 @@ const DEFAULT_CONFIG = {
|
|
|
68
69
|
title: "🐸 Versioned release",
|
|
69
70
|
branch: "bumpy/version-packages",
|
|
70
71
|
preamble: [
|
|
71
|
-
`<a href="https://
|
|
72
|
+
`<a href="https://bumpy.varlock.dev"><img src="https://raw.githubusercontent.com/dmno-dev/bumpy/main/images/frog-talking.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
|
|
72
73
|
"",
|
|
73
|
-
`This PR was created and will be kept in sync by [bumpy](https://
|
|
74
|
+
`This PR was created and will be kept in sync by [bumpy](https://bumpy.varlock.dev) based on your .bumpy bump files. Merge it when you are ready to release the packages listed below:`,
|
|
74
75
|
"<br clear=\"left\" />"
|
|
75
76
|
].join("\n")
|
|
76
77
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
2
|
import { t as ensureDir } from "./fs-DYR2XuFE.mjs";
|
|
3
|
-
import { a as loadConfig, r as getBumpyDir } from "./config-
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
5
|
-
import {
|
|
6
|
-
import { i as writeBumpFile } from "./bump-file-
|
|
7
|
-
import {
|
|
3
|
+
import { a as loadConfig, r as getBumpyDir } from "./config-B-Qg3DZH.mjs";
|
|
4
|
+
import { t as discoverPackages } from "./workspace-DWXlwcH4.mjs";
|
|
5
|
+
import { s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
6
|
+
import { i as writeBumpFile } from "./bump-file-DVqR3k67.mjs";
|
|
7
|
+
import { i as getFilesChangedInCommit, n as getBranchCommits } from "./git-YDedMddc.mjs";
|
|
8
|
+
import { n as slugify, t as randomName } from "./names-C-TuOPbd.mjs";
|
|
9
|
+
import { relative } from "node:path";
|
|
8
10
|
//#region src/commands/generate.ts
|
|
9
11
|
const BUMP_MAP = {
|
|
10
12
|
feat: "minor",
|
|
@@ -21,57 +23,62 @@ const BUMP_MAP = {
|
|
|
21
23
|
async function generateCommand(rootDir, opts) {
|
|
22
24
|
const config = await loadConfig(rootDir);
|
|
23
25
|
const packages = await discoverPackages(rootDir, config);
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
log.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
let commits;
|
|
27
|
+
if (opts.from) {
|
|
28
|
+
log.step(`Scanning commits from ${colorize(opts.from, "cyan")}...`);
|
|
29
|
+
const rawLog = tryRunArgs([
|
|
30
|
+
"git",
|
|
31
|
+
"log",
|
|
32
|
+
`${opts.from}..HEAD`,
|
|
33
|
+
"--format=%H%n%s%n%b%n---END---"
|
|
34
|
+
], { cwd: rootDir });
|
|
35
|
+
if (!rawLog) {
|
|
36
|
+
log.info("No commits found since " + opts.from);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
commits = parseGitLog(rawLog);
|
|
40
|
+
} else {
|
|
41
|
+
log.step(`Scanning commits on this branch (vs ${colorize(config.baseBranch, "cyan")})...`);
|
|
42
|
+
commits = getBranchCommits(rootDir, config.baseBranch);
|
|
39
43
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
log.info("No conventional commits found. Commits must follow the format: type(scope): description");
|
|
44
|
+
if (commits.length === 0) {
|
|
45
|
+
log.info("No commits found on this branch.");
|
|
43
46
|
return;
|
|
44
47
|
}
|
|
45
|
-
log.dim(` Found ${
|
|
48
|
+
log.dim(` Found ${commits.length} commit(s)`);
|
|
46
49
|
const scopeMap = buildScopeMap(packages, config);
|
|
47
50
|
const releaseMap = /* @__PURE__ */ new Map();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
let ccCount = 0;
|
|
52
|
+
let fileBasedCount = 0;
|
|
53
|
+
for (const commit of commits) {
|
|
54
|
+
const cc = parseConventionalCommit(commit);
|
|
55
|
+
if (cc) {
|
|
56
|
+
ccCount++;
|
|
57
|
+
const bump = cc.breaking ? "major" : BUMP_MAP[cc.type] || "patch";
|
|
58
|
+
let pkgNames = [];
|
|
59
|
+
if (cc.scope) {
|
|
60
|
+
const resolved = resolveScope(cc.scope, scopeMap, packages);
|
|
61
|
+
if (resolved.length > 0) pkgNames = resolved;
|
|
62
|
+
}
|
|
63
|
+
if (pkgNames.length > 0) {
|
|
64
|
+
for (const name of pkgNames) mergeRelease(releaseMap, name, bump, cc.description);
|
|
56
65
|
continue;
|
|
57
66
|
}
|
|
67
|
+
const touchedPkgs = mapFilesToPackages(getFilesChangedInCommit(commit.hash, { cwd: rootDir }), packages, rootDir);
|
|
68
|
+
if (touchedPkgs.length > 0) for (const name of touchedPkgs) mergeRelease(releaseMap, name, bump, cc.description);
|
|
69
|
+
else log.dim(` Skipping CC (no matching packages): ${cc.type}: ${cc.description}`);
|
|
58
70
|
} else {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (existing) {
|
|
65
|
-
if (bumpPriority(bump) > bumpPriority(existing.type)) existing.type = bump;
|
|
66
|
-
existing.messages.push(commit.description);
|
|
67
|
-
} else releaseMap.set(name, {
|
|
68
|
-
type: bump,
|
|
69
|
-
messages: [commit.description]
|
|
70
|
-
});
|
|
71
|
+
const touchedPkgs = mapFilesToPackages(getFilesChangedInCommit(commit.hash, { cwd: rootDir }), packages, rootDir);
|
|
72
|
+
if (touchedPkgs.length > 0) {
|
|
73
|
+
fileBasedCount++;
|
|
74
|
+
for (const name of touchedPkgs) mergeRelease(releaseMap, name, "patch", commit.subject);
|
|
75
|
+
} else log.dim(` Skipping (no matching packages): ${commit.subject}`);
|
|
71
76
|
}
|
|
72
77
|
}
|
|
78
|
+
if (ccCount > 0) log.dim(` ${ccCount} conventional commit(s)`);
|
|
79
|
+
if (fileBasedCount > 0) log.dim(` ${fileBasedCount} commit(s) detected via changed files`);
|
|
73
80
|
if (releaseMap.size === 0) {
|
|
74
|
-
log.info("No package bumps detected from
|
|
81
|
+
log.info("No package bumps detected from commits.");
|
|
75
82
|
return;
|
|
76
83
|
}
|
|
77
84
|
const releases = [];
|
|
@@ -94,9 +101,29 @@ async function generateCommand(rootDir, opts) {
|
|
|
94
101
|
await ensureDir(getBumpyDir(rootDir));
|
|
95
102
|
const filename = opts.name ? slugify(opts.name) : randomName();
|
|
96
103
|
await writeBumpFile(rootDir, filename, releases, summaryLines.join("\n"));
|
|
97
|
-
log.success(
|
|
104
|
+
log.success(`🐸 Created bump file: .bumpy/${filename}.md`);
|
|
98
105
|
for (const r of releases) log.dim(` ${r.name}: ${r.type}`);
|
|
99
106
|
}
|
|
107
|
+
/** Merge a bump into the release map, keeping the highest bump level */
|
|
108
|
+
function mergeRelease(releaseMap, name, bump, message) {
|
|
109
|
+
const existing = releaseMap.get(name);
|
|
110
|
+
if (existing) {
|
|
111
|
+
if (bumpPriority(bump) > bumpPriority(existing.type)) existing.type = bump;
|
|
112
|
+
existing.messages.push(message);
|
|
113
|
+
} else releaseMap.set(name, {
|
|
114
|
+
type: bump,
|
|
115
|
+
messages: [message]
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/** Map file paths to package names based on directory containment */
|
|
119
|
+
function mapFilesToPackages(files, packages, rootDir) {
|
|
120
|
+
const matched = /* @__PURE__ */ new Set();
|
|
121
|
+
for (const file of files) for (const [name, pkg] of packages) {
|
|
122
|
+
const pkgRelDir = relative(rootDir, pkg.dir);
|
|
123
|
+
if (file.startsWith(pkgRelDir + "/")) matched.add(name);
|
|
124
|
+
}
|
|
125
|
+
return [...matched];
|
|
126
|
+
}
|
|
100
127
|
/** Parse raw git log output into individual commits */
|
|
101
128
|
function parseGitLog(raw) {
|
|
102
129
|
const commits = [];
|
|
@@ -155,23 +182,5 @@ function resolveScope(scope, scopeMap, packages) {
|
|
|
155
182
|
function bumpPriority(type) {
|
|
156
183
|
return type === "major" ? 2 : type === "minor" ? 1 : 0;
|
|
157
184
|
}
|
|
158
|
-
/** Find the most recent version tag in the repo */
|
|
159
|
-
function findLastVersionTag(rootDir) {
|
|
160
|
-
return tryRunArgs([
|
|
161
|
-
"git",
|
|
162
|
-
"describe",
|
|
163
|
-
"--tags",
|
|
164
|
-
"--abbrev=0",
|
|
165
|
-
"--match",
|
|
166
|
-
"v*"
|
|
167
|
-
], { cwd: rootDir }) || tryRunArgs([
|
|
168
|
-
"git",
|
|
169
|
-
"describe",
|
|
170
|
-
"--tags",
|
|
171
|
-
"--abbrev=0",
|
|
172
|
-
"--match",
|
|
173
|
-
"*@*"
|
|
174
|
-
], { cwd: rootDir }) || null;
|
|
175
|
-
}
|
|
176
185
|
//#endregion
|
|
177
186
|
export { generateCommand };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as runArgs, s as tryRunArgs } from "./shell-CY7OD48z.mjs";
|
|
2
2
|
//#region src/core/git.ts
|
|
3
3
|
/** Create a git tag */
|
|
4
4
|
function createTag(tag, opts) {
|
|
@@ -63,6 +63,58 @@ function getChangedFiles(rootDir, baseBranch) {
|
|
|
63
63
|
if (!diff) return [];
|
|
64
64
|
return diff.split("\n").filter(Boolean);
|
|
65
65
|
}
|
|
66
|
+
/** Get commits on the current branch since it diverged from baseBranch */
|
|
67
|
+
function getBranchCommits(rootDir, baseBranch) {
|
|
68
|
+
if (!tryRunArgs([
|
|
69
|
+
"git",
|
|
70
|
+
"rev-parse",
|
|
71
|
+
"--verify",
|
|
72
|
+
`origin/${baseBranch}`
|
|
73
|
+
], { cwd: rootDir })) tryRunArgs([
|
|
74
|
+
"git",
|
|
75
|
+
"fetch",
|
|
76
|
+
"origin",
|
|
77
|
+
baseBranch,
|
|
78
|
+
"--depth=1"
|
|
79
|
+
], { cwd: rootDir });
|
|
80
|
+
const rawLog = tryRunArgs([
|
|
81
|
+
"git",
|
|
82
|
+
"log",
|
|
83
|
+
`${tryRunArgs([
|
|
84
|
+
"git",
|
|
85
|
+
"merge-base",
|
|
86
|
+
"HEAD",
|
|
87
|
+
`origin/${baseBranch}`
|
|
88
|
+
], { cwd: rootDir }) || `origin/${baseBranch}`}..HEAD`,
|
|
89
|
+
"--format=%H%n%s%n%b%n---END---"
|
|
90
|
+
], { cwd: rootDir });
|
|
91
|
+
if (!rawLog) return [];
|
|
92
|
+
const commits = [];
|
|
93
|
+
const entries = rawLog.split("---END---").filter((e) => e.trim());
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
const lines = entry.trim().split("\n");
|
|
96
|
+
if (lines.length < 2) continue;
|
|
97
|
+
commits.push({
|
|
98
|
+
hash: lines[0].trim(),
|
|
99
|
+
subject: lines[1].trim(),
|
|
100
|
+
body: lines.slice(2).join("\n").trim()
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return commits;
|
|
104
|
+
}
|
|
105
|
+
/** Get files changed in a specific commit */
|
|
106
|
+
function getFilesChangedInCommit(hash, opts) {
|
|
107
|
+
const result = tryRunArgs([
|
|
108
|
+
"git",
|
|
109
|
+
"diff-tree",
|
|
110
|
+
"--no-commit-id",
|
|
111
|
+
"--name-only",
|
|
112
|
+
"-r",
|
|
113
|
+
hash
|
|
114
|
+
], opts);
|
|
115
|
+
if (!result) return [];
|
|
116
|
+
return result.split("\n").filter(Boolean);
|
|
117
|
+
}
|
|
66
118
|
/** Get all tags matching a pattern */
|
|
67
119
|
function listTags(pattern, opts) {
|
|
68
120
|
const result = tryRunArgs([
|
|
@@ -75,4 +127,4 @@ function listTags(pattern, opts) {
|
|
|
75
127
|
return result.split("\n").filter(Boolean);
|
|
76
128
|
}
|
|
77
129
|
//#endregion
|
|
78
|
-
export {
|
|
130
|
+
export { hasUncommittedChanges as a, tagExists as c, getFilesChangedInCommit as i, getBranchCommits as n, listTags as o, getChangedFiles as r, pushWithTags as s, createTag as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -32,10 +32,19 @@ interface PublishConfig {
|
|
|
32
32
|
interface BumpyConfig {
|
|
33
33
|
baseBranch: string;
|
|
34
34
|
access: 'public' | 'restricted';
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Customize the commit message used when versioning.
|
|
37
|
+
* A string starting with "./" is treated as a path to a module that exports
|
|
38
|
+
* a function receiving the release plan and returning a message string.
|
|
39
|
+
* Any other string is used as a static commit message.
|
|
40
|
+
* Omit to use the default: "Version packages\n\npkg@version..."
|
|
41
|
+
*/
|
|
42
|
+
versionCommitMessage?: string;
|
|
43
|
+
changelog: false | string | [string, Record<string, unknown>];
|
|
37
44
|
fixed: string[][];
|
|
38
45
|
linked: string[][];
|
|
46
|
+
/** Glob patterns to filter which changed files count toward marking a package as changed */
|
|
47
|
+
changedFilePatterns: string[];
|
|
39
48
|
/** Package names/globs to exclude from version management */
|
|
40
49
|
ignore: string[];
|
|
41
50
|
/** Package names/globs to explicitly include (overrides private + ignore) */
|
|
@@ -90,6 +99,8 @@ interface PackageConfig {
|
|
|
90
99
|
skipNpmPublish?: boolean;
|
|
91
100
|
/** Command to check if a version is already published. Should output the published version string. */
|
|
92
101
|
checkPublished?: string;
|
|
102
|
+
/** Glob patterns to filter which changed files count toward marking this package as changed */
|
|
103
|
+
changedFilePatterns?: string[];
|
|
93
104
|
dependencyBumpRules?: Partial<Record<DepType, DependencyBumpRule | false>>;
|
|
94
105
|
cascadeTo?: Record<string, DependencyBumpRule>;
|
|
95
106
|
}
|