@varlock/bumpy 1.2.2 → 1.4.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/README.md +4 -5
- package/dist/{add-DEqGa5gI.mjs → add-D1uiW7VA.mjs} +24 -5
- package/dist/{apply-release-plan-Bi9OSWks.mjs → apply-release-plan-60VfCLF8.mjs} +2 -2
- package/dist/{bump-file-BTsntOO-.mjs → bump-file-CoaSxqne.mjs} +1 -1
- package/dist/{changelog-xKuL0IKx.mjs → changelog-DP3OrTqQ.mjs} +7 -6
- package/dist/{changelog-github-CEaDCtTk.mjs → changelog-github-Da5KekQd.mjs} +1 -1
- package/dist/{picomatch-TGJi--_I.mjs → check-CS8WIGZA.mjs} +131 -2
- package/dist/{ci-BVTwTUUK.mjs → ci-CnIkaf7Q.mjs} +40 -41
- package/dist/cli.mjs +29 -21
- package/dist/{config-CJIj8xG3.mjs → config-D13G4-R8.mjs} +1 -1
- package/dist/{generate-wHN6Ll6p.mjs → generate-D0KJsvpD.mjs} +4 -4
- package/dist/{git-D0__HP86.mjs → git-ukq7VTuZ.mjs} +21 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +8 -8
- package/dist/{publish-BwidFqbo.mjs → publish-DWdN3o9u.mjs} +45 -9
- package/dist/{publish-pipeline-BvLIu7WF.mjs → publish-pipeline-C1slMaJV.mjs} +1 -1
- package/dist/{release-plan-21H89Cx1.mjs → release-plan-pyxf71dx.mjs} +6 -56
- package/dist/{status-CDGxgXWd.mjs → status-DyzcQ6CD.mjs} +6 -6
- package/dist/{types-CSM0c2-m.mjs → types-BX4pfmKh.mjs} +1 -1
- package/dist/{version-ClkaCNTE.mjs → version-BxDhayli.mjs} +6 -6
- package/dist/{workspace-c9-TqXed.mjs → workspace-BKOAMeki.mjs} +1 -1
- package/package.json +1 -1
- package/skills/add-change/SKILL.md +1 -1
- package/dist/check-D3eXRyKJ.mjs +0 -92
- /package/dist/{ci-setup-D1NCzbNH.mjs → ci-setup-DWxrdSK6.mjs} +0 -0
- /package/dist/{commit-message-DOIfDxfj.mjs → commit-message-3e4KhzFV.mjs} +0 -0
- /package/dist/{init-DND7zRGD.mjs → init-CUIw0jg8.mjs} +0 -0
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-D13G4-R8.mjs";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
const args = process.argv.slice(2);
|
|
6
6
|
const command = args[0];
|
|
@@ -25,24 +25,25 @@ 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-CUIw0jg8.mjs");
|
|
29
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-D1uiW7VA.mjs");
|
|
35
35
|
await addCommand(rootDir, {
|
|
36
36
|
packages: flags.packages,
|
|
37
37
|
message: flags.message,
|
|
38
38
|
name: flags.name,
|
|
39
|
-
empty: flags.empty === true
|
|
39
|
+
empty: flags.empty === true,
|
|
40
|
+
none: flags.none === true
|
|
40
41
|
});
|
|
41
42
|
break;
|
|
42
43
|
}
|
|
43
44
|
case "status": {
|
|
44
45
|
const rootDir = await findRoot();
|
|
45
|
-
const { statusCommand } = await import("./status-
|
|
46
|
+
const { statusCommand } = await import("./status-DyzcQ6CD.mjs");
|
|
46
47
|
await statusCommand(rootDir, {
|
|
47
48
|
json: flags.json === true,
|
|
48
49
|
packagesOnly: flags.packages === true,
|
|
@@ -54,13 +55,13 @@ async function main() {
|
|
|
54
55
|
}
|
|
55
56
|
case "version": {
|
|
56
57
|
const rootDir = await findRoot();
|
|
57
|
-
const { versionCommand } = await import("./version-
|
|
58
|
+
const { versionCommand } = await import("./version-BxDhayli.mjs");
|
|
58
59
|
await versionCommand(rootDir, { commit: flags.commit === true });
|
|
59
60
|
break;
|
|
60
61
|
}
|
|
61
62
|
case "generate": {
|
|
62
63
|
const rootDir = await findRoot();
|
|
63
|
-
const { generateCommand } = await import("./generate-
|
|
64
|
+
const { generateCommand } = await import("./generate-D0KJsvpD.mjs");
|
|
64
65
|
await generateCommand(rootDir, {
|
|
65
66
|
from: flags.from,
|
|
66
67
|
dryRun: flags["dry-run"] === true,
|
|
@@ -70,10 +71,16 @@ async function main() {
|
|
|
70
71
|
}
|
|
71
72
|
case "check": {
|
|
72
73
|
const rootDir = await findRoot();
|
|
73
|
-
const { checkCommand } = await import("./check-
|
|
74
|
+
const { checkCommand } = await import("./check-CS8WIGZA.mjs");
|
|
75
|
+
const hookValue = flags.hook;
|
|
76
|
+
if (hookValue && hookValue !== "pre-commit" && hookValue !== "pre-push") {
|
|
77
|
+
log.error(`Invalid --hook value "${hookValue}". Expected "pre-commit" or "pre-push".`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
74
80
|
await checkCommand(rootDir, {
|
|
75
81
|
strict: flags.strict === true,
|
|
76
|
-
noFail: flags["no-fail"] === true
|
|
82
|
+
noFail: flags["no-fail"] === true,
|
|
83
|
+
hook: hookValue
|
|
77
84
|
});
|
|
78
85
|
break;
|
|
79
86
|
}
|
|
@@ -82,23 +89,21 @@ async function main() {
|
|
|
82
89
|
const subcommand = args[1];
|
|
83
90
|
const ciFlags = parseFlags(args.slice(2));
|
|
84
91
|
if (subcommand === "check") {
|
|
85
|
-
const { ciCheckCommand } = await import("./ci-
|
|
92
|
+
const { ciCheckCommand } = await import("./ci-CnIkaf7Q.mjs");
|
|
86
93
|
await ciCheckCommand(rootDir, {
|
|
87
94
|
comment: ciFlags.comment !== void 0 ? ciFlags.comment === true : void 0,
|
|
88
95
|
strict: ciFlags.strict === true,
|
|
89
|
-
noFail: ciFlags["no-fail"] === true
|
|
90
|
-
patComments: ciFlags["pat-comments"] === true
|
|
96
|
+
noFail: ciFlags["no-fail"] === true
|
|
91
97
|
});
|
|
92
98
|
} else if (subcommand === "release") {
|
|
93
|
-
const { ciReleaseCommand } = await import("./ci-
|
|
99
|
+
const { ciReleaseCommand } = await import("./ci-CnIkaf7Q.mjs");
|
|
94
100
|
await ciReleaseCommand(rootDir, {
|
|
95
101
|
mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
|
|
96
102
|
tag: ciFlags.tag,
|
|
97
|
-
branch: ciFlags.branch
|
|
98
|
-
patPr: ciFlags["pat-pr"] === true
|
|
103
|
+
branch: ciFlags.branch
|
|
99
104
|
});
|
|
100
105
|
} else if (subcommand === "setup") {
|
|
101
|
-
const { ciSetupCommand } = await import("./ci-setup-
|
|
106
|
+
const { ciSetupCommand } = await import("./ci-setup-DWxrdSK6.mjs");
|
|
102
107
|
await ciSetupCommand(rootDir);
|
|
103
108
|
} else {
|
|
104
109
|
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
|
|
@@ -108,7 +113,7 @@ async function main() {
|
|
|
108
113
|
}
|
|
109
114
|
case "publish": {
|
|
110
115
|
const rootDir = await findRoot();
|
|
111
|
-
const { publishCommand } = await import("./publish-
|
|
116
|
+
const { publishCommand } = await import("./publish-DWdN3o9u.mjs");
|
|
112
117
|
await publishCommand(rootDir, {
|
|
113
118
|
dryRun: flags["dry-run"] === true,
|
|
114
119
|
tag: flags.tag,
|
|
@@ -132,7 +137,7 @@ async function main() {
|
|
|
132
137
|
}
|
|
133
138
|
case "--version":
|
|
134
139
|
case "-v":
|
|
135
|
-
console.log(`bumpy 1.
|
|
140
|
+
console.log(`bumpy 1.4.0`);
|
|
136
141
|
break;
|
|
137
142
|
case "help":
|
|
138
143
|
case "--help":
|
|
@@ -152,18 +157,21 @@ async function main() {
|
|
|
152
157
|
}
|
|
153
158
|
function printHelp() {
|
|
154
159
|
console.log(`
|
|
155
|
-
${colorize(`🐸 bumpy v1.
|
|
160
|
+
${colorize(`🐸 bumpy v1.4.0`, "bold")} - Modern monorepo versioning
|
|
156
161
|
|
|
157
162
|
Usage: bumpy <command> [options]
|
|
158
163
|
|
|
159
164
|
Commands:
|
|
160
165
|
init [--force] Initialize .bumpy/ (migrates from .changeset/ if found)
|
|
161
166
|
add Create a new bump file
|
|
167
|
+
--none Set all changed packages to "none" (acknowledge without bumping)
|
|
168
|
+
--empty Create an empty bump file (no releases needed)
|
|
162
169
|
generate Generate bump file from branch commits
|
|
163
170
|
status Show pending releases
|
|
164
|
-
check Verify changed packages have bump files (for
|
|
171
|
+
check Verify changed packages have bump files (for git hooks)
|
|
165
172
|
--strict Fail if any changed package is uncovered (default: only fail if no bump files at all)
|
|
166
173
|
--no-fail Warn only, never exit 1
|
|
174
|
+
--hook <context> Hook context: "pre-commit" or "pre-push" (controls which bump files count)
|
|
167
175
|
version [--commit] Apply bump files and bump versions
|
|
168
176
|
publish Publish versioned packages
|
|
169
177
|
ci check PR check — report pending releases, comment on PR
|
|
@@ -206,7 +214,7 @@ function printHelp() {
|
|
|
206
214
|
--branch <name> Branch name for version PR (default: bumpy/version-packages)
|
|
207
215
|
|
|
208
216
|
AI setup options:
|
|
209
|
-
--target <tool> Target AI tool: opencode, cursor, codex
|
|
217
|
+
--target <tool> Target AI tool: claude, opencode, cursor, codex
|
|
210
218
|
|
|
211
219
|
${colorize("https://bumpy.varlock.dev", "dim")}
|
|
212
220
|
`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
2
2
|
import { a as readJson, n as exists, o as readJsonc } from "./fs-DnDogVn-.mjs";
|
|
3
|
-
import { r as DEFAULT_CONFIG } from "./types-
|
|
3
|
+
import { r as DEFAULT_CONFIG } from "./types-BX4pfmKh.mjs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
//#region src/core/config.ts
|
|
6
6
|
var config_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
2
|
import { t as ensureDir } from "./fs-DnDogVn-.mjs";
|
|
3
|
-
import { a as loadConfig, r as getBumpyDir } from "./config-
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
3
|
+
import { a as loadConfig, r as getBumpyDir } from "./config-D13G4-R8.mjs";
|
|
4
|
+
import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
5
5
|
import { s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
|
|
6
|
-
import { i as writeBumpFile } from "./bump-file-
|
|
7
|
-
import {
|
|
6
|
+
import { i as writeBumpFile } from "./bump-file-CoaSxqne.mjs";
|
|
7
|
+
import { n as getBranchCommits, o as getFilesChangedInCommit } from "./git-ukq7VTuZ.mjs";
|
|
8
8
|
import { n as slugify, t as randomName } from "./names-CBy7d8K_.mjs";
|
|
9
9
|
import { relative } from "node:path";
|
|
10
10
|
//#region src/commands/generate.ts
|
|
@@ -124,6 +124,26 @@ function getFilesChangedInCommit(hash, opts) {
|
|
|
124
124
|
if (!result) return [];
|
|
125
125
|
return result.split("\n").filter(Boolean);
|
|
126
126
|
}
|
|
127
|
+
/** Get the git status of files in a directory (staged, unstaged, untracked) */
|
|
128
|
+
function getFileStatuses(dir, opts) {
|
|
129
|
+
const statuses = /* @__PURE__ */ new Map();
|
|
130
|
+
const result = tryRunArgs([
|
|
131
|
+
"git",
|
|
132
|
+
"status",
|
|
133
|
+
"--porcelain",
|
|
134
|
+
"--",
|
|
135
|
+
dir
|
|
136
|
+
], opts);
|
|
137
|
+
if (!result) return statuses;
|
|
138
|
+
for (const line of result.split("\n")) {
|
|
139
|
+
if (!line.trim()) continue;
|
|
140
|
+
const indexStatus = line[0];
|
|
141
|
+
const file = line.slice(3);
|
|
142
|
+
if (indexStatus === "?") statuses.set(file, "untracked");
|
|
143
|
+
else statuses.set(file, "staged");
|
|
144
|
+
}
|
|
145
|
+
return statuses;
|
|
146
|
+
}
|
|
127
147
|
/** Get all tags matching a pattern */
|
|
128
148
|
function listTags(pattern, opts) {
|
|
129
149
|
const result = tryRunArgs([
|
|
@@ -136,4 +156,4 @@ function listTags(pattern, opts) {
|
|
|
136
156
|
return result.split("\n").filter(Boolean);
|
|
137
157
|
}
|
|
138
158
|
//#endregion
|
|
139
|
-
export {
|
|
159
|
+
export { getFileStatuses as a, listTags as c, getCurrentBranch as i, pushWithTags as l, getBranchCommits as n, getFilesChangedInCommit as o, getChangedFiles as r, hasUncommittedChanges as s, createTag as t, tagExists as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -231,6 +231,8 @@ interface ChangelogContext {
|
|
|
231
231
|
bumpFiles: BumpFile[];
|
|
232
232
|
/** ISO date string (YYYY-MM-DD) */
|
|
233
233
|
date: string;
|
|
234
|
+
/** Where this entry will be used — formatters can customize output per target (default: 'changelog') */
|
|
235
|
+
target?: 'changelog' | 'github-release';
|
|
234
236
|
}
|
|
235
237
|
/**
|
|
236
238
|
* A changelog formatter receives full context and returns the complete
|
|
@@ -245,7 +247,7 @@ declare const defaultFormatter: ChangelogFormatter;
|
|
|
245
247
|
*/
|
|
246
248
|
declare function loadFormatter(changelog: BumpyConfig['changelog'], rootDir: string): Promise<ChangelogFormatter>;
|
|
247
249
|
/** Generate a changelog entry using the configured formatter */
|
|
248
|
-
declare function generateChangelogEntry(release: PlannedRelease, bumpFiles: BumpFile[], formatter?: ChangelogFormatter, date?: string): Promise<string>;
|
|
250
|
+
declare function generateChangelogEntry(release: PlannedRelease, bumpFiles: BumpFile[], formatter?: ChangelogFormatter, date?: string, target?: ChangelogContext['target']): Promise<string>;
|
|
249
251
|
/** Prepend a new entry to an existing CHANGELOG.md content */
|
|
250
252
|
declare function prependToChangelog(existingContent: string, newEntry: string): string;
|
|
251
253
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { a as DEP_TYPES, c as maxBump, i as DEFAULT_PUBLISH_CONFIG, n as DEFAULT_BUMP_RULES, o as bumpLevel, r as DEFAULT_CONFIG, s as hasCascade, t as BUMP_LEVELS } from "./types-
|
|
2
|
-
import { a as loadConfig, n as findRoot, r as getBumpyDir, s as matchGlob } from "./config-
|
|
3
|
-
import { t as discoverPackages } from "./workspace-
|
|
1
|
+
import { a as DEP_TYPES, c as maxBump, i as DEFAULT_PUBLISH_CONFIG, n as DEFAULT_BUMP_RULES, o as bumpLevel, r as DEFAULT_CONFIG, s as hasCascade, t as BUMP_LEVELS } from "./types-BX4pfmKh.mjs";
|
|
2
|
+
import { a as loadConfig, n as findRoot, r as getBumpyDir, s as matchGlob } from "./config-D13G4-R8.mjs";
|
|
3
|
+
import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
4
4
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
5
|
-
import { i as writeBumpFile, n as parseBumpFile, r as readBumpFiles } from "./bump-file-
|
|
5
|
+
import { i as writeBumpFile, n as parseBumpFile, r as readBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
6
6
|
import { n as satisfies, r as stripProtocol, t as bumpVersion } from "./semver-DfQyVLM_.mjs";
|
|
7
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
8
|
-
import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry, t as defaultFormatter } from "./changelog-
|
|
9
|
-
import { t as applyReleasePlan } from "./apply-release-plan-
|
|
10
|
-
import { t as publishPackages } from "./publish-pipeline-
|
|
7
|
+
import { t as assembleReleasePlan } from "./release-plan-pyxf71dx.mjs";
|
|
8
|
+
import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry, t as defaultFormatter } from "./changelog-DP3OrTqQ.mjs";
|
|
9
|
+
import { t as applyReleasePlan } from "./apply-release-plan-60VfCLF8.mjs";
|
|
10
|
+
import { t as publishPackages } from "./publish-pipeline-C1slMaJV.mjs";
|
|
11
11
|
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,11 +1,12 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
2
|
+
import { a as loadConfig } from "./config-D13G4-R8.mjs";
|
|
3
3
|
import { n as detectWorkspaces } from "./package-manager-CClZtIHP.mjs";
|
|
4
|
-
import { n as discoverWorkspace } from "./workspace-
|
|
4
|
+
import { n as discoverWorkspace } from "./workspace-BKOAMeki.mjs";
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
6
6
|
import { r as runArgsAsync, s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { i as loadFormatter, n as generateChangelogEntry } from "./changelog-DP3OrTqQ.mjs";
|
|
8
|
+
import { c as listTags, l as pushWithTags, s as hasUncommittedChanges } from "./git-ukq7VTuZ.mjs";
|
|
9
|
+
import { t as publishPackages } from "./publish-pipeline-C1slMaJV.mjs";
|
|
9
10
|
//#region src/core/github-release.ts
|
|
10
11
|
/** Get the current HEAD commit SHA */
|
|
11
12
|
function getHeadSha(rootDir) {
|
|
@@ -24,7 +25,7 @@ async function createIndividualReleases(releases, bumpFiles, rootDir, opts = {})
|
|
|
24
25
|
const headSha = getHeadSha(rootDir);
|
|
25
26
|
for (const release of releases) {
|
|
26
27
|
const tag = `${release.name}@${release.newVersion}`;
|
|
27
|
-
const body = buildReleaseBody(release, bumpFiles);
|
|
28
|
+
const body = opts.formatter ? await generateReleaseBody(release, bumpFiles, opts.formatter) : buildReleaseBody(release, bumpFiles);
|
|
28
29
|
const title = `${release.name} v${release.newVersion}`;
|
|
29
30
|
if (opts.dryRun) {
|
|
30
31
|
log.dim(` Would create GitHub release: ${title}`);
|
|
@@ -58,7 +59,7 @@ async function createAggregateRelease(releases, bumpFiles, rootDir, opts = {}) {
|
|
|
58
59
|
if (releases.length === 0) return;
|
|
59
60
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
60
61
|
const { tag, title } = resolveAggregateTagAndTitle(date, listTags(`release-${date}*`, { cwd: rootDir }), opts.title);
|
|
61
|
-
const body = buildAggregateBody(releases, bumpFiles);
|
|
62
|
+
const body = opts.formatter ? await generateAggregateBody(releases, bumpFiles, opts.formatter) : buildAggregateBody(releases, bumpFiles);
|
|
62
63
|
if (opts.dryRun) {
|
|
63
64
|
log.dim(` Would create aggregate GitHub release: ${title}`);
|
|
64
65
|
log.dim(` Tag: ${tag}`);
|
|
@@ -88,6 +89,36 @@ async function createAggregateRelease(releases, bumpFiles, rootDir, opts = {}) {
|
|
|
88
89
|
log.warn(`Failed to create aggregate GitHub release: ${err instanceof Error ? err.message : err}`);
|
|
89
90
|
}
|
|
90
91
|
}
|
|
92
|
+
/** Generate a release body for a single package using the changelog formatter */
|
|
93
|
+
async function generateReleaseBody(release, bumpFiles, formatter) {
|
|
94
|
+
return stripVersionHeading(await generateChangelogEntry(release, bumpFiles, formatter, void 0, "github-release")).trim() || "No changelog entries.";
|
|
95
|
+
}
|
|
96
|
+
/** Generate an aggregate release body using the changelog formatter */
|
|
97
|
+
async function generateAggregateBody(releases, bumpFiles, formatter) {
|
|
98
|
+
const lines = [];
|
|
99
|
+
const groups = [
|
|
100
|
+
["Major Changes", releases.filter((r) => r.type === "major")],
|
|
101
|
+
["Minor Changes", releases.filter((r) => r.type === "minor")],
|
|
102
|
+
["Patch Changes", releases.filter((r) => r.type === "patch")]
|
|
103
|
+
];
|
|
104
|
+
for (const [heading, group] of groups) {
|
|
105
|
+
if (group.length === 0) continue;
|
|
106
|
+
lines.push(`## ${heading}\n`);
|
|
107
|
+
for (const release of group) {
|
|
108
|
+
lines.push(`### ${release.name} v${release.newVersion}\n`);
|
|
109
|
+
const body = stripVersionHeading(await generateChangelogEntry(release, bumpFiles, formatter, void 0, "github-release")).trim();
|
|
110
|
+
if (body) lines.push(body);
|
|
111
|
+
else if (release.isDependencyBump) lines.push("- Updated dependencies");
|
|
112
|
+
else if (release.isCascadeBump) lines.push("- Version bump via cascade rule");
|
|
113
|
+
lines.push("");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return lines.join("\n").trim() || "No changelog entries.";
|
|
117
|
+
}
|
|
118
|
+
/** Strip the leading ## version heading and date sub-heading from a changelog entry */
|
|
119
|
+
function stripVersionHeading(entry) {
|
|
120
|
+
return entry.replace(/^## .+\n/, "").replace(/^<sub>.+<\/sub>\n/, "").replace(/^_.+_\n/, "");
|
|
121
|
+
}
|
|
91
122
|
function buildReleaseBody(release, bumpFiles) {
|
|
92
123
|
const lines = [];
|
|
93
124
|
const relevant = bumpFiles.filter((bf) => release.bumpFiles.includes(bf.id));
|
|
@@ -148,7 +179,7 @@ async function publishCommand(rootDir, opts) {
|
|
|
148
179
|
}
|
|
149
180
|
let toPublish = await findUnpublishedPackages(packages, config);
|
|
150
181
|
if (opts.filter) {
|
|
151
|
-
const { matchGlob } = await import("./config-
|
|
182
|
+
const { matchGlob } = await import("./config-D13G4-R8.mjs").then((n) => n.t);
|
|
152
183
|
const patterns = opts.filter.split(",").map((p) => p.trim());
|
|
153
184
|
toPublish = toPublish.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
|
|
154
185
|
}
|
|
@@ -187,11 +218,16 @@ async function publishCommand(rootDir, opts) {
|
|
|
187
218
|
const aggConfig = config.aggregateRelease;
|
|
188
219
|
const isAggregate = aggConfig === true || typeof aggConfig === "object" && aggConfig.enabled;
|
|
189
220
|
const aggTitle = typeof aggConfig === "object" ? aggConfig.title : void 0;
|
|
221
|
+
const formatter = config.changelog !== false ? await loadFormatter(config.changelog, rootDir) : void 0;
|
|
190
222
|
if (isAggregate) await createAggregateRelease(publishedReleases, releasePlan.bumpFiles, rootDir, {
|
|
191
223
|
dryRun: opts.dryRun,
|
|
192
|
-
title: aggTitle
|
|
224
|
+
title: aggTitle,
|
|
225
|
+
formatter
|
|
226
|
+
});
|
|
227
|
+
else await createIndividualReleases(publishedReleases, releasePlan.bumpFiles, rootDir, {
|
|
228
|
+
dryRun: opts.dryRun,
|
|
229
|
+
formatter
|
|
193
230
|
});
|
|
194
|
-
else await createIndividualReleases(publishedReleases, releasePlan.bumpFiles, rootDir, { dryRun: opts.dryRun });
|
|
195
231
|
}
|
|
196
232
|
}
|
|
197
233
|
/**
|
|
@@ -3,7 +3,7 @@ import { a as readJson, u as updateJsonNestedField } from "./fs-DnDogVn-.mjs";
|
|
|
3
3
|
import { r as resolveCatalogDep } from "./package-manager-CClZtIHP.mjs";
|
|
4
4
|
import { i as runAsync, o as sq, r as runArgsAsync, s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
|
|
5
5
|
import { r as stripProtocol } from "./semver-DfQyVLM_.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { t as createTag, u as tagExists } from "./git-ukq7VTuZ.mjs";
|
|
7
7
|
import { resolve } from "node:path";
|
|
8
8
|
import { unlink } from "node:fs/promises";
|
|
9
9
|
import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as maxBump, n as DEFAULT_BUMP_RULES, o as bumpLevel, s as hasCascade } from "./types-
|
|
2
|
-
import { s as matchGlob } from "./config-
|
|
1
|
+
import { c as maxBump, n as DEFAULT_BUMP_RULES, o as bumpLevel, s as hasCascade } from "./types-BX4pfmKh.mjs";
|
|
2
|
+
import { s as matchGlob } from "./config-D13G4-R8.mjs";
|
|
3
3
|
import { n as satisfies, t as bumpVersion } from "./semver-DfQyVLM_.mjs";
|
|
4
4
|
//#region src/core/release-plan.ts
|
|
5
5
|
/**
|
|
@@ -20,21 +20,16 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
20
20
|
const planned = /* @__PURE__ */ new Map();
|
|
21
21
|
const warnings = [];
|
|
22
22
|
const cascadeOverrides = /* @__PURE__ */ new Map();
|
|
23
|
-
const suppressedPackages = /* @__PURE__ */ new Set();
|
|
24
23
|
for (const bf of bumpFiles) for (const release of bf.releases) {
|
|
25
24
|
if (!packages.has(release.name)) continue;
|
|
26
25
|
const bump = release.type;
|
|
27
|
-
if (bump === "none")
|
|
28
|
-
suppressedPackages.add(release.name);
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
26
|
+
if (bump === "none") continue;
|
|
31
27
|
const existing = planned.get(release.name);
|
|
32
28
|
if (existing) {
|
|
33
29
|
existing.type = maxBump(existing.type, bump);
|
|
34
30
|
existing.bumpFiles.add(bf.id);
|
|
35
31
|
} else planned.set(release.name, {
|
|
36
32
|
type: bump,
|
|
37
|
-
suppressed: false,
|
|
38
33
|
isDependencyBump: false,
|
|
39
34
|
isCascadeBump: false,
|
|
40
35
|
bumpFiles: new Set([bf.id])
|
|
@@ -48,13 +43,6 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
48
43
|
}
|
|
49
44
|
}
|
|
50
45
|
}
|
|
51
|
-
for (const name of suppressedPackages) if (!planned.has(name)) planned.set(name, {
|
|
52
|
-
type: "patch",
|
|
53
|
-
suppressed: true,
|
|
54
|
-
isDependencyBump: false,
|
|
55
|
-
isCascadeBump: false,
|
|
56
|
-
bumpFiles: /* @__PURE__ */ new Set()
|
|
57
|
-
});
|
|
58
46
|
let changed = true;
|
|
59
47
|
let iterations = 0;
|
|
60
48
|
const MAX_ITERATIONS = 100;
|
|
@@ -62,7 +50,6 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
62
50
|
changed = false;
|
|
63
51
|
iterations++;
|
|
64
52
|
for (const [pkgName, bump] of planned) {
|
|
65
|
-
if (bump.suppressed) continue;
|
|
66
53
|
const pkg = packages.get(pkgName);
|
|
67
54
|
const newVersion = bumpVersion(pkg.version, bump.type);
|
|
68
55
|
const dependents = depGraph.getDependents(pkgName);
|
|
@@ -73,7 +60,6 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
73
60
|
let depBump;
|
|
74
61
|
if (dep.depType === "peerDependencies") depBump = bump.type;
|
|
75
62
|
else depBump = "patch";
|
|
76
|
-
if (planned.get(dep.name)?.suppressed) throw new Error(`Cannot suppress bump for '${dep.name}' (via 'none' in bump file) — '${pkgName}' is bumping to ${newVersion} which breaks the declared range '${dep.versionRange}'. Either widen the range or remove the 'none' entry.`);
|
|
77
63
|
if (dep.depType === "peerDependencies" && depBump !== "patch") {
|
|
78
64
|
let resolvedRange = dep.versionRange.replace(/^workspace:/, "");
|
|
79
65
|
if (resolvedRange === "^" || resolvedRange === "~") resolvedRange = `${resolvedRange}${pkg.version}`;
|
|
@@ -84,15 +70,11 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
84
70
|
}
|
|
85
71
|
for (const group of config.fixed) {
|
|
86
72
|
let groupBump;
|
|
87
|
-
for (const nameOrGlob of group) for (const [name, bump] of planned)
|
|
88
|
-
if (bump.suppressed) continue;
|
|
89
|
-
if (matchGlob(name, nameOrGlob)) groupBump = maxBump(groupBump, bump.type);
|
|
90
|
-
}
|
|
73
|
+
for (const nameOrGlob of group) for (const [name, bump] of planned) if (matchGlob(name, nameOrGlob)) groupBump = maxBump(groupBump, bump.type);
|
|
91
74
|
if (!groupBump) continue;
|
|
92
75
|
for (const nameOrGlob of group) for (const [name] of packages) {
|
|
93
76
|
if (!matchGlob(name, nameOrGlob)) continue;
|
|
94
77
|
const existing = planned.get(name);
|
|
95
|
-
if (existing && existing.suppressed) continue;
|
|
96
78
|
if (existing) {
|
|
97
79
|
const newType = maxBump(existing.type, groupBump);
|
|
98
80
|
if (newType !== existing.type) {
|
|
@@ -102,7 +84,6 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
102
84
|
} else {
|
|
103
85
|
planned.set(name, {
|
|
104
86
|
type: groupBump,
|
|
105
|
-
suppressed: false,
|
|
106
87
|
isDependencyBump: false,
|
|
107
88
|
isCascadeBump: false,
|
|
108
89
|
bumpFiles: /* @__PURE__ */ new Set()
|
|
@@ -113,15 +94,12 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
113
94
|
}
|
|
114
95
|
for (const group of config.linked) {
|
|
115
96
|
let groupBump;
|
|
116
|
-
for (const nameOrGlob of group) for (const [name, bump] of planned)
|
|
117
|
-
if (bump.suppressed) continue;
|
|
118
|
-
if (matchGlob(name, nameOrGlob)) groupBump = maxBump(groupBump, bump.type);
|
|
119
|
-
}
|
|
97
|
+
for (const nameOrGlob of group) for (const [name, bump] of planned) if (matchGlob(name, nameOrGlob)) groupBump = maxBump(groupBump, bump.type);
|
|
120
98
|
if (!groupBump) continue;
|
|
121
99
|
for (const nameOrGlob of group) for (const [name] of packages) {
|
|
122
100
|
if (!matchGlob(name, nameOrGlob)) continue;
|
|
123
101
|
const existing = planned.get(name);
|
|
124
|
-
if (!existing
|
|
102
|
+
if (!existing) continue;
|
|
125
103
|
const newType = maxBump(existing.type, groupBump);
|
|
126
104
|
if (newType !== existing.type) {
|
|
127
105
|
existing.type = newType;
|
|
@@ -130,12 +108,10 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
130
108
|
}
|
|
131
109
|
}
|
|
132
110
|
if (config.updateInternalDependencies !== "out-of-range") for (const [pkgName, bump] of planned) {
|
|
133
|
-
if (bump.suppressed) continue;
|
|
134
111
|
if (config.updateInternalDependencies === "minor" && bumpLevel(bump.type) < bumpLevel("minor")) continue;
|
|
135
112
|
const bfOverrides = cascadeOverrides.get(pkgName);
|
|
136
113
|
if (bfOverrides) for (const [pattern, cascadeBumpType] of bfOverrides) for (const [targetName] of packages) {
|
|
137
114
|
if (!matchGlob(targetName, pattern)) continue;
|
|
138
|
-
if (planned.get(targetName)?.suppressed) continue;
|
|
139
115
|
if (applyBump(planned, targetName, cascadeBumpType, false, true, bump.bumpFiles)) changed = true;
|
|
140
116
|
}
|
|
141
117
|
const cascadeTo = packages.get(pkgName)?.bumpy?.cascadeTo;
|
|
@@ -144,7 +120,6 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
144
120
|
const cascadeBump = rule.bumpAs === "match" ? bump.type : rule.bumpAs;
|
|
145
121
|
for (const [targetName] of packages) {
|
|
146
122
|
if (!matchGlob(targetName, pattern)) continue;
|
|
147
|
-
if (planned.get(targetName)?.suppressed) continue;
|
|
148
123
|
if (applyBump(planned, targetName, cascadeBump, false, true, bump.bumpFiles)) changed = true;
|
|
149
124
|
}
|
|
150
125
|
}
|
|
@@ -153,17 +128,14 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
153
128
|
const rule = resolveRule(dep.name, dep.depType, packages, config);
|
|
154
129
|
if (!rule) continue;
|
|
155
130
|
if (!shouldTrigger(bump.type, rule.trigger)) continue;
|
|
156
|
-
if (planned.get(dep.name)?.suppressed) continue;
|
|
157
131
|
const depBump = rule.bumpAs === "match" ? bump.type : rule.bumpAs;
|
|
158
132
|
if (applyBump(planned, dep.name, depBump, true, false, bump.bumpFiles)) changed = true;
|
|
159
133
|
}
|
|
160
134
|
}
|
|
161
135
|
else for (const [pkgName, bump] of planned) {
|
|
162
|
-
if (bump.suppressed) continue;
|
|
163
136
|
const bfOverrides = cascadeOverrides.get(pkgName);
|
|
164
137
|
if (bfOverrides) for (const [pattern, cascadeBumpType] of bfOverrides) for (const [targetName] of packages) {
|
|
165
138
|
if (!matchGlob(targetName, pattern)) continue;
|
|
166
|
-
if (planned.get(targetName)?.suppressed) continue;
|
|
167
139
|
if (applyBump(planned, targetName, cascadeBumpType, false, true, bump.bumpFiles)) changed = true;
|
|
168
140
|
}
|
|
169
141
|
const cascadeTo = packages.get(pkgName)?.bumpy?.cascadeTo;
|
|
@@ -172,33 +144,13 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
172
144
|
const cascadeBump = rule.bumpAs === "match" ? bump.type : rule.bumpAs;
|
|
173
145
|
for (const [targetName] of packages) {
|
|
174
146
|
if (!matchGlob(targetName, pattern)) continue;
|
|
175
|
-
if (planned.get(targetName)?.suppressed) continue;
|
|
176
147
|
if (applyBump(planned, targetName, cascadeBump, false, true, bump.bumpFiles)) changed = true;
|
|
177
148
|
}
|
|
178
149
|
}
|
|
179
150
|
}
|
|
180
151
|
}
|
|
181
|
-
for (const [name, bump] of planned) {
|
|
182
|
-
if (!bump.suppressed) continue;
|
|
183
|
-
const pkg = packages.get(name);
|
|
184
|
-
for (const [depName, depBump] of planned) {
|
|
185
|
-
if (depBump.suppressed) continue;
|
|
186
|
-
const depPkg = packages.get(depName);
|
|
187
|
-
const newDepVersion = bumpVersion(depPkg.version, depBump.type);
|
|
188
|
-
for (const depType of [
|
|
189
|
-
"dependencies",
|
|
190
|
-
"peerDependencies",
|
|
191
|
-
"optionalDependencies"
|
|
192
|
-
]) {
|
|
193
|
-
const range = pkg[depType]?.[depName];
|
|
194
|
-
if (!range) continue;
|
|
195
|
-
if (!satisfies(newDepVersion, range, depPkg.version)) throw new Error(`Cannot suppress bump for '${name}' (via 'none' in bump file) — '${depName}' is bumping to ${newDepVersion} which breaks the declared range '${range}'. Either widen the range or remove the 'none' entry.`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
152
|
const releases = [];
|
|
200
153
|
for (const [name, bump] of planned) {
|
|
201
|
-
if (bump.suppressed) continue;
|
|
202
154
|
const pkg = packages.get(name);
|
|
203
155
|
if (!pkg) continue;
|
|
204
156
|
const newVersion = bumpVersion(pkg.version, bump.type);
|
|
@@ -224,7 +176,6 @@ function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
|
|
|
224
176
|
function applyBump(planned, name, type, isDependencyBump, isCascadeBump, sourceBumpFiles) {
|
|
225
177
|
const existing = planned.get(name);
|
|
226
178
|
if (existing) {
|
|
227
|
-
if (existing.suppressed) return false;
|
|
228
179
|
const newType = maxBump(existing.type, type);
|
|
229
180
|
if (newType === existing.type) return false;
|
|
230
181
|
existing.type = newType;
|
|
@@ -235,7 +186,6 @@ function applyBump(planned, name, type, isDependencyBump, isCascadeBump, sourceB
|
|
|
235
186
|
}
|
|
236
187
|
planned.set(name, {
|
|
237
188
|
type,
|
|
238
|
-
suppressed: false,
|
|
239
189
|
isDependencyBump,
|
|
240
190
|
isCascadeBump,
|
|
241
191
|
bumpFiles: new Set(sourceBumpFiles)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
3
|
-
import { t as discoverPackages } from "./workspace-
|
|
2
|
+
import { a as loadConfig } from "./config-D13G4-R8.mjs";
|
|
3
|
+
import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
4
4
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
5
|
-
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-
|
|
6
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
7
|
-
import { i as getCurrentBranch, r as getChangedFiles } from "./git-
|
|
5
|
+
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
6
|
+
import { t as assembleReleasePlan } from "./release-plan-pyxf71dx.mjs";
|
|
7
|
+
import { i as getCurrentBranch, r as getChangedFiles } from "./git-ukq7VTuZ.mjs";
|
|
8
8
|
//#region src/commands/status.ts
|
|
9
9
|
async function statusCommand(rootDir, opts) {
|
|
10
10
|
const config = await loadConfig(rootDir);
|
|
@@ -31,7 +31,7 @@ async function statusCommand(rootDir, opts) {
|
|
|
31
31
|
releases = releases.filter((r) => types.includes(r.type));
|
|
32
32
|
}
|
|
33
33
|
if (opts.filter) {
|
|
34
|
-
const { matchGlob } = await import("./config-
|
|
34
|
+
const { matchGlob } = await import("./config-D13G4-R8.mjs").then((n) => n.t);
|
|
35
35
|
const patterns = opts.filter.split(",").map((p) => p.trim());
|
|
36
36
|
releases = releases.filter((r) => patterns.some((p) => matchGlob(r.name, p)));
|
|
37
37
|
}
|
|
@@ -66,7 +66,7 @@ const DEFAULT_CONFIG = {
|
|
|
66
66
|
title: "🐸 Versioned release",
|
|
67
67
|
branch: "bumpy/version-packages",
|
|
68
68
|
preamble: [
|
|
69
|
-
`<a href="https://bumpy.varlock.dev"><img src="https://raw.githubusercontent.com/dmno-dev/bumpy/main/images/frog-
|
|
69
|
+
`<a href="https://bumpy.varlock.dev"><img src="https://raw.githubusercontent.com/dmno-dev/bumpy/main/images/frog-clipboard.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
|
|
70
70
|
"",
|
|
71
71
|
`This PR was created and will be kept in sync by [bumpy](https://bumpy.varlock.dev) based on your bump files (in \`.bumpy/\`). Merge it when you are ready to release the packages listed below:`,
|
|
72
72
|
"<br clear=\"left\" />"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
2
|
+
import { a as loadConfig } from "./config-D13G4-R8.mjs";
|
|
3
3
|
import { n as detectWorkspaces } from "./package-manager-CClZtIHP.mjs";
|
|
4
|
-
import { t as discoverPackages } from "./workspace-
|
|
4
|
+
import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
6
6
|
import { n as runArgs, s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
|
|
7
|
-
import { r as readBumpFiles } from "./bump-file-
|
|
8
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
9
|
-
import { t as applyReleasePlan } from "./apply-release-plan-
|
|
10
|
-
import { t as resolveCommitMessage } from "./commit-message-
|
|
7
|
+
import { r as readBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
8
|
+
import { t as assembleReleasePlan } from "./release-plan-pyxf71dx.mjs";
|
|
9
|
+
import { t as applyReleasePlan } from "./apply-release-plan-60VfCLF8.mjs";
|
|
10
|
+
import { t as resolveCommitMessage } from "./commit-message-3e4KhzFV.mjs";
|
|
11
11
|
//#region src/commands/version.ts
|
|
12
12
|
async function versionCommand(rootDir, opts = {}) {
|
|
13
13
|
const config = await loadConfig(rootDir);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as readJson, n as exists } from "./fs-DnDogVn-.mjs";
|
|
2
|
-
import { i as isPackageManaged, o as loadPackageConfig } from "./config-
|
|
2
|
+
import { i as isPackageManaged, o as loadPackageConfig } from "./config-D13G4-R8.mjs";
|
|
3
3
|
import { n as detectWorkspaces } from "./package-manager-CClZtIHP.mjs";
|
|
4
4
|
import { relative, resolve } from "node:path";
|
|
5
5
|
import { readdir, stat } from "node:fs/promises";
|
package/package.json
CHANGED
|
@@ -43,7 +43,7 @@ For each affected package, choose the appropriate bump level:
|
|
|
43
43
|
| **minor** | New features: added exports, new options, new functionality |
|
|
44
44
|
| **patch** | Bug fixes, internal refactors, documentation, dependency updates |
|
|
45
45
|
|
|
46
|
-
Use `none` in a bump file to
|
|
46
|
+
Use `none` in a bump file to acknowledge a change without triggering a direct bump. Cascading bumps from other packages can still apply normally.
|
|
47
47
|
|
|
48
48
|
### 4. Write a clear summary
|
|
49
49
|
|