@varlock/bumpy 0.0.2 → 1.0.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/.claude-plugin/plugin.json +2 -2
- package/dist/add-CgCjs4d-.mjs +313 -0
- package/dist/{ai-CQhUyHAG.mjs → ai-sMYUf3lP.mjs} +21 -4
- package/dist/{apply-release-plan-D6TSrcwX.mjs → apply-release-plan-CczGWJTk.mjs} +28 -24
- package/dist/bump-file-CCLXMLA8.mjs +143 -0
- package/dist/{changelog-github-Du62krXi.mjs → changelog-github-Cd8uJHZI.mjs} +22 -20
- package/dist/{check-jIwike9F.mjs → check-BOoxpWqk.mjs} +9 -9
- package/dist/{ci-D6LQbR38.mjs → ci-Bhx--Tj6.mjs} +116 -72
- package/dist/{ci-setup-C6FlOfW5.mjs → ci-setup-qz4Y3v7T.mjs} +1 -1
- package/dist/cli.mjs +32 -30
- package/dist/{config-BkwIEaQg.mjs → config-XZWUL3ma.mjs} +27 -22
- package/dist/fs-DYR2XuFE.mjs +81 -0
- package/dist/{generate-Btrsn1qi.mjs → generate-gYKTpvex.mjs} +8 -8
- package/dist/index.d.mts +55 -37
- package/dist/index.mjs +8 -8
- package/dist/{init-B0q3wEQW.mjs → init-lA9E5pEc.mjs} +2 -2
- package/dist/{migrate-CfQNwD0T.mjs → migrate-DmOYgmfD.mjs} +10 -10
- package/dist/{names-Ck8cun7B.mjs → names-9VubBmL0.mjs} +1 -1
- package/dist/{package-manager-DcI5TdDE.mjs → package-manager-VCe10bjc.mjs} +1 -1
- package/dist/{publish-D_7RqEYL.mjs → publish-Cun-zQ1b.mjs} +21 -20
- package/dist/{publish-pipeline-ChnqW8nR.mjs → publish-pipeline-BwBuKCIk.mjs} +22 -17
- package/dist/release-plan-Bi5QNSEo.mjs +264 -0
- package/dist/{semver-BTzYh8vc.mjs → semver-DfQyVLM_.mjs} +13 -3
- package/dist/{status--Q8yAxQ4.mjs → status-CfE63ti5.mjs} +25 -21
- package/dist/{version-cAUkfYPx.mjs → version-19vVt9dv.mjs} +16 -12
- package/dist/{workspace-CxEKakDm.mjs → workspace-C5ULTyUN.mjs} +3 -3
- package/package.json +13 -1
- package/skills/add-change/SKILL.md +8 -12
- package/dist/add-BjyVIUlr.mjs +0 -175
- package/dist/changeset-UCZdSRDv.mjs +0 -108
- package/dist/fs-0AtnPUUe.mjs +0 -51
- package/dist/release-plan-BEzwApuK.mjs +0 -173
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-XZWUL3ma.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-
|
|
28
|
+
const { initCommand } = await import("./init-lA9E5pEc.mjs");
|
|
29
29
|
await initCommand(rootDir);
|
|
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-CgCjs4d-.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-CfE63ti5.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-
|
|
57
|
+
const { versionCommand } = await import("./version-19vVt9dv.mjs");
|
|
58
58
|
await versionCommand(rootDir);
|
|
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-gYKTpvex.mjs");
|
|
64
64
|
await generateCommand(rootDir, {
|
|
65
65
|
from: flags.from,
|
|
66
66
|
dryRun: flags["dry-run"] === true,
|
|
@@ -70,13 +70,13 @@ async function main() {
|
|
|
70
70
|
}
|
|
71
71
|
case "migrate": {
|
|
72
72
|
const rootDir = await findRoot();
|
|
73
|
-
const { migrateCommand } = await import("./migrate-
|
|
73
|
+
const { migrateCommand } = await import("./migrate-DmOYgmfD.mjs");
|
|
74
74
|
await migrateCommand(rootDir, { force: flags.force === true });
|
|
75
75
|
break;
|
|
76
76
|
}
|
|
77
77
|
case "check": {
|
|
78
78
|
const rootDir = await findRoot();
|
|
79
|
-
const { checkCommand } = await import("./check-
|
|
79
|
+
const { checkCommand } = await import("./check-BOoxpWqk.mjs");
|
|
80
80
|
await checkCommand(rootDir);
|
|
81
81
|
break;
|
|
82
82
|
}
|
|
@@ -85,20 +85,22 @@ async function main() {
|
|
|
85
85
|
const subcommand = args[1];
|
|
86
86
|
const ciFlags = parseFlags(args.slice(2));
|
|
87
87
|
if (subcommand === "check") {
|
|
88
|
-
const { ciCheckCommand } = await import("./ci-
|
|
88
|
+
const { ciCheckCommand } = await import("./ci-Bhx--Tj6.mjs");
|
|
89
89
|
await ciCheckCommand(rootDir, {
|
|
90
90
|
comment: ciFlags.comment !== void 0 ? ciFlags.comment === true : void 0,
|
|
91
|
-
failOnMissing: ciFlags["fail-on-missing"] === true
|
|
91
|
+
failOnMissing: ciFlags["fail-on-missing"] === true,
|
|
92
|
+
patComments: ciFlags["pat-comments"] === true
|
|
92
93
|
});
|
|
93
94
|
} else if (subcommand === "release") {
|
|
94
|
-
const { ciReleaseCommand } = await import("./ci-
|
|
95
|
+
const { ciReleaseCommand } = await import("./ci-Bhx--Tj6.mjs");
|
|
95
96
|
await ciReleaseCommand(rootDir, {
|
|
96
97
|
mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
|
|
97
98
|
tag: ciFlags.tag,
|
|
98
|
-
branch: ciFlags.branch
|
|
99
|
+
branch: ciFlags.branch,
|
|
100
|
+
patPr: ciFlags["pat-pr"] === true
|
|
99
101
|
});
|
|
100
102
|
} else if (subcommand === "setup") {
|
|
101
|
-
const { ciSetupCommand } = await import("./ci-setup-
|
|
103
|
+
const { ciSetupCommand } = await import("./ci-setup-qz4Y3v7T.mjs");
|
|
102
104
|
await ciSetupCommand(rootDir);
|
|
103
105
|
} else {
|
|
104
106
|
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
|
|
@@ -108,7 +110,7 @@ async function main() {
|
|
|
108
110
|
}
|
|
109
111
|
case "publish": {
|
|
110
112
|
const rootDir = await findRoot();
|
|
111
|
-
const { publishCommand } = await import("./publish-
|
|
113
|
+
const { publishCommand } = await import("./publish-Cun-zQ1b.mjs");
|
|
112
114
|
await publishCommand(rootDir, {
|
|
113
115
|
dryRun: flags["dry-run"] === true,
|
|
114
116
|
tag: flags.tag,
|
|
@@ -122,7 +124,7 @@ async function main() {
|
|
|
122
124
|
const subcommand = args[1];
|
|
123
125
|
const aiFlags = parseFlags(args.slice(2));
|
|
124
126
|
if (subcommand === "setup") {
|
|
125
|
-
const { aiSetupCommand } = await import("./ai-
|
|
127
|
+
const { aiSetupCommand } = await import("./ai-sMYUf3lP.mjs");
|
|
126
128
|
await aiSetupCommand(rootDir, { target: aiFlags.target });
|
|
127
129
|
} else {
|
|
128
130
|
log.error(`Unknown ai subcommand: ${subcommand}. Use "ai setup".`);
|
|
@@ -132,7 +134,7 @@ async function main() {
|
|
|
132
134
|
}
|
|
133
135
|
case "--version":
|
|
134
136
|
case "-v":
|
|
135
|
-
console.log(`bumpy 0.0
|
|
137
|
+
console.log(`bumpy 1.0.0`);
|
|
136
138
|
break;
|
|
137
139
|
case "help":
|
|
138
140
|
case "--help":
|
|
@@ -152,41 +154,41 @@ async function main() {
|
|
|
152
154
|
}
|
|
153
155
|
function printHelp() {
|
|
154
156
|
console.log(`
|
|
155
|
-
${colorize(`🐸 bumpy
|
|
157
|
+
${colorize(`🐸 bumpy v1.0.0`, "bold")} - Modern monorepo versioning
|
|
156
158
|
|
|
157
159
|
Usage: bumpy <command> [options]
|
|
158
160
|
|
|
159
161
|
Commands:
|
|
160
162
|
init Initialize .bumpy/ directory
|
|
161
|
-
add Create a new
|
|
162
|
-
generate Generate
|
|
163
|
+
add Create a new bump file
|
|
164
|
+
generate Generate bump file from conventional commits
|
|
163
165
|
status Show pending releases
|
|
164
|
-
check Verify changed packages have
|
|
165
|
-
version Apply
|
|
166
|
+
check Verify changed packages have bump files (for pre-push hooks)
|
|
167
|
+
version Apply bump files and bump versions
|
|
166
168
|
publish Publish versioned packages
|
|
167
169
|
ci check PR check — report pending releases, comment on PR
|
|
168
170
|
ci release Release — create version PR or auto-publish
|
|
169
171
|
ci setup Set up a token for triggering CI on version PRs
|
|
170
172
|
migrate Migrate from .changeset/ to .bumpy/
|
|
171
|
-
ai setup Install AI skill for creating
|
|
173
|
+
ai setup Install AI skill for creating bump files
|
|
172
174
|
|
|
173
175
|
Add options:
|
|
174
176
|
--packages <list> Package bumps (e.g., "pkg-a:minor,pkg-b:patch")
|
|
175
|
-
--message <text>
|
|
176
|
-
--name <name>
|
|
177
|
-
--empty Create an empty
|
|
177
|
+
--message <text> Bump file summary
|
|
178
|
+
--name <name> Bump file filename
|
|
179
|
+
--empty Create an empty bump file
|
|
178
180
|
|
|
179
181
|
Generate options:
|
|
180
182
|
--from <ref> Git ref to scan from (default: last version tag)
|
|
181
|
-
--dry-run Preview without creating a
|
|
182
|
-
--name <name>
|
|
183
|
+
--dry-run Preview without creating a bump file
|
|
184
|
+
--name <name> Bump file filename
|
|
183
185
|
|
|
184
186
|
Status options:
|
|
185
|
-
--json Output as JSON (includes dirs,
|
|
187
|
+
--json Output as JSON (includes dirs, bumpFiles, packageNames)
|
|
186
188
|
--packages Output only package names, one per line
|
|
187
189
|
--bump <types> Filter by bump type (e.g., "major", "minor,patch")
|
|
188
190
|
--filter <names> Filter by package name/glob (e.g., "@myorg/*")
|
|
189
|
-
--verbose Show
|
|
191
|
+
--verbose Show bump file details
|
|
190
192
|
|
|
191
193
|
Publish options:
|
|
192
194
|
--dry-run Preview without publishing
|
|
@@ -196,7 +198,7 @@ function printHelp() {
|
|
|
196
198
|
|
|
197
199
|
CI check options:
|
|
198
200
|
--comment Force PR comment on/off (auto-detected in CI)
|
|
199
|
-
--fail-on-missing Exit 1 if no
|
|
201
|
+
--fail-on-missing Exit 1 if no bump files found
|
|
200
202
|
|
|
201
203
|
CI release options:
|
|
202
204
|
--auto-publish Version + publish directly (default: create version PR)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as readJson, n as exists } from "./fs-
|
|
2
|
+
import { a as readJson, n as exists } from "./fs-DYR2XuFE.mjs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
//#region src/types.ts
|
|
5
5
|
const BUMP_LEVELS = {
|
|
@@ -10,16 +10,6 @@ const BUMP_LEVELS = {
|
|
|
10
10
|
function bumpLevel(type) {
|
|
11
11
|
return BUMP_LEVELS[type];
|
|
12
12
|
}
|
|
13
|
-
function parseIsolatedBump(type) {
|
|
14
|
-
if (type.endsWith("-isolated")) return {
|
|
15
|
-
bump: type.replace("-isolated", ""),
|
|
16
|
-
isolated: true
|
|
17
|
-
};
|
|
18
|
-
return {
|
|
19
|
-
bump: type,
|
|
20
|
-
isolated: false
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
13
|
function maxBump(a, b) {
|
|
24
14
|
if (!a) return b;
|
|
25
15
|
return bumpLevel(a) >= bumpLevel(b) ? a : b;
|
|
@@ -31,12 +21,9 @@ const DEFAULT_BUMP_RULES = {
|
|
|
31
21
|
},
|
|
32
22
|
peerDependencies: {
|
|
33
23
|
trigger: "major",
|
|
34
|
-
bumpAs: "
|
|
35
|
-
},
|
|
36
|
-
devDependencies: {
|
|
37
|
-
trigger: "none",
|
|
38
|
-
bumpAs: "patch"
|
|
24
|
+
bumpAs: "match"
|
|
39
25
|
},
|
|
26
|
+
devDependencies: false,
|
|
40
27
|
optionalDependencies: {
|
|
41
28
|
trigger: "minor",
|
|
42
29
|
bumpAs: "patch"
|
|
@@ -69,6 +56,7 @@ const DEFAULT_CONFIG = {
|
|
|
69
56
|
version: false,
|
|
70
57
|
tag: false
|
|
71
58
|
},
|
|
59
|
+
allowCustomCommands: false,
|
|
72
60
|
packages: {},
|
|
73
61
|
publish: { ...DEFAULT_PUBLISH_CONFIG },
|
|
74
62
|
aggregateRelease: false,
|
|
@@ -82,7 +70,7 @@ const DEFAULT_CONFIG = {
|
|
|
82
70
|
preamble: [
|
|
83
71
|
`<a href="https://github.com/dmno-dev/bumpy"><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>`,
|
|
84
72
|
"",
|
|
85
|
-
`This PR was created and will be kept in sync by [bumpy](https://github.com/dmno-dev/bumpy) based on your .bumpy
|
|
73
|
+
`This PR was created and will be kept in sync by [bumpy](https://github.com/dmno-dev/bumpy) based on your .bumpy bump files. Merge it when you are ready to release the packages listed below:`,
|
|
86
74
|
"<br clear=\"left\" />"
|
|
87
75
|
].join("\n")
|
|
88
76
|
}
|
|
@@ -131,6 +119,20 @@ async function loadPackageConfig(pkgDir, rootConfig, pkgName) {
|
|
|
131
119
|
const pkg = await readJson(resolve(pkgDir, "package.json"));
|
|
132
120
|
if (pkg.bumpy && typeof pkg.bumpy === "object") pkgJsonConfig = pkg.bumpy;
|
|
133
121
|
} catch {}
|
|
122
|
+
const disallowedKeys = [
|
|
123
|
+
"buildCommand",
|
|
124
|
+
"publishCommand",
|
|
125
|
+
"checkPublished"
|
|
126
|
+
].filter((k) => pkgJsonConfig[k] != null);
|
|
127
|
+
if (disallowedKeys.length > 0 && !isCustomCommandAllowed(pkgName, rootConfig)) {
|
|
128
|
+
const fields = disallowedKeys.map((k) => `"${k}"`).join(", ");
|
|
129
|
+
throw new Error(`Package "${pkgName}" defines custom command(s) (${fields}) in its package.json "bumpy" config, but the root config does not allow this.
|
|
130
|
+
Custom commands execute shell commands during publishing and must be explicitly enabled.
|
|
131
|
+
|
|
132
|
+
To fix this, either:
|
|
133
|
+
1. Move the command(s) to .bumpy/_config.json under "packages" (always trusted)
|
|
134
|
+
2. Add "allowCustomCommands": true (or ["${pkgName}"]) to .bumpy/_config.json`);
|
|
135
|
+
}
|
|
134
136
|
return mergePackageConfig(rootPkgConfig, pkgJsonConfig);
|
|
135
137
|
}
|
|
136
138
|
/** Find a package config from the root config, supporting glob patterns */
|
|
@@ -175,10 +177,6 @@ function mergePackageConfig(...configs) {
|
|
|
175
177
|
...result.dependencyBumpRules,
|
|
176
178
|
...cfg.dependencyBumpRules
|
|
177
179
|
};
|
|
178
|
-
if (cfg.specificDependencyRules) result.specificDependencyRules = {
|
|
179
|
-
...result.specificDependencyRules,
|
|
180
|
-
...cfg.specificDependencyRules
|
|
181
|
-
};
|
|
182
180
|
if (cfg.cascadeTo) result.cascadeTo = {
|
|
183
181
|
...result.cascadeTo,
|
|
184
182
|
...cfg.cascadeTo
|
|
@@ -186,6 +184,13 @@ function mergePackageConfig(...configs) {
|
|
|
186
184
|
}
|
|
187
185
|
return result;
|
|
188
186
|
}
|
|
187
|
+
/** Check if a package is allowed to define custom commands via package.json */
|
|
188
|
+
function isCustomCommandAllowed(pkgName, config) {
|
|
189
|
+
const { allowCustomCommands } = config;
|
|
190
|
+
if (allowCustomCommands === true) return true;
|
|
191
|
+
if (Array.isArray(allowCustomCommands)) return allowCustomCommands.some((pattern) => matchGlob(pkgName, pattern));
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
189
194
|
function getBumpyDir(rootDir) {
|
|
190
195
|
return resolve(rootDir, BUMPY_DIR);
|
|
191
196
|
}
|
|
@@ -212,4 +217,4 @@ function isPackageManaged(pkgName, isPrivate, config, pkgBumpy) {
|
|
|
212
217
|
return true;
|
|
213
218
|
}
|
|
214
219
|
//#endregion
|
|
215
|
-
export { loadConfig as a, BUMP_LEVELS as c, DEFAULT_PUBLISH_CONFIG as d, DEP_TYPES as f,
|
|
220
|
+
export { loadConfig as a, BUMP_LEVELS as c, DEFAULT_PUBLISH_CONFIG as d, DEP_TYPES as f, maxBump as h, isPackageManaged as i, DEFAULT_BUMP_RULES as l, hasCascade as m, findRoot as n, loadPackageConfig as o, bumpLevel as p, getBumpyDir as r, matchGlob as s, config_exports as t, DEFAULT_CONFIG as u };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
2
|
+
import { access, mkdir, readFile, readdir, unlink, writeFile } from "node:fs/promises";
|
|
3
|
+
//#region src/utils/fs.ts
|
|
4
|
+
var fs_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
ensureDir: () => ensureDir,
|
|
6
|
+
exists: () => exists,
|
|
7
|
+
listFiles: () => listFiles,
|
|
8
|
+
readJson: () => readJson,
|
|
9
|
+
readText: () => readText,
|
|
10
|
+
removeFile: () => removeFile,
|
|
11
|
+
updateJsonFields: () => updateJsonFields,
|
|
12
|
+
updateJsonNestedField: () => updateJsonNestedField,
|
|
13
|
+
writeJson: () => writeJson,
|
|
14
|
+
writeText: () => writeText
|
|
15
|
+
});
|
|
16
|
+
async function readJson(filePath) {
|
|
17
|
+
const content = await readFile(filePath, "utf-8");
|
|
18
|
+
return JSON.parse(content);
|
|
19
|
+
}
|
|
20
|
+
async function writeJson(filePath, data, indent = 2) {
|
|
21
|
+
await writeFile(filePath, JSON.stringify(data, null, indent) + "\n", "utf-8");
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Update specific top-level string fields in a JSON file without reformatting.
|
|
25
|
+
* Reads the raw text, does targeted regex replacements, and writes it back.
|
|
26
|
+
*/
|
|
27
|
+
async function updateJsonFields(filePath, updates) {
|
|
28
|
+
let content = await readFile(filePath, "utf-8");
|
|
29
|
+
for (const [key, newValue] of Object.entries(updates)) {
|
|
30
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
31
|
+
const pattern = new RegExp(`("${escaped}"\\s*:\\s*)"[^"]*"`);
|
|
32
|
+
content = content.replace(pattern, `$1"${newValue}"`);
|
|
33
|
+
}
|
|
34
|
+
await writeFile(filePath, content, "utf-8");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Update a nested string field inside a top-level object in a JSON file without reformatting.
|
|
38
|
+
* e.g., updateJsonNestedField(path, 'dependencies', 'core', '^2.0.0')
|
|
39
|
+
*/
|
|
40
|
+
async function updateJsonNestedField(filePath, parentKey, childKey, newValue) {
|
|
41
|
+
let content = await readFile(filePath, "utf-8");
|
|
42
|
+
const parentEscaped = parentKey.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
43
|
+
const childEscaped = childKey.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
44
|
+
const parentPattern = new RegExp(`("${parentEscaped}"\\s*:\\s*\\{)([^}]*)\\}`, "s");
|
|
45
|
+
content = content.replace(parentPattern, (match, prefix, body) => {
|
|
46
|
+
const childPattern = new RegExp(`("${childEscaped}"\\s*:\\s*)"[^"]*"`);
|
|
47
|
+
return `${prefix}${body.replace(childPattern, `$1"${newValue}"`)}}`;
|
|
48
|
+
});
|
|
49
|
+
await writeFile(filePath, content, "utf-8");
|
|
50
|
+
}
|
|
51
|
+
async function readText(filePath) {
|
|
52
|
+
return readFile(filePath, "utf-8");
|
|
53
|
+
}
|
|
54
|
+
async function writeText(filePath, content) {
|
|
55
|
+
await writeFile(filePath, content, "utf-8");
|
|
56
|
+
}
|
|
57
|
+
async function exists(filePath) {
|
|
58
|
+
try {
|
|
59
|
+
await access(filePath);
|
|
60
|
+
return true;
|
|
61
|
+
} catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function listFiles(dir, ext) {
|
|
66
|
+
try {
|
|
67
|
+
const entries = await readdir(dir);
|
|
68
|
+
if (ext) return entries.filter((e) => e.endsWith(ext));
|
|
69
|
+
return entries;
|
|
70
|
+
} catch {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function removeFile(filePath) {
|
|
75
|
+
await unlink(filePath);
|
|
76
|
+
}
|
|
77
|
+
async function ensureDir(dir) {
|
|
78
|
+
await mkdir(dir, { recursive: true });
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { readJson as a, updateJsonFields as c, writeText as d, listFiles as i, updateJsonNestedField as l, exists as n, readText as o, fs_exports as r, removeFile as s, ensureDir as t, writeJson as u };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { t as ensureDir } from "./fs-
|
|
3
|
-
import { a as loadConfig, r as getBumpyDir } from "./config-
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
2
|
+
import { t as ensureDir } from "./fs-DYR2XuFE.mjs";
|
|
3
|
+
import { a as loadConfig, r as getBumpyDir } from "./config-XZWUL3ma.mjs";
|
|
4
|
+
import { t as discoverPackages } from "./workspace-C5ULTyUN.mjs";
|
|
5
5
|
import { o as tryRunArgs } from "./shell-Dj7JRD_q.mjs";
|
|
6
|
-
import { i as
|
|
7
|
-
import { n as slugify, t as randomName } from "./names-
|
|
6
|
+
import { i as writeBumpFile } from "./bump-file-CCLXMLA8.mjs";
|
|
7
|
+
import { n as slugify, t as randomName } from "./names-9VubBmL0.mjs";
|
|
8
8
|
//#region src/commands/generate.ts
|
|
9
9
|
const BUMP_MAP = {
|
|
10
10
|
feat: "minor",
|
|
@@ -84,7 +84,7 @@ async function generateCommand(rootDir, opts) {
|
|
|
84
84
|
for (const msg of info.messages) summaryLines.push(`- ${name}: ${msg}`);
|
|
85
85
|
}
|
|
86
86
|
if (opts.dryRun) {
|
|
87
|
-
log.bold("Would create
|
|
87
|
+
log.bold("Would create bump file:");
|
|
88
88
|
for (const r of releases) console.log(` ${r.name}: ${colorize(r.type, r.type === "major" ? "red" : r.type === "minor" ? "yellow" : "green")}`);
|
|
89
89
|
console.log();
|
|
90
90
|
log.dim("Summary:");
|
|
@@ -93,8 +93,8 @@ async function generateCommand(rootDir, opts) {
|
|
|
93
93
|
}
|
|
94
94
|
await ensureDir(getBumpyDir(rootDir));
|
|
95
95
|
const filename = opts.name ? slugify(opts.name) : randomName();
|
|
96
|
-
await
|
|
97
|
-
log.success(`Created
|
|
96
|
+
await writeBumpFile(rootDir, filename, releases, summaryLines.join("\n"));
|
|
97
|
+
log.success(`Created bump file: .bumpy/${filename}.md`);
|
|
98
98
|
for (const r of releases) log.dim(` ${r.name}: ${r.type}`);
|
|
99
99
|
}
|
|
100
100
|
/** Parse raw git log output into individual commits */
|
package/dist/index.d.mts
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
2
|
type BumpType = 'major' | 'minor' | 'patch';
|
|
3
|
-
type
|
|
3
|
+
type BumpTypeWithNone = BumpType | 'none';
|
|
4
4
|
declare const BUMP_LEVELS: Record<BumpType, number>;
|
|
5
5
|
declare function bumpLevel(type: BumpType): number;
|
|
6
|
-
declare function parseIsolatedBump(type: BumpTypeWithIsolated): {
|
|
7
|
-
bump: BumpType;
|
|
8
|
-
isolated: boolean;
|
|
9
|
-
};
|
|
10
6
|
declare function maxBump(a: BumpType | undefined, b: BumpType): BumpType;
|
|
11
7
|
interface DependencyBumpRule {
|
|
12
8
|
/** What bump level in the dependency triggers propagation */
|
|
13
|
-
trigger: BumpType
|
|
9
|
+
trigger: BumpType;
|
|
14
10
|
/** What bump to apply to the dependent */
|
|
15
11
|
bumpAs: BumpType | 'match';
|
|
16
12
|
}
|
|
17
|
-
declare const DEFAULT_BUMP_RULES: Record<string, DependencyBumpRule>;
|
|
13
|
+
declare const DEFAULT_BUMP_RULES: Record<string, DependencyBumpRule | false>;
|
|
18
14
|
type DepType = 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies';
|
|
19
15
|
declare const DEP_TYPES: DepType[];
|
|
20
16
|
interface PublishConfig {
|
|
@@ -44,12 +40,22 @@ interface BumpyConfig {
|
|
|
44
40
|
ignore: string[];
|
|
45
41
|
/** Package names/globs to explicitly include (overrides private + ignore) */
|
|
46
42
|
include: string[];
|
|
47
|
-
updateInternalDependencies: 'patch' | 'minor' | 'out-of-range'
|
|
48
|
-
dependencyBumpRules: Partial<Record<DepType, DependencyBumpRule>>;
|
|
43
|
+
updateInternalDependencies: 'patch' | 'minor' | 'out-of-range';
|
|
44
|
+
dependencyBumpRules: Partial<Record<DepType, DependencyBumpRule | false>>;
|
|
49
45
|
privatePackages: {
|
|
50
46
|
version: boolean;
|
|
51
47
|
tag: boolean;
|
|
52
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Allow per-package custom commands (buildCommand, publishCommand, checkPublished)
|
|
51
|
+
* defined in package.json "bumpy" fields.
|
|
52
|
+
* Commands defined in the root config's `packages` map are always trusted.
|
|
53
|
+
*
|
|
54
|
+
* true = allow all packages to define custom commands
|
|
55
|
+
* string[] = allow only matching package names/globs
|
|
56
|
+
* false = only root-config commands are allowed (default)
|
|
57
|
+
*/
|
|
58
|
+
allowCustomCommands: boolean | string[];
|
|
53
59
|
packages: Record<string, PackageConfig>;
|
|
54
60
|
publish: PublishConfig;
|
|
55
61
|
/**
|
|
@@ -84,26 +90,25 @@ interface PackageConfig {
|
|
|
84
90
|
skipNpmPublish?: boolean;
|
|
85
91
|
/** Command to check if a version is already published. Should output the published version string. */
|
|
86
92
|
checkPublished?: string;
|
|
87
|
-
dependencyBumpRules?: Partial<Record<DepType, DependencyBumpRule>>;
|
|
88
|
-
specificDependencyRules?: Record<string, DependencyBumpRule>;
|
|
93
|
+
dependencyBumpRules?: Partial<Record<DepType, DependencyBumpRule | false>>;
|
|
89
94
|
cascadeTo?: Record<string, DependencyBumpRule>;
|
|
90
95
|
}
|
|
91
96
|
declare const DEFAULT_PUBLISH_CONFIG: PublishConfig;
|
|
92
97
|
declare const DEFAULT_CONFIG: BumpyConfig;
|
|
93
|
-
interface
|
|
98
|
+
interface BumpFileReleaseSimple {
|
|
94
99
|
name: string;
|
|
95
|
-
type:
|
|
100
|
+
type: BumpTypeWithNone;
|
|
96
101
|
}
|
|
97
|
-
interface
|
|
102
|
+
interface BumpFileReleaseCascade {
|
|
98
103
|
name: string;
|
|
99
|
-
type:
|
|
104
|
+
type: BumpTypeWithNone;
|
|
100
105
|
cascade: Record<string, BumpType>;
|
|
101
106
|
}
|
|
102
|
-
type
|
|
103
|
-
declare function hasCascade(r:
|
|
104
|
-
interface
|
|
107
|
+
type BumpFileRelease = BumpFileReleaseSimple | BumpFileReleaseCascade;
|
|
108
|
+
declare function hasCascade(r: BumpFileRelease): r is BumpFileReleaseCascade;
|
|
109
|
+
interface BumpFile {
|
|
105
110
|
id: string;
|
|
106
|
-
releases:
|
|
111
|
+
releases: BumpFileRelease[];
|
|
107
112
|
summary: string;
|
|
108
113
|
}
|
|
109
114
|
interface WorkspacePackage {
|
|
@@ -131,13 +136,14 @@ interface PlannedRelease {
|
|
|
131
136
|
type: BumpType;
|
|
132
137
|
oldVersion: string;
|
|
133
138
|
newVersion: string;
|
|
134
|
-
|
|
139
|
+
bumpFiles: string[];
|
|
135
140
|
isDependencyBump: boolean;
|
|
136
141
|
isCascadeBump: boolean;
|
|
137
142
|
}
|
|
138
143
|
interface ReleasePlan {
|
|
139
|
-
|
|
144
|
+
bumpFiles: BumpFile[];
|
|
140
145
|
releases: PlannedRelease[];
|
|
146
|
+
warnings: string[];
|
|
141
147
|
}
|
|
142
148
|
//#endregion
|
|
143
149
|
//#region src/core/config.d.ts
|
|
@@ -175,30 +181,35 @@ declare class DependencyGraph {
|
|
|
175
181
|
topologicalSort(packages: Map<string, WorkspacePackage>): string[];
|
|
176
182
|
}
|
|
177
183
|
//#endregion
|
|
178
|
-
//#region src/core/
|
|
179
|
-
/** Read all
|
|
180
|
-
declare function
|
|
181
|
-
/** Parse
|
|
182
|
-
declare function
|
|
183
|
-
/** Write a
|
|
184
|
-
declare function
|
|
184
|
+
//#region src/core/bump-file.d.ts
|
|
185
|
+
/** Read all bump files from .bumpy/ directory, sorted by git creation order */
|
|
186
|
+
declare function readBumpFiles(rootDir: string): Promise<BumpFile[]>;
|
|
187
|
+
/** Parse bump file content (for testing) */
|
|
188
|
+
declare function parseBumpFile(content: string, id: string): BumpFile | null;
|
|
189
|
+
/** Write a bump file */
|
|
190
|
+
declare function writeBumpFile(rootDir: string, filename: string, releases: BumpFileRelease[], summary: string): Promise<string>;
|
|
185
191
|
//#endregion
|
|
186
192
|
//#region src/core/release-plan.d.ts
|
|
187
193
|
/**
|
|
188
|
-
* Build a release plan from pending
|
|
194
|
+
* Build a release plan from pending bump files, the dependency graph, and config.
|
|
189
195
|
* This is the core algorithm of bumpy.
|
|
196
|
+
*
|
|
197
|
+
* The propagation loop runs three phases until stable:
|
|
198
|
+
* Phase A — fix out-of-range dependencies (always runs)
|
|
199
|
+
* Phase B — enforce fixed/linked group constraints
|
|
200
|
+
* Phase C — apply cascades and proactive propagation rules
|
|
190
201
|
*/
|
|
191
|
-
declare function assembleReleasePlan(
|
|
202
|
+
declare function assembleReleasePlan(bumpFiles: BumpFile[], packages: Map<string, WorkspacePackage>, depGraph: DependencyGraph, config: BumpyConfig): ReleasePlan;
|
|
192
203
|
//#endregion
|
|
193
204
|
//#region src/core/apply-release-plan.d.ts
|
|
194
|
-
/** Apply the release plan: bump versions, update changelogs, delete
|
|
205
|
+
/** Apply the release plan: bump versions, update changelogs, delete bump files */
|
|
195
206
|
declare function applyReleasePlan(releasePlan: ReleasePlan, packages: Map<string, WorkspacePackage>, rootDir: string, config: BumpyConfig): Promise<void>;
|
|
196
207
|
//#endregion
|
|
197
208
|
//#region src/core/changelog.d.ts
|
|
198
209
|
interface ChangelogContext {
|
|
199
210
|
release: PlannedRelease;
|
|
200
|
-
/**
|
|
201
|
-
|
|
211
|
+
/** Bump files that contributed to this release */
|
|
212
|
+
bumpFiles: BumpFile[];
|
|
202
213
|
/** ISO date string (YYYY-MM-DD) */
|
|
203
214
|
date: string;
|
|
204
215
|
}
|
|
@@ -215,7 +226,7 @@ declare const defaultFormatter: ChangelogFormatter;
|
|
|
215
226
|
*/
|
|
216
227
|
declare function loadFormatter(changelog: BumpyConfig['changelog'], rootDir: string): Promise<ChangelogFormatter>;
|
|
217
228
|
/** Generate a changelog entry using the configured formatter */
|
|
218
|
-
declare function generateChangelogEntry(release: PlannedRelease,
|
|
229
|
+
declare function generateChangelogEntry(release: PlannedRelease, bumpFiles: BumpFile[], formatter?: ChangelogFormatter, date?: string): Promise<string>;
|
|
219
230
|
/** Prepend a new entry to an existing CHANGELOG.md content */
|
|
220
231
|
declare function prependToChangelog(existingContent: string, newEntry: string): string;
|
|
221
232
|
//#endregion
|
|
@@ -223,14 +234,21 @@ declare function prependToChangelog(existingContent: string, newEntry: string):
|
|
|
223
234
|
interface GithubChangelogOptions {
|
|
224
235
|
/** "owner/repo" — auto-detected from gh CLI if not provided */
|
|
225
236
|
repo?: string;
|
|
237
|
+
/** Whether to include "Thanks @user" messages for contributors (default: true) */
|
|
238
|
+
thankContributors?: boolean;
|
|
226
239
|
/** GitHub usernames (without @) to skip "Thanks" messages for (e.g. internal team members) */
|
|
227
240
|
internalAuthors?: string[];
|
|
228
241
|
}
|
|
229
242
|
//#endregion
|
|
230
243
|
//#region src/core/semver.d.ts
|
|
231
244
|
declare function bumpVersion(version: string, type: BumpType): string;
|
|
232
|
-
/**
|
|
233
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Check if a version satisfies a range.
|
|
247
|
+
* @param version - The version to check
|
|
248
|
+
* @param range - The version range (may include workspace: or catalog: protocol)
|
|
249
|
+
* @param currentVersion - The dependency's current version, used to resolve workspace:^ and workspace:~
|
|
250
|
+
*/
|
|
251
|
+
declare function satisfies(version: string, range: string, currentVersion?: string): boolean;
|
|
234
252
|
/** Strip workspace: protocol from version ranges */
|
|
235
253
|
declare function stripProtocol(range: string): string;
|
|
236
254
|
//#endregion
|
|
@@ -259,4 +277,4 @@ interface PublishResult {
|
|
|
259
277
|
*/
|
|
260
278
|
declare function publishPackages(releasePlan: ReleasePlan, packages: Map<string, WorkspacePackage>, depGraph: DependencyGraph, config: BumpyConfig, rootDir: string, opts?: PublishOptions, catalogs?: CatalogMap, detectedPm?: PackageManager): Promise<PublishResult>;
|
|
261
279
|
//#endregion
|
|
262
|
-
export { BUMP_LEVELS, BumpType,
|
|
280
|
+
export { BUMP_LEVELS, BumpFile, BumpFileRelease, BumpFileReleaseCascade, BumpFileReleaseSimple, BumpType, BumpTypeWithNone, BumpyConfig, type ChangelogContext, type ChangelogFormatter, DEFAULT_BUMP_RULES, DEFAULT_CONFIG, DEFAULT_PUBLISH_CONFIG, DEP_TYPES, DepType, DependencyBumpRule, DependencyGraph, DependentInfo, type GithubChangelogOptions, PackageConfig, PackageManager, PlannedRelease, PublishConfig, ReleasePlan, WorkspacePackage, applyReleasePlan, assembleReleasePlan, bumpLevel, bumpVersion, defaultFormatter, discoverPackages, findRoot, generateChangelogEntry, getBumpyDir, hasCascade, loadConfig, loadFormatter, matchGlob, maxBump, parseBumpFile, prependToChangelog, publishPackages, readBumpFiles, satisfies, stripProtocol, writeBumpFile };
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as loadConfig, c as BUMP_LEVELS, d as DEFAULT_PUBLISH_CONFIG, f as DEP_TYPES,
|
|
2
|
-
import { t as discoverPackages } from "./workspace-
|
|
1
|
+
import { a as loadConfig, c as BUMP_LEVELS, d as DEFAULT_PUBLISH_CONFIG, f as DEP_TYPES, h as maxBump, l as DEFAULT_BUMP_RULES, m as hasCascade, n as findRoot, p as bumpLevel, r as getBumpyDir, s as matchGlob, u as DEFAULT_CONFIG } from "./config-XZWUL3ma.mjs";
|
|
2
|
+
import { t as discoverPackages } from "./workspace-C5ULTyUN.mjs";
|
|
3
3
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
4
|
-
import { i as
|
|
5
|
-
import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-
|
|
6
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
7
|
-
import { a as prependToChangelog, i as loadFormatter, n as defaultFormatter, r as generateChangelogEntry, t as applyReleasePlan } from "./apply-release-plan-
|
|
8
|
-
import { t as publishPackages } from "./publish-pipeline-
|
|
9
|
-
export { BUMP_LEVELS, DEFAULT_BUMP_RULES, DEFAULT_CONFIG, DEFAULT_PUBLISH_CONFIG, DEP_TYPES, DependencyGraph, applyReleasePlan, assembleReleasePlan, bumpLevel, bumpVersion, defaultFormatter, discoverPackages, findRoot, generateChangelogEntry, getBumpyDir, hasCascade, loadConfig, loadFormatter, matchGlob, maxBump,
|
|
4
|
+
import { i as writeBumpFile, n as parseBumpFile, r as readBumpFiles } from "./bump-file-CCLXMLA8.mjs";
|
|
5
|
+
import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-DfQyVLM_.mjs";
|
|
6
|
+
import { t as assembleReleasePlan } from "./release-plan-Bi5QNSEo.mjs";
|
|
7
|
+
import { a as prependToChangelog, i as loadFormatter, n as defaultFormatter, r as generateChangelogEntry, t as applyReleasePlan } from "./apply-release-plan-CczGWJTk.mjs";
|
|
8
|
+
import { t as publishPackages } from "./publish-pipeline-BwBuKCIk.mjs";
|
|
9
|
+
export { BUMP_LEVELS, DEFAULT_BUMP_RULES, DEFAULT_CONFIG, DEFAULT_PUBLISH_CONFIG, DEP_TYPES, DependencyGraph, applyReleasePlan, assembleReleasePlan, bumpLevel, bumpVersion, defaultFormatter, discoverPackages, findRoot, generateChangelogEntry, getBumpyDir, hasCascade, loadConfig, loadFormatter, matchGlob, maxBump, parseBumpFile, prependToChangelog, publishPackages, readBumpFiles, satisfies, stripProtocol, writeBumpFile };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as log } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { d as writeText, n as exists, t as ensureDir, u as writeJson } from "./fs-DYR2XuFE.mjs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
//#region src/commands/init.ts
|
|
5
5
|
async function initCommand(rootDir) {
|
|
@@ -13,7 +13,7 @@ async function initCommand(rootDir) {
|
|
|
13
13
|
baseBranch: "main",
|
|
14
14
|
changelog: "default"
|
|
15
15
|
});
|
|
16
|
-
await writeText(resolve(bumpyDir, "README.md"), `# 🐸 Bumpy\n\nThis directory is used by [bumpy](https://github.com/dmno-dev/bumpy) to manage versioning.\n\
|
|
16
|
+
await writeText(resolve(bumpyDir, "README.md"), `# 🐸 Bumpy\n\nThis directory is used by [bumpy](https://github.com/dmno-dev/bumpy) to manage versioning.\n\nBump files (\`.md\`) in this directory describe pending version bumps.\nRun \`bumpy add\` to create a new bump file.\n`);
|
|
17
17
|
log.success("Initialized .bumpy/ directory");
|
|
18
18
|
log.dim(" Created .bumpy/_config.json");
|
|
19
19
|
log.dim(" Created .bumpy/README.md");
|