@varlock/bumpy 1.3.0 → 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 +1 -1
- package/dist/{add-ET1tcdQm.mjs → add-D1uiW7VA.mjs} +22 -3
- package/dist/{apply-release-plan-BvZ32LAm.mjs → apply-release-plan-60VfCLF8.mjs} +1 -1
- package/dist/{changelog-BIkNBJ15.mjs → changelog-DP3OrTqQ.mjs} +3 -3
- package/dist/{changelog-github-BAtgxeXv.mjs → changelog-github-Da5KekQd.mjs} +1 -1
- package/dist/{picomatch-TGJi--_I.mjs → check-CS8WIGZA.mjs} +131 -2
- package/dist/{ci-WJ8kTjeN.mjs → ci-CnIkaf7Q.mjs} +8 -8
- package/dist/cli.mjs +25 -15
- package/dist/{generate-BJq--oCu.mjs → generate-D0KJsvpD.mjs} +1 -1
- package/dist/{git-D0__HP86.mjs → git-ukq7VTuZ.mjs} +21 -1
- package/dist/index.mjs +4 -4
- package/dist/{publish-CfZCAlPx.mjs → publish-DWdN3o9u.mjs} +3 -3
- package/dist/{publish-pipeline-BvLIu7WF.mjs → publish-pipeline-C1slMaJV.mjs} +1 -1
- package/dist/{release-plan-RBjKmavL.mjs → release-plan-pyxf71dx.mjs} +4 -54
- package/dist/{status-pMfPtt1p.mjs → status-DyzcQ6CD.mjs} +2 -2
- package/dist/{version-DLU0h1cq.mjs → version-BxDhayli.mjs} +3 -3
- package/package.json +1 -1
- package/skills/add-change/SKILL.md +1 -1
- package/dist/check-C80o_gJK.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/README.md
CHANGED
|
@@ -22,7 +22,7 @@ A modern package versioning, release, and changelog generation tool. Built for m
|
|
|
22
22
|
Bumpy uses **bump files** (you may know them as "changesets" if coming from [that tool 🦋](https://github.com/changesets/changesets)) - small markdown files that declare an intent to release packages with a bump level (patch/minor/major), and a description that ends up in changelogs. Developers create these files as part of their PRs, and these files are then used to consolidate changes, generate changelogs, and trigger publishing. Specifically:
|
|
23
23
|
|
|
24
24
|
- Devs/agents create bump files as part of their PRs (using `bumpy add` or manually)
|
|
25
|
-
- A pre-
|
|
25
|
+
- A git hook (pre-commit or pre-push) can enforce bump files exist for changed packages
|
|
26
26
|
- In CI, a workflow checks PRs for bump files, leaves a comment on the PR detailing changed packages
|
|
27
27
|
- As PRs merge to the base branch, a "release PR" is kept up to date
|
|
28
28
|
- Shows what packages will be released and their changelogs
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
|
|
2
2
|
import { n as exists, t as ensureDir } from "./fs-DnDogVn-.mjs";
|
|
3
3
|
import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir, s as matchGlob } from "./config-D13G4-R8.mjs";
|
|
4
|
-
import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
4
|
+
import { n as discoverWorkspace, t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
6
6
|
import { i as writeBumpFile } from "./bump-file-CoaSxqne.mjs";
|
|
7
|
-
import { r as getChangedFiles } from "./git-
|
|
7
|
+
import { r as getChangedFiles } from "./git-ukq7VTuZ.mjs";
|
|
8
8
|
import { c as ot, d as yt, i as _t, l as pt, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-CJT1JFFa.mjs";
|
|
9
9
|
import { n as slugify, t as randomName } from "./names-CBy7d8K_.mjs";
|
|
10
|
-
import { t as require_picomatch } from "./
|
|
10
|
+
import { findChangedPackages, t as require_picomatch } from "./check-CS8WIGZA.mjs";
|
|
11
11
|
import { relative, resolve } from "node:path";
|
|
12
12
|
import * as readline from "node:readline";
|
|
13
13
|
//#region src/prompts/bump-select.ts
|
|
@@ -191,6 +191,25 @@ async function addCommand(rootDir, opts) {
|
|
|
191
191
|
log.success(`🐸 Created empty bump file: .bumpy/${filename}.md`);
|
|
192
192
|
return;
|
|
193
193
|
}
|
|
194
|
+
if (opts.none) {
|
|
195
|
+
const { packages } = await discoverWorkspace(rootDir, config);
|
|
196
|
+
const changedPackages = await findChangedPackages(getChangedFiles(rootDir, config.baseBranch), packages, rootDir, config);
|
|
197
|
+
if (changedPackages.length === 0) {
|
|
198
|
+
log.info("No changed packages detected.");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const releases = changedPackages.map((name) => ({
|
|
202
|
+
name,
|
|
203
|
+
type: "none"
|
|
204
|
+
}));
|
|
205
|
+
const summary = opts.message || "";
|
|
206
|
+
const filename = opts.name ? slugify(opts.name) : randomName();
|
|
207
|
+
if (await exists(resolve(bumpyDir, `${filename}.md`))) await writeBumpFile(rootDir, `${filename}-${Date.now()}`, releases, summary);
|
|
208
|
+
else await writeBumpFile(rootDir, filename, releases, summary);
|
|
209
|
+
log.success(`🐸 Created bump file with ${changedPackages.length} package(s) set to none: .bumpy/${filename}.md`);
|
|
210
|
+
for (const name of changedPackages) log.dim(` ${name}: none`);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
194
213
|
let releases;
|
|
195
214
|
let summary;
|
|
196
215
|
let filename;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as readJson, c as removeFile, f as writeText, i as listFiles, l as updateJsonFields, n as exists, s as readText, u as updateJsonNestedField } from "./fs-DnDogVn-.mjs";
|
|
2
2
|
import { r as getBumpyDir } from "./config-D13G4-R8.mjs";
|
|
3
|
-
import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry } from "./changelog-
|
|
3
|
+
import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry } from "./changelog-DP3OrTqQ.mjs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
//#region src/core/apply-release-plan.ts
|
|
6
6
|
/** Apply the release plan: bump versions, update changelogs, delete bump files */
|
|
@@ -6,7 +6,7 @@ import { realpathSync } from "node:fs";
|
|
|
6
6
|
/** Get the bump type a bump file applies to a specific package */
|
|
7
7
|
function getBumpTypeForPackage(bf, packageName) {
|
|
8
8
|
const rel = bf.releases.find((r) => r.name === packageName);
|
|
9
|
-
return rel?.type === "none" ? "patch" : rel
|
|
9
|
+
return rel?.type === "none" || !rel?.type ? "patch" : rel.type;
|
|
10
10
|
}
|
|
11
11
|
/** Sort bump files by bump type for a specific package (major → minor → patch) */
|
|
12
12
|
function sortBumpFilesByType(bumpFiles, packageName) {
|
|
@@ -43,7 +43,7 @@ const defaultFormatter = (ctx) => {
|
|
|
43
43
|
const BUILTIN_FORMATTERS = {
|
|
44
44
|
default: defaultFormatter,
|
|
45
45
|
github: async () => {
|
|
46
|
-
const { createGithubFormatter } = await import("./changelog-github-
|
|
46
|
+
const { createGithubFormatter } = await import("./changelog-github-Da5KekQd.mjs");
|
|
47
47
|
return createGithubFormatter();
|
|
48
48
|
}
|
|
49
49
|
};
|
|
@@ -54,7 +54,7 @@ const BUILTIN_FORMATTERS = {
|
|
|
54
54
|
async function loadFormatter(changelog, rootDir) {
|
|
55
55
|
const [name, options] = Array.isArray(changelog) ? changelog : [changelog, {}];
|
|
56
56
|
if (name === "github") {
|
|
57
|
-
const { createGithubFormatter } = await import("./changelog-github-
|
|
57
|
+
const { createGithubFormatter } = await import("./changelog-github-Da5KekQd.mjs");
|
|
58
58
|
return createGithubFormatter(options);
|
|
59
59
|
}
|
|
60
60
|
if (typeof name === "string" && BUILTIN_FORMATTERS[name]) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
|
|
2
|
-
import { o as sortBumpFilesByType, r as getBumpTypeForPackage } from "./changelog-
|
|
2
|
+
import { o as sortBumpFilesByType, r as getBumpTypeForPackage } from "./changelog-DP3OrTqQ.mjs";
|
|
3
3
|
//#region src/core/changelog-github.ts
|
|
4
4
|
/** Authors filtered from "Thanks" attribution by default (e.g. bots) */
|
|
5
5
|
/** Authors filtered from "Thanks" attribution by default (e.g. AI/automation bots) */
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import { i as __commonJSMin } from "./logger-C2dEe5Su.mjs";
|
|
1
|
+
import { i as __commonJSMin, n as log, o as __toESM, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
+
import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir } from "./config-D13G4-R8.mjs";
|
|
3
|
+
import { n as discoverWorkspace } from "./workspace-BKOAMeki.mjs";
|
|
4
|
+
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
5
|
+
import { a as getFileStatuses, r as getChangedFiles } from "./git-ukq7VTuZ.mjs";
|
|
6
|
+
import { relative } from "node:path";
|
|
2
7
|
//#region ../../node_modules/.bun/picomatch@4.0.4/node_modules/picomatch/lib/constants.js
|
|
3
8
|
var require_constants = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4
9
|
const WIN_SLASH = "\\\\/";
|
|
@@ -1867,4 +1872,128 @@ var require_picomatch = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
1867
1872
|
module.exports = picomatch;
|
|
1868
1873
|
}));
|
|
1869
1874
|
//#endregion
|
|
1870
|
-
|
|
1875
|
+
//#region src/commands/check.ts
|
|
1876
|
+
var import_picomatch = /* @__PURE__ */ __toESM(require_picomatch(), 1);
|
|
1877
|
+
/**
|
|
1878
|
+
* Local check: detect which packages have changed on this branch
|
|
1879
|
+
* and verify they have corresponding bump files.
|
|
1880
|
+
* Designed for pre-push hooks — no GitHub API needed.
|
|
1881
|
+
*
|
|
1882
|
+
* Default: at least one bump file must exist, uncovered packages are warned.
|
|
1883
|
+
* --strict: every changed package must be covered.
|
|
1884
|
+
* --no-fail: warn only, never exit 1.
|
|
1885
|
+
* --hook pre-commit: only staged + committed bump files count.
|
|
1886
|
+
* --hook pre-push: only committed bump files count.
|
|
1887
|
+
*/
|
|
1888
|
+
async function checkCommand(rootDir, opts = {}) {
|
|
1889
|
+
const config = await loadConfig(rootDir);
|
|
1890
|
+
const { packages } = await discoverWorkspace(rootDir, config);
|
|
1891
|
+
const baseBranch = config.baseBranch;
|
|
1892
|
+
const changedFiles = getChangedFiles(rootDir, baseBranch);
|
|
1893
|
+
if (changedFiles.length === 0) {
|
|
1894
|
+
log.info("No changed files detected.");
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
const { bumpFiles: allBumpFiles, errors: parseErrors } = await readBumpFiles(rootDir);
|
|
1898
|
+
if (parseErrors.length > 0) {
|
|
1899
|
+
for (const err of parseErrors) log.error(err);
|
|
1900
|
+
process.exit(1);
|
|
1901
|
+
}
|
|
1902
|
+
const bumpyRelDir = relative(rootDir, getBumpyDir(rootDir));
|
|
1903
|
+
const fileStatuses = getFileStatuses(bumpyRelDir, { cwd: rootDir });
|
|
1904
|
+
const augmentedChangedFiles = [...changedFiles];
|
|
1905
|
+
for (const [file] of fileStatuses) if (file.endsWith(".md") && !file.endsWith("README.md") && !augmentedChangedFiles.includes(file)) augmentedChangedFiles.push(file);
|
|
1906
|
+
const { branchBumpFiles, emptyBumpFileIds } = filterBranchBumpFiles(allBumpFiles, augmentedChangedFiles, rootDir);
|
|
1907
|
+
const bumpFileStatuses = /* @__PURE__ */ new Map();
|
|
1908
|
+
for (const bf of branchBumpFiles) {
|
|
1909
|
+
const filePath = `${bumpyRelDir}/${bf.id}.md`;
|
|
1910
|
+
const status = fileStatuses.get(filePath);
|
|
1911
|
+
bumpFileStatuses.set(bf.id, status ?? "committed");
|
|
1912
|
+
}
|
|
1913
|
+
for (const id of emptyBumpFileIds) {
|
|
1914
|
+
const filePath = `${bumpyRelDir}/${id}.md`;
|
|
1915
|
+
const status = fileStatuses.get(filePath);
|
|
1916
|
+
bumpFileStatuses.set(id, status ?? "committed");
|
|
1917
|
+
}
|
|
1918
|
+
const effectiveBumpFiles = opts.hook ? branchBumpFiles.filter((bf) => {
|
|
1919
|
+
const status = bumpFileStatuses.get(bf.id);
|
|
1920
|
+
if (opts.hook === "pre-push") return status === "committed";
|
|
1921
|
+
if (opts.hook === "pre-commit") return status !== "untracked";
|
|
1922
|
+
return true;
|
|
1923
|
+
}) : branchBumpFiles;
|
|
1924
|
+
const effectiveEmptyIds = opts.hook ? emptyBumpFileIds.filter((id) => {
|
|
1925
|
+
const status = bumpFileStatuses.get(id);
|
|
1926
|
+
if (opts.hook === "pre-push") return status === "committed";
|
|
1927
|
+
if (opts.hook === "pre-commit") return status !== "untracked";
|
|
1928
|
+
return true;
|
|
1929
|
+
}) : emptyBumpFileIds;
|
|
1930
|
+
if (opts.hook) {
|
|
1931
|
+
const excludedBumpFiles = branchBumpFiles.filter((bf) => !effectiveBumpFiles.includes(bf));
|
|
1932
|
+
const excludedEmptyIds = emptyBumpFileIds.filter((id) => !effectiveEmptyIds.includes(id));
|
|
1933
|
+
for (const bf of excludedBumpFiles) {
|
|
1934
|
+
const status = bumpFileStatuses.get(bf.id);
|
|
1935
|
+
if (opts.hook === "pre-push" && status === "staged") log.warn(`${bumpyRelDir}/${bf.id}.md is staged but not committed — it won't be included in the push`);
|
|
1936
|
+
else if (status === "untracked") log.warn(`${bumpyRelDir}/${bf.id}.md is untracked — run \`git add\` to include it`);
|
|
1937
|
+
}
|
|
1938
|
+
for (const id of excludedEmptyIds) {
|
|
1939
|
+
const status = bumpFileStatuses.get(id);
|
|
1940
|
+
if (opts.hook === "pre-push" && status === "staged") log.warn(`${bumpyRelDir}/${id}.md is staged but not committed — it won't be included in the push`);
|
|
1941
|
+
else if (status === "untracked") log.warn(`${bumpyRelDir}/${id}.md is untracked — run \`git add\` to include it`);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
const hasEmptyBumpFile = effectiveEmptyIds.length > 0;
|
|
1945
|
+
const coveredPackages = /* @__PURE__ */ new Set();
|
|
1946
|
+
for (const bf of effectiveBumpFiles) for (const release of bf.releases) coveredPackages.add(release.name);
|
|
1947
|
+
const changedPackages = await findChangedPackages(changedFiles, packages, rootDir, config);
|
|
1948
|
+
if (changedPackages.length === 0) {
|
|
1949
|
+
log.info("No managed packages have changed.");
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
const missing = changedPackages.filter((name) => !coveredPackages.has(name));
|
|
1953
|
+
const hasAnyCoverage = effectiveBumpFiles.length > 0 || hasEmptyBumpFile;
|
|
1954
|
+
if (missing.length === 0 || hasEmptyBumpFile && !opts.strict) {
|
|
1955
|
+
if (hasEmptyBumpFile && missing.length > 0) log.success("Empty bump file found — uncovered packages acknowledged.");
|
|
1956
|
+
else log.success(`🐸 All ${changedPackages.length} changed package(s) have bump files.`);
|
|
1957
|
+
if (effectiveBumpFiles.length > 0) printBumpFileList(effectiveBumpFiles.map((bf) => bf.id), bumpyRelDir, bumpFileStatuses);
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
const willFail = !opts.noFail && (opts.strict || !hasAnyCoverage);
|
|
1961
|
+
(willFail ? log.error : log.warn)(`${missing.length} changed package(s) missing bump files:\n`);
|
|
1962
|
+
for (const name of missing) console.log(` ${colorize(name, "yellow")}`);
|
|
1963
|
+
if (effectiveBumpFiles.length > 0) {
|
|
1964
|
+
console.log();
|
|
1965
|
+
printBumpFileList(effectiveBumpFiles.map((bf) => bf.id), bumpyRelDir, bumpFileStatuses);
|
|
1966
|
+
}
|
|
1967
|
+
console.log();
|
|
1968
|
+
if (opts.strict) log.dim("Run `bumpy add` to create a bump file. Use bump type `none` for packages that changed but don't need a bump.");
|
|
1969
|
+
else log.dim("Run `bumpy add` to create a bump file, or `bumpy add --empty` if no release is needed.");
|
|
1970
|
+
log.dim("To adjust which files trigger change detection, set `changedFilePatterns` in .bumpy/_config.json.");
|
|
1971
|
+
if (willFail) process.exit(1);
|
|
1972
|
+
}
|
|
1973
|
+
function printBumpFileList(ids, bumpyRelDir, statuses) {
|
|
1974
|
+
log.dim("Bump files on this branch:");
|
|
1975
|
+
for (const id of ids) {
|
|
1976
|
+
const status = statuses.get(id);
|
|
1977
|
+
const statusLabel = status === "staged" ? colorize(" (staged)", "yellow") : status === "untracked" ? colorize(" (untracked)", "yellow") : "";
|
|
1978
|
+
log.dim(` ${bumpyRelDir}/${id}.md${statusLabel}`);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
/** Map changed files to the packages they belong to */
|
|
1982
|
+
async function findChangedPackages(changedFiles, packages, rootDir, config) {
|
|
1983
|
+
const changed = /* @__PURE__ */ new Set();
|
|
1984
|
+
const matchers = /* @__PURE__ */ new Map();
|
|
1985
|
+
for (const [name, pkg] of packages) {
|
|
1986
|
+
const patterns = (await loadPackageConfig(pkg.dir, config, name)).changedFilePatterns ?? config.changedFilePatterns;
|
|
1987
|
+
matchers.set(name, (0, import_picomatch.default)(patterns));
|
|
1988
|
+
}
|
|
1989
|
+
for (const file of changedFiles) for (const [name, pkg] of packages) {
|
|
1990
|
+
const pkgRelDir = relative(rootDir, pkg.dir);
|
|
1991
|
+
if (file.startsWith(pkgRelDir + "/")) {
|
|
1992
|
+
const relToPackage = file.slice(pkgRelDir.length + 1);
|
|
1993
|
+
if (matchers.get(name)(relToPackage)) changed.add(name);
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return [...changed];
|
|
1997
|
+
}
|
|
1998
|
+
//#endregion
|
|
1999
|
+
export { checkCommand, findChangedPackages, require_picomatch as t };
|
|
@@ -5,11 +5,11 @@ import { n as discoverWorkspace } from "./workspace-BKOAMeki.mjs";
|
|
|
5
5
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
6
6
|
import { n as runArgs, r as runArgsAsync, s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
|
|
7
7
|
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
8
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
9
|
-
import { r as getChangedFiles } from "./git-
|
|
8
|
+
import { t as assembleReleasePlan } from "./release-plan-pyxf71dx.mjs";
|
|
9
|
+
import { r as getChangedFiles } from "./git-ukq7VTuZ.mjs";
|
|
10
10
|
import { t as randomName } from "./names-CBy7d8K_.mjs";
|
|
11
|
-
import { findChangedPackages } from "./check-
|
|
12
|
-
import { t as resolveCommitMessage } from "./commit-message-
|
|
11
|
+
import { findChangedPackages } from "./check-CS8WIGZA.mjs";
|
|
12
|
+
import { t as resolveCommitMessage } from "./commit-message-3e4KhzFV.mjs";
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
14
14
|
//#region src/commands/ci.ts
|
|
15
15
|
/**
|
|
@@ -135,7 +135,7 @@ async function ciReleaseCommand(rootDir, opts) {
|
|
|
135
135
|
}
|
|
136
136
|
if (bumpFiles.length === 0) {
|
|
137
137
|
log.info("No pending bump files — checking for unpublished packages...");
|
|
138
|
-
const { publishCommand } = await import("./publish-
|
|
138
|
+
const { publishCommand } = await import("./publish-DWdN3o9u.mjs");
|
|
139
139
|
await publishCommand(rootDir, { tag: opts.tag });
|
|
140
140
|
return;
|
|
141
141
|
}
|
|
@@ -149,7 +149,7 @@ async function ciReleaseCommand(rootDir, opts) {
|
|
|
149
149
|
}
|
|
150
150
|
async function autoPublish(rootDir, config, plan, tag) {
|
|
151
151
|
log.step("Running bumpy version...");
|
|
152
|
-
const { versionCommand } = await import("./version-
|
|
152
|
+
const { versionCommand } = await import("./version-BxDhayli.mjs");
|
|
153
153
|
await versionCommand(rootDir);
|
|
154
154
|
log.step("Committing version changes...");
|
|
155
155
|
runArgs([
|
|
@@ -178,7 +178,7 @@ async function autoPublish(rootDir, config, plan, tag) {
|
|
|
178
178
|
], { cwd: rootDir });
|
|
179
179
|
}
|
|
180
180
|
log.step("Running bumpy publish...");
|
|
181
|
-
const { publishCommand } = await import("./publish-
|
|
181
|
+
const { publishCommand } = await import("./publish-DWdN3o9u.mjs");
|
|
182
182
|
await publishCommand(rootDir, { tag });
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
@@ -344,7 +344,7 @@ async function createVersionPr(rootDir, plan, config, packageDirs, branchName) {
|
|
|
344
344
|
branch
|
|
345
345
|
], { cwd: rootDir });
|
|
346
346
|
log.step("Running bumpy version...");
|
|
347
|
-
const { versionCommand } = await import("./version-
|
|
347
|
+
const { versionCommand } = await import("./version-BxDhayli.mjs");
|
|
348
348
|
await versionCommand(rootDir);
|
|
349
349
|
runArgs([
|
|
350
350
|
"git",
|
package/dist/cli.mjs
CHANGED
|
@@ -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,21 +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
96
|
noFail: ciFlags["no-fail"] === true
|
|
90
97
|
});
|
|
91
98
|
} else if (subcommand === "release") {
|
|
92
|
-
const { ciReleaseCommand } = await import("./ci-
|
|
99
|
+
const { ciReleaseCommand } = await import("./ci-CnIkaf7Q.mjs");
|
|
93
100
|
await ciReleaseCommand(rootDir, {
|
|
94
101
|
mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
|
|
95
102
|
tag: ciFlags.tag,
|
|
96
103
|
branch: ciFlags.branch
|
|
97
104
|
});
|
|
98
105
|
} else if (subcommand === "setup") {
|
|
99
|
-
const { ciSetupCommand } = await import("./ci-setup-
|
|
106
|
+
const { ciSetupCommand } = await import("./ci-setup-DWxrdSK6.mjs");
|
|
100
107
|
await ciSetupCommand(rootDir);
|
|
101
108
|
} else {
|
|
102
109
|
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
|
|
@@ -106,7 +113,7 @@ async function main() {
|
|
|
106
113
|
}
|
|
107
114
|
case "publish": {
|
|
108
115
|
const rootDir = await findRoot();
|
|
109
|
-
const { publishCommand } = await import("./publish-
|
|
116
|
+
const { publishCommand } = await import("./publish-DWdN3o9u.mjs");
|
|
110
117
|
await publishCommand(rootDir, {
|
|
111
118
|
dryRun: flags["dry-run"] === true,
|
|
112
119
|
tag: flags.tag,
|
|
@@ -130,7 +137,7 @@ async function main() {
|
|
|
130
137
|
}
|
|
131
138
|
case "--version":
|
|
132
139
|
case "-v":
|
|
133
|
-
console.log(`bumpy 1.
|
|
140
|
+
console.log(`bumpy 1.4.0`);
|
|
134
141
|
break;
|
|
135
142
|
case "help":
|
|
136
143
|
case "--help":
|
|
@@ -150,18 +157,21 @@ async function main() {
|
|
|
150
157
|
}
|
|
151
158
|
function printHelp() {
|
|
152
159
|
console.log(`
|
|
153
|
-
${colorize(`🐸 bumpy v1.
|
|
160
|
+
${colorize(`🐸 bumpy v1.4.0`, "bold")} - Modern monorepo versioning
|
|
154
161
|
|
|
155
162
|
Usage: bumpy <command> [options]
|
|
156
163
|
|
|
157
164
|
Commands:
|
|
158
165
|
init [--force] Initialize .bumpy/ (migrates from .changeset/ if found)
|
|
159
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)
|
|
160
169
|
generate Generate bump file from branch commits
|
|
161
170
|
status Show pending releases
|
|
162
|
-
check Verify changed packages have bump files (for
|
|
171
|
+
check Verify changed packages have bump files (for git hooks)
|
|
163
172
|
--strict Fail if any changed package is uncovered (default: only fail if no bump files at all)
|
|
164
173
|
--no-fail Warn only, never exit 1
|
|
174
|
+
--hook <context> Hook context: "pre-commit" or "pre-push" (controls which bump files count)
|
|
165
175
|
version [--commit] Apply bump files and bump versions
|
|
166
176
|
publish Publish versioned packages
|
|
167
177
|
ci check PR check — report pending releases, comment on PR
|
|
@@ -4,7 +4,7 @@ import { a as loadConfig, r as getBumpyDir } from "./config-D13G4-R8.mjs";
|
|
|
4
4
|
import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
5
5
|
import { s as tryRunArgs } from "./shell-u3bYGxNy.mjs";
|
|
6
6
|
import { i as writeBumpFile } from "./bump-file-CoaSxqne.mjs";
|
|
7
|
-
import {
|
|
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.mjs
CHANGED
|
@@ -4,8 +4,8 @@ import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
|
4
4
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
5
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 };
|
|
@@ -4,9 +4,9 @@ import { n as detectWorkspaces } from "./package-manager-CClZtIHP.mjs";
|
|
|
4
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 { i as loadFormatter, n as generateChangelogEntry } from "./changelog-
|
|
8
|
-
import { c as
|
|
9
|
-
import { t as publishPackages } from "./publish-pipeline-
|
|
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";
|
|
10
10
|
//#region src/core/github-release.ts
|
|
11
11
|
/** Get the current HEAD commit SHA */
|
|
12
12
|
function getHeadSha(rootDir) {
|
|
@@ -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";
|
|
@@ -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)
|
|
@@ -3,8 +3,8 @@ import { a as loadConfig } from "./config-D13G4-R8.mjs";
|
|
|
3
3
|
import { t as discoverPackages } from "./workspace-BKOAMeki.mjs";
|
|
4
4
|
import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
|
|
5
5
|
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
6
|
-
import { t as assembleReleasePlan } from "./release-plan-
|
|
7
|
-
import { i as getCurrentBranch, r as getChangedFiles } from "./git-
|
|
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);
|
|
@@ -5,9 +5,9 @@ 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
7
|
import { r as readBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
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-
|
|
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);
|
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
|
|
package/dist/check-C80o_gJK.mjs
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { n as log, o as __toESM, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
-
import { a as loadConfig, o as loadPackageConfig, r as getBumpyDir } from "./config-D13G4-R8.mjs";
|
|
3
|
-
import { n as discoverWorkspace } from "./workspace-BKOAMeki.mjs";
|
|
4
|
-
import { r as readBumpFiles, t as filterBranchBumpFiles } from "./bump-file-CoaSxqne.mjs";
|
|
5
|
-
import { r as getChangedFiles } from "./git-D0__HP86.mjs";
|
|
6
|
-
import { t as require_picomatch } from "./picomatch-TGJi--_I.mjs";
|
|
7
|
-
import { relative } from "node:path";
|
|
8
|
-
//#region src/commands/check.ts
|
|
9
|
-
var import_picomatch = /* @__PURE__ */ __toESM(require_picomatch(), 1);
|
|
10
|
-
/**
|
|
11
|
-
* Local check: detect which packages have changed on this branch
|
|
12
|
-
* and verify they have corresponding bump files.
|
|
13
|
-
* Designed for pre-push hooks — no GitHub API needed.
|
|
14
|
-
*
|
|
15
|
-
* Default: at least one bump file must exist, uncovered packages are warned.
|
|
16
|
-
* --strict: every changed package must be covered.
|
|
17
|
-
* --no-fail: warn only, never exit 1.
|
|
18
|
-
*/
|
|
19
|
-
async function checkCommand(rootDir, opts = {}) {
|
|
20
|
-
const config = await loadConfig(rootDir);
|
|
21
|
-
const { packages } = await discoverWorkspace(rootDir, config);
|
|
22
|
-
const baseBranch = config.baseBranch;
|
|
23
|
-
const changedFiles = getChangedFiles(rootDir, baseBranch);
|
|
24
|
-
if (changedFiles.length === 0) {
|
|
25
|
-
log.info("No changed files detected.");
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
const { bumpFiles: allBumpFiles, errors: parseErrors } = await readBumpFiles(rootDir);
|
|
29
|
-
if (parseErrors.length > 0) {
|
|
30
|
-
for (const err of parseErrors) log.error(err);
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
const { branchBumpFiles, emptyBumpFileIds } = filterBranchBumpFiles(allBumpFiles, changedFiles, rootDir);
|
|
34
|
-
if (emptyBumpFileIds.length > 0) {
|
|
35
|
-
log.success("Empty bump file found — no releases needed.");
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const coveredPackages = /* @__PURE__ */ new Set();
|
|
39
|
-
for (const bf of branchBumpFiles) for (const release of bf.releases) coveredPackages.add(release.name);
|
|
40
|
-
const changedPackages = await findChangedPackages(changedFiles, packages, rootDir, config);
|
|
41
|
-
if (changedPackages.length === 0) {
|
|
42
|
-
log.info("No managed packages have changed.");
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const willFailNoBump = !opts.noFail;
|
|
46
|
-
if (branchBumpFiles.length === 0) {
|
|
47
|
-
(willFailNoBump ? log.error : log.warn)(`${changedPackages.length} changed package(s) missing bump files:\n`);
|
|
48
|
-
for (const name of changedPackages) console.log(` ${colorize(name, "yellow")}`);
|
|
49
|
-
console.log();
|
|
50
|
-
log.dim("Run `bumpy add` to create a bump file, or `bumpy add --empty` if no release is needed.");
|
|
51
|
-
log.dim("To adjust which files trigger change detection, set `changedFilePatterns` in .bumpy/_config.json.");
|
|
52
|
-
if (willFailNoBump) process.exit(1);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const missing = changedPackages.filter((name) => !coveredPackages.has(name));
|
|
56
|
-
if (missing.length === 0) {
|
|
57
|
-
log.success(`🐸 All ${changedPackages.length} changed package(s) have bump files.`);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const willFailUncovered = opts.strict && !opts.noFail;
|
|
61
|
-
(willFailUncovered ? log.error : log.warn)(`${missing.length} changed package(s) missing bump files:\n`);
|
|
62
|
-
for (const name of missing) console.log(` ${colorize(name, "yellow")}`);
|
|
63
|
-
if (branchBumpFiles.length > 0) {
|
|
64
|
-
console.log();
|
|
65
|
-
log.dim(`Existing bump files on this branch:`);
|
|
66
|
-
for (const bf of branchBumpFiles) log.dim(` ${getBumpyDir(rootDir)}/${bf.id}.md`);
|
|
67
|
-
}
|
|
68
|
-
console.log();
|
|
69
|
-
if (opts.strict) log.dim("Run `bumpy add` to create a bump file. Use bump type `none` for packages that changed but don't need a release.");
|
|
70
|
-
else log.dim("Run `bumpy add` to create a bump file, or `bumpy add --empty` if no release is needed.");
|
|
71
|
-
log.dim("To adjust which files trigger change detection, set `changedFilePatterns` in .bumpy/_config.json.");
|
|
72
|
-
if (willFailUncovered) process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
/** Map changed files to the packages they belong to */
|
|
75
|
-
async function findChangedPackages(changedFiles, packages, rootDir, config) {
|
|
76
|
-
const changed = /* @__PURE__ */ new Set();
|
|
77
|
-
const matchers = /* @__PURE__ */ new Map();
|
|
78
|
-
for (const [name, pkg] of packages) {
|
|
79
|
-
const patterns = (await loadPackageConfig(pkg.dir, config, name)).changedFilePatterns ?? config.changedFilePatterns;
|
|
80
|
-
matchers.set(name, (0, import_picomatch.default)(patterns));
|
|
81
|
-
}
|
|
82
|
-
for (const file of changedFiles) for (const [name, pkg] of packages) {
|
|
83
|
-
const pkgRelDir = relative(rootDir, pkg.dir);
|
|
84
|
-
if (file.startsWith(pkgRelDir + "/")) {
|
|
85
|
-
const relToPackage = file.slice(pkgRelDir.length + 1);
|
|
86
|
-
if (matchers.get(name)(relToPackage)) changed.add(name);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return [...changed];
|
|
90
|
-
}
|
|
91
|
-
//#endregion
|
|
92
|
-
export { checkCommand, findChangedPackages };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|