@varlock/bumpy 0.0.1 → 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-B8ZL2x8z.mjs → ai-sMYUf3lP.mjs} +22 -5
- package/dist/{apply-release-plan-DtU3rVyL.mjs → apply-release-plan-CczGWJTk.mjs} +34 -25
- package/dist/bump-file-CCLXMLA8.mjs +143 -0
- package/dist/changelog-github-Cd8uJHZI.mjs +195 -0
- package/dist/{check-CkRubvuk.mjs → check-BOoxpWqk.mjs} +11 -17
- package/dist/ci-Bhx--Tj6.mjs +629 -0
- package/dist/ci-setup-qz4Y3v7T.mjs +211 -0
- package/dist/clack-CDRCHrC-.mjs +1216 -0
- package/dist/cli.mjs +37 -31
- package/dist/{config-CJ2orhTL.mjs → config-XZWUL3ma.mjs} +28 -23
- package/dist/fs-DYR2XuFE.mjs +81 -0
- package/dist/{generate-oOFD9ABC.mjs → generate-gYKTpvex.mjs} +31 -12
- package/dist/git-CGHVXXKw.mjs +78 -0
- package/dist/index.d.mts +63 -37
- package/dist/index.mjs +9 -9
- package/dist/{init-Blw2GfC_.mjs → init-lA9E5pEc.mjs} +3 -3
- package/dist/logger-C2dEe5Su.mjs +135 -0
- package/dist/{migrate-DvOrXSw0.mjs → migrate-DmOYgmfD.mjs} +23 -16
- package/dist/{names-C-u50ofE.mjs → names-9VubBmL0.mjs} +3 -2
- package/dist/package-manager-VCe10bjc.mjs +80 -0
- package/dist/{publish-DZ3m7qkX.mjs → publish-Cun-zQ1b.mjs} +90 -35
- package/dist/{publish-pipeline-1M5GmbdP.mjs → publish-pipeline-BwBuKCIk.mjs} +56 -65
- package/dist/release-plan-Bi5QNSEo.mjs +264 -0
- package/dist/{semver-DWO6NFKN.mjs → semver-DfQyVLM_.mjs} +14 -4
- package/dist/shell-Dj7JRD_q.mjs +92 -0
- package/dist/{status-DRpq_Mha.mjs → status-CfE63ti5.mjs} +27 -23
- package/dist/version-19vVt9dv.mjs +124 -0
- package/dist/workspace-C5ULTyUN.mjs +107 -0
- package/package.json +16 -2
- package/skills/add-change/SKILL.md +8 -12
- package/dist/add-u5V9V3L7.mjs +0 -131
- package/dist/changelog-github-n-3zV1p9.mjs +0 -59
- package/dist/changeset-ClCYsChu.mjs +0 -75
- package/dist/ci-8KWWhjXl.mjs +0 -224
- package/dist/fs-DbNNEyzq.mjs +0 -51
- package/dist/logger-ZqggsyGZ.mjs +0 -176
- package/dist/prompt-BP8toAOI.mjs +0 -46
- package/dist/release-plan-CFnutSHD.mjs +0 -173
- package/dist/shell-DPlltpzb.mjs +0 -44
- package/dist/version-CJwf8XIA.mjs +0 -81
- package/dist/workspace-mVjawG8g.mjs +0 -183
- /package/dist/{dep-graph-DiLeAhl9.mjs → dep-graph-E-9-eQ2J.mjs} +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as log, t as colorize } from "./logger-
|
|
3
|
-
import { n as findRoot } from "./config-
|
|
2
|
+
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
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,27 +85,32 @@ 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
|
});
|
|
102
|
+
} else if (subcommand === "setup") {
|
|
103
|
+
const { ciSetupCommand } = await import("./ci-setup-qz4Y3v7T.mjs");
|
|
104
|
+
await ciSetupCommand(rootDir);
|
|
100
105
|
} else {
|
|
101
|
-
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check" or "ci
|
|
106
|
+
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
|
|
102
107
|
process.exit(1);
|
|
103
108
|
}
|
|
104
109
|
break;
|
|
105
110
|
}
|
|
106
111
|
case "publish": {
|
|
107
112
|
const rootDir = await findRoot();
|
|
108
|
-
const { publishCommand } = await import("./publish-
|
|
113
|
+
const { publishCommand } = await import("./publish-Cun-zQ1b.mjs");
|
|
109
114
|
await publishCommand(rootDir, {
|
|
110
115
|
dryRun: flags["dry-run"] === true,
|
|
111
116
|
tag: flags.tag,
|
|
@@ -119,7 +124,7 @@ async function main() {
|
|
|
119
124
|
const subcommand = args[1];
|
|
120
125
|
const aiFlags = parseFlags(args.slice(2));
|
|
121
126
|
if (subcommand === "setup") {
|
|
122
|
-
const { aiSetupCommand } = await import("./ai-
|
|
127
|
+
const { aiSetupCommand } = await import("./ai-sMYUf3lP.mjs");
|
|
123
128
|
await aiSetupCommand(rootDir, { target: aiFlags.target });
|
|
124
129
|
} else {
|
|
125
130
|
log.error(`Unknown ai subcommand: ${subcommand}. Use "ai setup".`);
|
|
@@ -129,7 +134,7 @@ async function main() {
|
|
|
129
134
|
}
|
|
130
135
|
case "--version":
|
|
131
136
|
case "-v":
|
|
132
|
-
console.log(`bumpy 0.0
|
|
137
|
+
console.log(`bumpy 1.0.0`);
|
|
133
138
|
break;
|
|
134
139
|
case "help":
|
|
135
140
|
case "--help":
|
|
@@ -149,40 +154,41 @@ async function main() {
|
|
|
149
154
|
}
|
|
150
155
|
function printHelp() {
|
|
151
156
|
console.log(`
|
|
152
|
-
${colorize(`🐸 bumpy
|
|
157
|
+
${colorize(`🐸 bumpy v1.0.0`, "bold")} - Modern monorepo versioning
|
|
153
158
|
|
|
154
159
|
Usage: bumpy <command> [options]
|
|
155
160
|
|
|
156
161
|
Commands:
|
|
157
162
|
init Initialize .bumpy/ directory
|
|
158
|
-
add Create a new
|
|
159
|
-
generate Generate
|
|
163
|
+
add Create a new bump file
|
|
164
|
+
generate Generate bump file from conventional commits
|
|
160
165
|
status Show pending releases
|
|
161
|
-
check Verify changed packages have
|
|
162
|
-
version Apply
|
|
166
|
+
check Verify changed packages have bump files (for pre-push hooks)
|
|
167
|
+
version Apply bump files and bump versions
|
|
163
168
|
publish Publish versioned packages
|
|
164
169
|
ci check PR check — report pending releases, comment on PR
|
|
165
170
|
ci release Release — create version PR or auto-publish
|
|
171
|
+
ci setup Set up a token for triggering CI on version PRs
|
|
166
172
|
migrate Migrate from .changeset/ to .bumpy/
|
|
167
|
-
ai setup Install AI skill for creating
|
|
173
|
+
ai setup Install AI skill for creating bump files
|
|
168
174
|
|
|
169
175
|
Add options:
|
|
170
176
|
--packages <list> Package bumps (e.g., "pkg-a:minor,pkg-b:patch")
|
|
171
|
-
--message <text>
|
|
172
|
-
--name <name>
|
|
173
|
-
--empty Create an empty
|
|
177
|
+
--message <text> Bump file summary
|
|
178
|
+
--name <name> Bump file filename
|
|
179
|
+
--empty Create an empty bump file
|
|
174
180
|
|
|
175
181
|
Generate options:
|
|
176
182
|
--from <ref> Git ref to scan from (default: last version tag)
|
|
177
|
-
--dry-run Preview without creating a
|
|
178
|
-
--name <name>
|
|
183
|
+
--dry-run Preview without creating a bump file
|
|
184
|
+
--name <name> Bump file filename
|
|
179
185
|
|
|
180
186
|
Status options:
|
|
181
|
-
--json Output as JSON (includes dirs,
|
|
187
|
+
--json Output as JSON (includes dirs, bumpFiles, packageNames)
|
|
182
188
|
--packages Output only package names, one per line
|
|
183
189
|
--bump <types> Filter by bump type (e.g., "major", "minor,patch")
|
|
184
190
|
--filter <names> Filter by package name/glob (e.g., "@myorg/*")
|
|
185
|
-
--verbose Show
|
|
191
|
+
--verbose Show bump file details
|
|
186
192
|
|
|
187
193
|
Publish options:
|
|
188
194
|
--dry-run Preview without publishing
|
|
@@ -192,7 +198,7 @@ function printHelp() {
|
|
|
192
198
|
|
|
193
199
|
CI check options:
|
|
194
200
|
--comment Force PR comment on/off (auto-detected in CI)
|
|
195
|
-
--fail-on-missing Exit 1 if no
|
|
201
|
+
--fail-on-missing Exit 1 if no bump files found
|
|
196
202
|
|
|
197
203
|
CI release options:
|
|
198
204
|
--auto-publish Version + publish directly (default: create version PR)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as readJson, n as exists } from "./fs-
|
|
1
|
+
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
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
|
-
import { n as log, t as colorize } from "./logger-
|
|
2
|
-
import { t as ensureDir } from "./fs-
|
|
3
|
-
import { a as loadConfig, r as getBumpyDir } from "./config-
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
5
|
-
import {
|
|
6
|
-
import { i as
|
|
7
|
-
import { n as slugify, t as randomName } from "./names-
|
|
1
|
+
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
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
|
+
import { o as tryRunArgs } from "./shell-Dj7JRD_q.mjs";
|
|
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",
|
|
@@ -27,7 +27,12 @@ async function generateCommand(rootDir, opts) {
|
|
|
27
27
|
process.exit(1);
|
|
28
28
|
}
|
|
29
29
|
log.step(`Scanning commits from ${colorize(from, "cyan")}...`);
|
|
30
|
-
const rawLog =
|
|
30
|
+
const rawLog = tryRunArgs([
|
|
31
|
+
"git",
|
|
32
|
+
"log",
|
|
33
|
+
`${from}..HEAD`,
|
|
34
|
+
"--format=%H%n%s%n%b%n---END---"
|
|
35
|
+
], { cwd: rootDir });
|
|
31
36
|
if (!rawLog) {
|
|
32
37
|
log.info("No commits found since " + from);
|
|
33
38
|
return;
|
|
@@ -79,7 +84,7 @@ async function generateCommand(rootDir, opts) {
|
|
|
79
84
|
for (const msg of info.messages) summaryLines.push(`- ${name}: ${msg}`);
|
|
80
85
|
}
|
|
81
86
|
if (opts.dryRun) {
|
|
82
|
-
log.bold("Would create
|
|
87
|
+
log.bold("Would create bump file:");
|
|
83
88
|
for (const r of releases) console.log(` ${r.name}: ${colorize(r.type, r.type === "major" ? "red" : r.type === "minor" ? "yellow" : "green")}`);
|
|
84
89
|
console.log();
|
|
85
90
|
log.dim("Summary:");
|
|
@@ -88,8 +93,8 @@ async function generateCommand(rootDir, opts) {
|
|
|
88
93
|
}
|
|
89
94
|
await ensureDir(getBumpyDir(rootDir));
|
|
90
95
|
const filename = opts.name ? slugify(opts.name) : randomName();
|
|
91
|
-
await
|
|
92
|
-
log.success(`Created
|
|
96
|
+
await writeBumpFile(rootDir, filename, releases, summaryLines.join("\n"));
|
|
97
|
+
log.success(`Created bump file: .bumpy/${filename}.md`);
|
|
93
98
|
for (const r of releases) log.dim(` ${r.name}: ${r.type}`);
|
|
94
99
|
}
|
|
95
100
|
/** Parse raw git log output into individual commits */
|
|
@@ -152,7 +157,21 @@ function bumpPriority(type) {
|
|
|
152
157
|
}
|
|
153
158
|
/** Find the most recent version tag in the repo */
|
|
154
159
|
function findLastVersionTag(rootDir) {
|
|
155
|
-
return
|
|
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;
|
|
156
175
|
}
|
|
157
176
|
//#endregion
|
|
158
177
|
export { generateCommand };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { o as tryRunArgs, t as runArgs } from "./shell-Dj7JRD_q.mjs";
|
|
2
|
+
//#region src/core/git.ts
|
|
3
|
+
/** Create a git tag */
|
|
4
|
+
function createTag(tag, opts) {
|
|
5
|
+
runArgs([
|
|
6
|
+
"git",
|
|
7
|
+
"tag",
|
|
8
|
+
tag
|
|
9
|
+
], opts);
|
|
10
|
+
}
|
|
11
|
+
/** Push commits and tags to remote */
|
|
12
|
+
function pushWithTags(opts) {
|
|
13
|
+
runArgs(["git", "push"], opts);
|
|
14
|
+
runArgs([
|
|
15
|
+
"git",
|
|
16
|
+
"push",
|
|
17
|
+
"--tags"
|
|
18
|
+
], opts);
|
|
19
|
+
}
|
|
20
|
+
/** Check if there are uncommitted changes */
|
|
21
|
+
function hasUncommittedChanges(opts) {
|
|
22
|
+
const result = tryRunArgs([
|
|
23
|
+
"git",
|
|
24
|
+
"status",
|
|
25
|
+
"--porcelain"
|
|
26
|
+
], opts);
|
|
27
|
+
return result !== null && result.length > 0;
|
|
28
|
+
}
|
|
29
|
+
/** Check if a tag already exists */
|
|
30
|
+
function tagExists(tag, opts) {
|
|
31
|
+
return tryRunArgs([
|
|
32
|
+
"git",
|
|
33
|
+
"tag",
|
|
34
|
+
"-l",
|
|
35
|
+
tag
|
|
36
|
+
], opts) === tag;
|
|
37
|
+
}
|
|
38
|
+
/** Get files changed on this branch compared to a base branch */
|
|
39
|
+
function getChangedFiles(rootDir, baseBranch) {
|
|
40
|
+
if (!tryRunArgs([
|
|
41
|
+
"git",
|
|
42
|
+
"rev-parse",
|
|
43
|
+
"--verify",
|
|
44
|
+
`origin/${baseBranch}`
|
|
45
|
+
], { cwd: rootDir })) tryRunArgs([
|
|
46
|
+
"git",
|
|
47
|
+
"fetch",
|
|
48
|
+
"origin",
|
|
49
|
+
baseBranch,
|
|
50
|
+
"--depth=1"
|
|
51
|
+
], { cwd: rootDir });
|
|
52
|
+
const diff = tryRunArgs([
|
|
53
|
+
"git",
|
|
54
|
+
"diff",
|
|
55
|
+
"--name-only",
|
|
56
|
+
tryRunArgs([
|
|
57
|
+
"git",
|
|
58
|
+
"merge-base",
|
|
59
|
+
"HEAD",
|
|
60
|
+
`origin/${baseBranch}`
|
|
61
|
+
], { cwd: rootDir }) || `origin/${baseBranch}`
|
|
62
|
+
], { cwd: rootDir });
|
|
63
|
+
if (!diff) return [];
|
|
64
|
+
return diff.split("\n").filter(Boolean);
|
|
65
|
+
}
|
|
66
|
+
/** Get all tags matching a pattern */
|
|
67
|
+
function listTags(pattern, opts) {
|
|
68
|
+
const result = tryRunArgs([
|
|
69
|
+
"git",
|
|
70
|
+
"tag",
|
|
71
|
+
"-l",
|
|
72
|
+
pattern
|
|
73
|
+
], opts);
|
|
74
|
+
if (!result) return [];
|
|
75
|
+
return result.split("\n").filter(Boolean);
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { pushWithTags as a, listTags as i, getChangedFiles as n, tagExists as o, hasUncommittedChanges as r, createTag as t };
|