@varlock/bumpy 1.6.0 → 1.7.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.
Files changed (30) hide show
  1. package/dist/{add-u3h5BH8e.mjs → add-Dr1vFn9b.mjs} +9 -10
  2. package/dist/{ai-C66IfTzs.mjs → ai-BHoKuvHn.mjs} +2 -2
  3. package/dist/{apply-release-plan-DNpoi7cS.mjs → apply-release-plan-BRN29C3D.mjs} +3 -3
  4. package/dist/{bump-file-CoaSxqne.mjs → bump-file-4cnuDyfW.mjs} +110 -6
  5. package/dist/{changelog-_gBjowzN.mjs → changelog-C9JXdwaj.mjs} +3 -3
  6. package/dist/{changelog-github-B_e9JWku.mjs → changelog-github-CZcW184H.mjs} +2 -2
  7. package/dist/{check-B3M2S2wx.mjs → check-Dqm9ZU8T.mjs} +9 -6
  8. package/dist/{ci-h8s-soA6.mjs → ci-E1QXDnB_.mjs} +102 -16
  9. package/dist/{ci-setup-DWxrdSK6.mjs → ci-setup-Bbf96usW.mjs} +4 -4
  10. package/dist/{clack-CJT1JFFa.mjs → clack-CehaQZU6.mjs} +1 -1
  11. package/dist/cli.mjs +20 -16
  12. package/dist/{config-D13G4-R8.mjs → config-BcmlSJJd.mjs} +2 -2
  13. package/dist/{fs-DnDogVn-.mjs → fs-CBXKZhoU.mjs} +1 -1
  14. package/dist/{generate-CxKXOBNP.mjs → generate-0a_KR7tn.mjs} +7 -8
  15. package/dist/{git-ukq7VTuZ.mjs → git-DE46Je5V.mjs} +1 -1
  16. package/dist/index.mjs +6 -8
  17. package/dist/{init-CUIw0jg8.mjs → init-CY7OVZCX.mjs} +5 -5
  18. package/dist/{logger-C2dEe5Su.mjs → logger-BgksGFuf.mjs} +3 -1
  19. package/dist/{package-manager-CClZtIHP.mjs → package-manager-BQPwXwu5.mjs} +1 -1
  20. package/dist/{publish-CXJ0Ggkq.mjs → publish-D5OcYhC_.mjs} +74 -12
  21. package/dist/{publish-pipeline-C1slMaJV.mjs → publish-pipeline-ChiL1eRQ.mjs} +6 -6
  22. package/dist/{semver-DfQyVLM_.mjs → release-plan-M9TGZn2W.mjs} +249 -2
  23. package/dist/{shell-u3bYGxNy.mjs → shell-C8KgKnMQ.mjs} +1 -1
  24. package/dist/{status-lS56U6F_.mjs → status-CapkBv6n.mjs} +8 -9
  25. package/dist/{version-BjjnO2ii.mjs → version-Cz-p96lm.mjs} +8 -9
  26. package/package.json +1 -1
  27. package/dist/release-plan-C1Lz9rl_.mjs +0 -249
  28. package/dist/workspace-Yt7qwsML.mjs +0 -109
  29. /package/dist/{commit-message-3e4KhzFV.mjs → commit-message-BA1w19wq.mjs} +0 -0
  30. /package/dist/{names-CBy7d8K_.mjs → names-C-TuOPbd.mjs} +0 -0
@@ -1,249 +0,0 @@
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
- import { n as satisfies, t as bumpVersion } from "./semver-DfQyVLM_.mjs";
4
- //#region src/core/release-plan.ts
5
- /**
6
- * Build a release plan from pending bump files, the dependency graph, and config.
7
- * This is the core algorithm of bumpy.
8
- *
9
- * The propagation loop runs three phases until stable:
10
- * Phase A — fix out-of-range dependencies (always runs)
11
- * Phase B — enforce fixed/linked group constraints
12
- * Phase C — apply cascades and proactive propagation rules
13
- */
14
- function assembleReleasePlan(bumpFiles, packages, depGraph, config) {
15
- if (bumpFiles.length === 0) return {
16
- bumpFiles: [],
17
- releases: [],
18
- warnings: []
19
- };
20
- const planned = /* @__PURE__ */ new Map();
21
- const warnings = [];
22
- const cascadeOverrides = /* @__PURE__ */ new Map();
23
- for (const bf of bumpFiles) for (const release of bf.releases) {
24
- if (!packages.has(release.name)) continue;
25
- const bump = release.type;
26
- if (bump === "none") continue;
27
- const existing = planned.get(release.name);
28
- if (existing) {
29
- existing.type = maxBump(existing.type, bump);
30
- existing.bumpFiles.add(bf.id);
31
- } else planned.set(release.name, {
32
- type: bump,
33
- isDependencyBump: false,
34
- isCascadeBump: false,
35
- isGroupBump: false,
36
- bumpFiles: new Set([bf.id]),
37
- bumpSources: /* @__PURE__ */ new Map()
38
- });
39
- if (hasCascade(release)) {
40
- if (!cascadeOverrides.has(release.name)) cascadeOverrides.set(release.name, /* @__PURE__ */ new Map());
41
- const overrides = cascadeOverrides.get(release.name);
42
- for (const [pattern, bumpType] of Object.entries(release.cascade)) {
43
- const existing = overrides.get(pattern);
44
- overrides.set(pattern, maxBump(existing, bumpType));
45
- }
46
- }
47
- }
48
- let changed = true;
49
- let iterations = 0;
50
- const MAX_ITERATIONS = 100;
51
- while (changed && iterations < MAX_ITERATIONS) {
52
- changed = false;
53
- iterations++;
54
- for (const [pkgName, bump] of planned) {
55
- const pkg = packages.get(pkgName);
56
- const newVersion = bumpVersion(pkg.version, bump.type);
57
- const dependents = depGraph.getDependents(pkgName);
58
- for (const dep of dependents) {
59
- if (dep.depType === "devDependencies") continue;
60
- const currentVersion = pkg.version;
61
- if (satisfies(newVersion, dep.versionRange, currentVersion)) continue;
62
- let depBump;
63
- if (dep.depType === "peerDependencies") depBump = bump.type;
64
- else depBump = "patch";
65
- if (dep.depType === "peerDependencies" && depBump !== "patch" && bump.type !== "major") {
66
- let resolvedRange = dep.versionRange.replace(/^workspace:/, "");
67
- if (resolvedRange === "^" || resolvedRange === "~") resolvedRange = `${resolvedRange}${pkg.version}`;
68
- if (/^\^0(\.|$)/.test(resolvedRange)) warnings.push(`${dep.name} gets a ${depBump} bump because ${pkgName}@${newVersion} is out of range for its peer dep "${dep.versionRange}" (resolves to ${resolvedRange}). npm treats ^ on 0.x as minor-breaking. Consider using >=0.x ranges for pre-1.0 peer deps.`);
69
- }
70
- if (applyBump(planned, dep.name, depBump, true, false, pkgName)) changed = true;
71
- }
72
- }
73
- for (const group of config.fixed) {
74
- let groupBump;
75
- const groupSources = [];
76
- for (const nameOrGlob of group) for (const [name, bump] of planned) if (matchGlob(name, nameOrGlob)) {
77
- if (!groupBump || bumpLevel(bump.type) > bumpLevel(groupBump)) {
78
- groupBump = bump.type;
79
- groupSources.length = 0;
80
- groupSources.push(name);
81
- } else if (bump.type === groupBump) groupSources.push(name);
82
- }
83
- if (!groupBump) continue;
84
- for (const nameOrGlob of group) for (const [name] of packages) {
85
- if (!matchGlob(name, nameOrGlob)) continue;
86
- const existing = planned.get(name);
87
- if (existing) {
88
- const newType = maxBump(existing.type, groupBump);
89
- if (newType !== existing.type) {
90
- existing.type = newType;
91
- existing.isGroupBump = true;
92
- for (const src of groupSources) if (src !== name) existing.bumpSources.set(src, groupBump);
93
- changed = true;
94
- }
95
- } else {
96
- planned.set(name, {
97
- type: groupBump,
98
- isDependencyBump: false,
99
- isCascadeBump: false,
100
- isGroupBump: true,
101
- bumpFiles: /* @__PURE__ */ new Set(),
102
- bumpSources: new Map(groupSources.filter((s) => s !== name).map((s) => [s, groupBump]))
103
- });
104
- changed = true;
105
- }
106
- }
107
- }
108
- for (const group of config.linked) {
109
- let groupBump;
110
- const groupSources = [];
111
- for (const nameOrGlob of group) for (const [name, bump] of planned) if (matchGlob(name, nameOrGlob)) {
112
- if (!groupBump || bumpLevel(bump.type) > bumpLevel(groupBump)) {
113
- groupBump = bump.type;
114
- groupSources.length = 0;
115
- groupSources.push(name);
116
- } else if (bump.type === groupBump) groupSources.push(name);
117
- }
118
- if (!groupBump) continue;
119
- for (const nameOrGlob of group) for (const [name] of packages) {
120
- if (!matchGlob(name, nameOrGlob)) continue;
121
- const existing = planned.get(name);
122
- if (!existing) continue;
123
- const newType = maxBump(existing.type, groupBump);
124
- if (newType !== existing.type) {
125
- existing.type = newType;
126
- existing.isGroupBump = true;
127
- for (const src of groupSources) if (src !== name) existing.bumpSources.set(src, groupBump);
128
- changed = true;
129
- }
130
- }
131
- }
132
- if (config.updateInternalDependencies !== "out-of-range") for (const [pkgName, bump] of planned) {
133
- if (config.updateInternalDependencies === "minor" && bumpLevel(bump.type) < bumpLevel("minor")) continue;
134
- const bfOverrides = cascadeOverrides.get(pkgName);
135
- if (bfOverrides) for (const [pattern, cascadeBumpType] of bfOverrides) for (const [targetName] of packages) {
136
- if (!matchGlob(targetName, pattern)) continue;
137
- if (applyBump(planned, targetName, cascadeBumpType, false, true, pkgName)) changed = true;
138
- }
139
- const cascadeTo = packages.get(pkgName)?.bumpy?.cascadeTo;
140
- if (cascadeTo) for (const [pattern, rule] of Object.entries(cascadeTo)) {
141
- if (!shouldTrigger(bump.type, rule.trigger)) continue;
142
- const cascadeBump = rule.bumpAs === "match" ? bump.type : rule.bumpAs;
143
- for (const [targetName] of packages) {
144
- if (!matchGlob(targetName, pattern)) continue;
145
- if (applyBump(planned, targetName, cascadeBump, false, true, pkgName)) changed = true;
146
- }
147
- }
148
- const dependents = depGraph.getDependents(pkgName);
149
- for (const dep of dependents) {
150
- const rule = resolveRule(dep.name, dep.depType, packages, config);
151
- if (!rule) continue;
152
- if (!shouldTrigger(bump.type, rule.trigger)) continue;
153
- const depBump = rule.bumpAs === "match" ? bump.type : rule.bumpAs;
154
- if (applyBump(planned, dep.name, depBump, true, false, pkgName)) changed = true;
155
- }
156
- }
157
- else for (const [pkgName, bump] of planned) {
158
- const bfOverrides = cascadeOverrides.get(pkgName);
159
- if (bfOverrides) for (const [pattern, cascadeBumpType] of bfOverrides) for (const [targetName] of packages) {
160
- if (!matchGlob(targetName, pattern)) continue;
161
- if (applyBump(planned, targetName, cascadeBumpType, false, true, pkgName)) changed = true;
162
- }
163
- const cascadeTo = packages.get(pkgName)?.bumpy?.cascadeTo;
164
- if (cascadeTo) for (const [pattern, rule] of Object.entries(cascadeTo)) {
165
- if (!shouldTrigger(bump.type, rule.trigger)) continue;
166
- const cascadeBump = rule.bumpAs === "match" ? bump.type : rule.bumpAs;
167
- for (const [targetName] of packages) {
168
- if (!matchGlob(targetName, pattern)) continue;
169
- if (applyBump(planned, targetName, cascadeBump, false, true, pkgName)) changed = true;
170
- }
171
- }
172
- }
173
- }
174
- const releases = [];
175
- for (const [name, bump] of planned) {
176
- const pkg = packages.get(name);
177
- if (!pkg) continue;
178
- const newVersion = bumpVersion(pkg.version, bump.type);
179
- releases.push({
180
- name,
181
- type: bump.type,
182
- oldVersion: pkg.version,
183
- newVersion,
184
- bumpFiles: [...bump.bumpFiles],
185
- isDependencyBump: bump.isDependencyBump,
186
- isCascadeBump: bump.isCascadeBump,
187
- isGroupBump: bump.isGroupBump,
188
- bumpSources: [...bump.bumpSources].map(([srcName, contributedType]) => {
189
- const srcBump = planned.get(srcName);
190
- const srcPkg = packages.get(srcName);
191
- return {
192
- name: srcName,
193
- newVersion: srcPkg && srcBump ? bumpVersion(srcPkg.version, srcBump.type) : "unknown",
194
- bumpType: contributedType
195
- };
196
- })
197
- });
198
- }
199
- releases.sort((a, b) => a.name.localeCompare(b.name));
200
- for (const [name, pkg] of packages) for (const [depName, range] of Object.entries(pkg.peerDependencies)) if (range === "workspace:*" && packages.has(depName)) warnings.push(`${name} has peer dep "${depName}": "workspace:*" — this will be published as a fixed range which may not match your intent. Consider using "workspace:^" instead.`);
201
- return {
202
- bumpFiles,
203
- releases,
204
- warnings
205
- };
206
- }
207
- /** Apply a bump to a package, upgrading if already planned. Returns true if anything changed. */
208
- function applyBump(planned, name, type, isDependencyBump, isCascadeBump, sourcePackageName) {
209
- const existing = planned.get(name);
210
- if (existing) {
211
- const newType = maxBump(existing.type, type);
212
- if (newType === existing.type) return false;
213
- existing.type = newType;
214
- if (isDependencyBump) existing.isDependencyBump = true;
215
- if (isCascadeBump) existing.isCascadeBump = true;
216
- existing.bumpSources.set(sourcePackageName, type);
217
- return true;
218
- }
219
- planned.set(name, {
220
- type,
221
- isDependencyBump,
222
- isCascadeBump,
223
- isGroupBump: false,
224
- bumpFiles: /* @__PURE__ */ new Set(),
225
- bumpSources: new Map([[sourcePackageName, type]])
226
- });
227
- return true;
228
- }
229
- /** Check if a bump level meets the trigger threshold */
230
- function shouldTrigger(bumpType, trigger) {
231
- return bumpLevel(bumpType) >= bumpLevel(trigger);
232
- }
233
- /**
234
- * Resolve the dependency bump rule for a specific dependent + dep type.
235
- * Priority: per-package depType rules > global depType rules > defaults
236
- * Returns false if the rule is disabled.
237
- */
238
- function resolveRule(dependentName, depType, packages, config) {
239
- const dependent = packages.get(dependentName);
240
- if (dependent?.bumpy?.dependencyBumpRules && depType in dependent.bumpy.dependencyBumpRules) return dependent.bumpy.dependencyBumpRules[depType];
241
- if (depType in config.dependencyBumpRules) return config.dependencyBumpRules[depType];
242
- const defaultRule = DEFAULT_BUMP_RULES[depType];
243
- return defaultRule !== void 0 ? defaultRule : {
244
- trigger: "patch",
245
- bumpAs: "patch"
246
- };
247
- }
248
- //#endregion
249
- export { assembleReleasePlan as t };
@@ -1,109 +0,0 @@
1
- import { a as readJson, n as exists } from "./fs-DnDogVn-.mjs";
2
- import { i as isPackageManaged, o as loadPackageConfig } from "./config-D13G4-R8.mjs";
3
- import { n as detectWorkspaces } from "./package-manager-CClZtIHP.mjs";
4
- import { relative, resolve } from "node:path";
5
- import { readdir, stat } from "node:fs/promises";
6
- //#region src/core/workspace.ts
7
- /** Discover all workspace packages and catalogs in a monorepo or single-package repo */
8
- async function discoverWorkspace(rootDir, config) {
9
- const { globs, catalogs } = await detectWorkspaces(rootDir);
10
- const packages = /* @__PURE__ */ new Map();
11
- if (globs.length === 0) {
12
- const pkg = await loadWorkspacePackage(rootDir, rootDir, config);
13
- if (pkg && isPackageManaged(pkg.name, pkg.private, config, pkg.bumpy)) packages.set(pkg.name, pkg);
14
- } else for (const glob of globs) {
15
- const dirs = await resolveGlob(rootDir, glob);
16
- for (const dir of dirs) {
17
- const pkg = await loadWorkspacePackage(dir, rootDir, config);
18
- if (pkg) {
19
- if (!isPackageManaged(pkg.name, pkg.private, config, pkg.bumpy)) continue;
20
- packages.set(pkg.name, pkg);
21
- }
22
- }
23
- }
24
- return {
25
- packages,
26
- catalogs
27
- };
28
- }
29
- /** Convenience wrapper that returns just packages (backwards compat) */
30
- async function discoverPackages(rootDir, config) {
31
- const { packages } = await discoverWorkspace(rootDir, config);
32
- return packages;
33
- }
34
- /** Resolve a workspace glob pattern to directories containing package.json */
35
- async function resolveGlob(rootDir, pattern) {
36
- return expandGlob(rootDir, pattern.split("/"));
37
- }
38
- async function expandGlob(baseDir, parts) {
39
- if (parts.length === 0) {
40
- if (await exists(resolve(baseDir, "package.json"))) return [baseDir];
41
- return [];
42
- }
43
- const [current, ...rest] = parts;
44
- if (current === "*") {
45
- const entries = await safeReaddir(baseDir);
46
- const results = [];
47
- for (const entry of entries) {
48
- const entryPath = resolve(baseDir, entry);
49
- if (await isDirectory(entryPath)) results.push(...await expandGlob(entryPath, rest));
50
- }
51
- return results;
52
- } else if (current === "**") {
53
- const results = [];
54
- results.push(...await expandGlob(baseDir, rest));
55
- const entries = await safeReaddir(baseDir);
56
- for (const entry of entries) {
57
- if (entry.startsWith(".") || entry === "node_modules") continue;
58
- const entryPath = resolve(baseDir, entry);
59
- if (await isDirectory(entryPath)) results.push(...await expandGlob(entryPath, parts));
60
- }
61
- return results;
62
- } else {
63
- const next = resolve(baseDir, current);
64
- if (await isDirectory(next)) return expandGlob(next, rest);
65
- return [];
66
- }
67
- }
68
- async function safeReaddir(dir) {
69
- try {
70
- return await readdir(dir);
71
- } catch {
72
- return [];
73
- }
74
- }
75
- async function isDirectory(path) {
76
- try {
77
- return (await stat(path)).isDirectory();
78
- } catch {
79
- return false;
80
- }
81
- }
82
- async function loadWorkspacePackage(dir, rootDir, config) {
83
- const pkgPath = resolve(dir, "package.json");
84
- if (!await exists(pkgPath)) return null;
85
- let pkg;
86
- try {
87
- pkg = await readJson(pkgPath);
88
- } catch {
89
- return null;
90
- }
91
- const name = pkg.name;
92
- if (!name) return null;
93
- const bumpy = await loadPackageConfig(dir, config, name);
94
- return {
95
- name,
96
- version: pkg.version || "0.0.0",
97
- dir: resolve(dir),
98
- relativeDir: relative(rootDir, dir) || ".",
99
- packageJson: pkg,
100
- private: !!pkg.private,
101
- dependencies: pkg.dependencies || {},
102
- devDependencies: pkg.devDependencies || {},
103
- peerDependencies: pkg.peerDependencies || {},
104
- optionalDependencies: pkg.optionalDependencies || {},
105
- bumpy
106
- };
107
- }
108
- //#endregion
109
- export { discoverWorkspace as n, discoverPackages as t };
File without changes