@varlock/bumpy 1.13.1 → 1.14.0-rc.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 +23 -140
- package/config-schema.json +43 -0
- package/dist/{add-5how2kia.mjs → add-C9rU_89s.mjs} +4 -4
- package/dist/{apply-release-plan-DD2R7SL2.mjs → apply-release-plan-DxTsUSqa.mjs} +11 -2
- package/dist/{bump-file-B7hmXZlB.mjs → bump-file-mRJeReRJ.mjs} +43 -8
- package/dist/{changelog-CbaET5V6.mjs → changelog-DuFhnJRO.mjs} +3 -3
- package/dist/{changelog-github-DXDnWkrB.mjs → changelog-github-jLOtwuWj.mjs} +2 -2
- package/dist/channels-CFXZkyGd.mjs +75 -0
- package/dist/{check-CsF0zh8r.mjs → check-DIl9Dz68.mjs} +18 -6
- package/dist/{ci-CIamssoq.mjs → ci-hO7tAbCN.mjs} +391 -23
- package/dist/cli.mjs +32 -17
- package/dist/{config-D_4GYDJi.mjs → config-0we4ISZX.mjs} +5 -1
- package/dist/{generate-CvCvUaRV.mjs → generate-B2OMt_64.mjs} +3 -3
- package/dist/{git-DJJ64SW9.mjs → git-DAWj8LyV.mjs} +25 -4
- package/dist/index.d.mts +46 -4
- package/dist/index.mjs +7 -7
- package/dist/prerelease-Blnk8FE1.mjs +186 -0
- package/dist/{publish-h6rM58Cq.mjs → publish-Cz0e4KYT.mjs} +164 -19
- package/dist/{publish-pipeline-DSj14dW6.mjs → publish-pipeline-BD8mLbL9.mjs} +18 -3
- package/dist/{release-plan-mK7iGeGq.mjs → release-plan-C84pcBi-.mjs} +12 -17
- package/dist/status-CrMvvvNy.mjs +232 -0
- package/dist/{types-Bkh-igOJ.mjs → types-lpiG-Zxh.mjs} +1 -0
- package/dist/version-BUUf8vKC.mjs +192 -0
- package/package.json +1 -1
- package/dist/status-BbsDr6t7.mjs +0 -129
- package/dist/version-Cm0nRAFF.mjs +0 -123
- /package/dist/{commit-message-CSWVKPJ-.mjs → commit-message-BwsowSds.mjs} +0 -0
- /package/dist/{init-BCkm6Nfa.mjs → init-DkAY5hjc.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-BgksGFuf.mjs";
|
|
3
|
-
import { n as findRoot } from "./config-
|
|
3
|
+
import { n as findRoot } from "./config-0we4ISZX.mjs";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
const args = process.argv.slice(2);
|
|
6
6
|
const command = args[0];
|
|
@@ -25,13 +25,13 @@ async function main() {
|
|
|
25
25
|
switch (command) {
|
|
26
26
|
case "init": {
|
|
27
27
|
const rootDir = await findRoot();
|
|
28
|
-
const { initCommand } = await import("./init-
|
|
28
|
+
const { initCommand } = await import("./init-DkAY5hjc.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-C9rU_89s.mjs");
|
|
35
35
|
await addCommand(rootDir, {
|
|
36
36
|
packages: flags.packages,
|
|
37
37
|
message: flags.message,
|
|
@@ -43,25 +43,29 @@ async function main() {
|
|
|
43
43
|
}
|
|
44
44
|
case "status": {
|
|
45
45
|
const rootDir = await findRoot();
|
|
46
|
-
const { statusCommand } = await import("./status-
|
|
46
|
+
const { statusCommand } = await import("./status-CrMvvvNy.mjs");
|
|
47
47
|
await statusCommand(rootDir, {
|
|
48
48
|
json: flags.json === true,
|
|
49
49
|
packagesOnly: flags.packages === true,
|
|
50
50
|
bumpType: flags.bump,
|
|
51
51
|
filter: flags.filter,
|
|
52
|
-
verbose: flags.verbose === true
|
|
52
|
+
verbose: flags.verbose === true,
|
|
53
|
+
channel: flags.channel
|
|
53
54
|
});
|
|
54
55
|
break;
|
|
55
56
|
}
|
|
56
57
|
case "version": {
|
|
57
58
|
const rootDir = await findRoot();
|
|
58
|
-
const { versionCommand } = await import("./version-
|
|
59
|
-
await versionCommand(rootDir, {
|
|
59
|
+
const { versionCommand } = await import("./version-BUUf8vKC.mjs");
|
|
60
|
+
await versionCommand(rootDir, {
|
|
61
|
+
commit: flags.commit === true,
|
|
62
|
+
channel: flags.channel
|
|
63
|
+
});
|
|
60
64
|
break;
|
|
61
65
|
}
|
|
62
66
|
case "generate": {
|
|
63
67
|
const rootDir = await findRoot();
|
|
64
|
-
const { generateCommand } = await import("./generate-
|
|
68
|
+
const { generateCommand } = await import("./generate-B2OMt_64.mjs");
|
|
65
69
|
await generateCommand(rootDir, {
|
|
66
70
|
from: flags.from,
|
|
67
71
|
dryRun: flags["dry-run"] === true,
|
|
@@ -71,7 +75,7 @@ async function main() {
|
|
|
71
75
|
}
|
|
72
76
|
case "check": {
|
|
73
77
|
const rootDir = await findRoot();
|
|
74
|
-
const { checkCommand } = await import("./check-
|
|
78
|
+
const { checkCommand } = await import("./check-DIl9Dz68.mjs").then((n) => n.t);
|
|
75
79
|
const hookValue = flags.hook;
|
|
76
80
|
if (hookValue && hookValue !== "pre-commit" && hookValue !== "pre-push") {
|
|
77
81
|
log.error(`Invalid --hook value "${hookValue}". Expected "pre-commit" or "pre-push".`);
|
|
@@ -80,7 +84,8 @@ async function main() {
|
|
|
80
84
|
await checkCommand(rootDir, {
|
|
81
85
|
strict: flags.strict === true,
|
|
82
86
|
noFail: flags["no-fail"] === true,
|
|
83
|
-
hook: hookValue
|
|
87
|
+
hook: hookValue,
|
|
88
|
+
base: flags.base
|
|
84
89
|
});
|
|
85
90
|
break;
|
|
86
91
|
}
|
|
@@ -89,17 +94,17 @@ async function main() {
|
|
|
89
94
|
const subcommand = args[1];
|
|
90
95
|
const ciFlags = parseFlags(args.slice(2));
|
|
91
96
|
if (subcommand === "check") {
|
|
92
|
-
const { ciCheckCommand } = await import("./ci-
|
|
97
|
+
const { ciCheckCommand } = await import("./ci-hO7tAbCN.mjs");
|
|
93
98
|
await ciCheckCommand(rootDir, {
|
|
94
99
|
comment: ciFlags.comment !== void 0 ? ciFlags.comment === true : void 0,
|
|
95
100
|
strict: ciFlags.strict === true,
|
|
96
101
|
noFail: ciFlags["no-fail"] === true
|
|
97
102
|
});
|
|
98
103
|
} else if (subcommand === "plan") {
|
|
99
|
-
const { ciPlanCommand } = await import("./ci-
|
|
104
|
+
const { ciPlanCommand } = await import("./ci-hO7tAbCN.mjs");
|
|
100
105
|
await ciPlanCommand(rootDir);
|
|
101
106
|
} else if (subcommand === "release") {
|
|
102
|
-
const { ciReleaseCommand } = await import("./ci-
|
|
107
|
+
const { ciReleaseCommand } = await import("./ci-hO7tAbCN.mjs");
|
|
103
108
|
const expectModeFlag = ciFlags["expect-mode"];
|
|
104
109
|
const autoPublishFlag = ciFlags["auto-publish"] === true;
|
|
105
110
|
if (expectModeFlag !== void 0 && expectModeFlag !== "version-pr" && expectModeFlag !== "publish") {
|
|
@@ -127,12 +132,13 @@ async function main() {
|
|
|
127
132
|
}
|
|
128
133
|
case "publish": {
|
|
129
134
|
const rootDir = await findRoot();
|
|
130
|
-
const { publishCommand } = await import("./publish-
|
|
135
|
+
const { publishCommand } = await import("./publish-Cz0e4KYT.mjs");
|
|
131
136
|
await publishCommand(rootDir, {
|
|
132
137
|
dryRun: flags["dry-run"] === true,
|
|
133
138
|
tag: flags.tag,
|
|
134
139
|
noPush: flags["no-push"] === true,
|
|
135
|
-
filter: flags.filter
|
|
140
|
+
filter: flags.filter,
|
|
141
|
+
channel: flags.channel
|
|
136
142
|
});
|
|
137
143
|
break;
|
|
138
144
|
}
|
|
@@ -151,7 +157,7 @@ async function main() {
|
|
|
151
157
|
}
|
|
152
158
|
case "--version":
|
|
153
159
|
case "-v":
|
|
154
|
-
console.log(`bumpy 1.13.
|
|
160
|
+
console.log(`bumpy 1.13.2`);
|
|
155
161
|
break;
|
|
156
162
|
case "help":
|
|
157
163
|
case "--help":
|
|
@@ -171,7 +177,7 @@ async function main() {
|
|
|
171
177
|
}
|
|
172
178
|
function printHelp() {
|
|
173
179
|
console.log(`
|
|
174
|
-
${colorize(`🐸 bumpy v1.13.
|
|
180
|
+
${colorize(`🐸 bumpy v1.13.2`, "bold")} - Modern monorepo versioning
|
|
175
181
|
|
|
176
182
|
Usage: bumpy <command> [options]
|
|
177
183
|
|
|
@@ -186,8 +192,11 @@ function printHelp() {
|
|
|
186
192
|
--strict Fail if any changed package is uncovered (default: only fail if no bump files at all)
|
|
187
193
|
--no-fail Warn only, never exit 1
|
|
188
194
|
--hook <context> Hook context: "pre-commit" or "pre-push" (controls which bump files count)
|
|
195
|
+
--base <branch> Branch to compare against (default: baseBranch; use the channel branch for channel PRs)
|
|
189
196
|
version [--commit] Apply bump files and bump versions
|
|
197
|
+
(on a channel branch: moves pending bump files into .bumpy/<channel>/)
|
|
190
198
|
publish Publish versioned packages
|
|
199
|
+
(on a channel branch: derives prerelease versions and publishes to the channel dist-tag)
|
|
191
200
|
ci check PR check — report pending releases, comment on PR
|
|
192
201
|
ci plan Report what ci release would do (JSON + GitHub Actions outputs)
|
|
193
202
|
ci release Release — create version PR or auto-publish
|
|
@@ -211,12 +220,18 @@ function printHelp() {
|
|
|
211
220
|
--bump <types> Filter by bump type (e.g., "major", "minor,patch")
|
|
212
221
|
--filter <names> Filter by package name/glob (e.g., "@myorg/*")
|
|
213
222
|
--verbose Show bump file details
|
|
223
|
+
--channel <name> Show channel status (default: inferred from the current branch)
|
|
214
224
|
|
|
215
225
|
Publish options:
|
|
216
226
|
--dry-run Preview without publishing
|
|
217
227
|
--tag <tag> npm dist-tag (e.g., "next", "beta")
|
|
218
228
|
--no-push Skip pushing git tags to remote
|
|
219
229
|
--filter <names> Publish only matching packages (e.g., "@myorg/*")
|
|
230
|
+
--channel <name> Publish a prerelease channel (default: inferred from the current branch)
|
|
231
|
+
|
|
232
|
+
Version options:
|
|
233
|
+
--commit Create a git commit with the version changes
|
|
234
|
+
--channel <name> Channel override (default: inferred from the current branch)
|
|
220
235
|
|
|
221
236
|
CI check options:
|
|
222
237
|
--comment Force PR comment on/off (auto-detected in CI)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as __exportAll } from "./logger-BgksGFuf.mjs";
|
|
2
2
|
import { a as readJson, n as exists, o as readJsonc } from "./fs-CBXKZhoU.mjs";
|
|
3
|
-
import { l as normalizeCascadeConfig, r as DEFAULT_CONFIG } from "./types-
|
|
3
|
+
import { l as normalizeCascadeConfig, r as DEFAULT_CONFIG } from "./types-lpiG-Zxh.mjs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
//#region src/core/config.ts
|
|
6
6
|
var config_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -89,6 +89,10 @@ function mergeConfig(defaults, user) {
|
|
|
89
89
|
packages: {
|
|
90
90
|
...defaults.packages,
|
|
91
91
|
...user.packages
|
|
92
|
+
},
|
|
93
|
+
channels: {
|
|
94
|
+
...defaults.channels,
|
|
95
|
+
...user.channels
|
|
92
96
|
}
|
|
93
97
|
};
|
|
94
98
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as log, t as colorize } from "./logger-BgksGFuf.mjs";
|
|
2
2
|
import { t as ensureDir } from "./fs-CBXKZhoU.mjs";
|
|
3
|
-
import { a as loadConfig, r as getBumpyDir } from "./config-
|
|
4
|
-
import {
|
|
3
|
+
import { a as loadConfig, r as getBumpyDir } from "./config-0we4ISZX.mjs";
|
|
4
|
+
import { o as writeBumpFile, s as discoverPackages } from "./bump-file-mRJeReRJ.mjs";
|
|
5
5
|
import { s as tryRunArgs } from "./shell-C8KgKnMQ.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { c as getFilesChangedInCommit, i as getBranchCommits } from "./git-DAWj8LyV.mjs";
|
|
7
7
|
import { n as slugify, t as randomName } from "./names-COooXAFg.mjs";
|
|
8
8
|
import { relative } from "node:path";
|
|
9
9
|
//#region src/commands/generate.ts
|
|
@@ -8,13 +8,23 @@ function createTag(tag, opts) {
|
|
|
8
8
|
tag
|
|
9
9
|
], opts);
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Force-push a single tag to origin, using BUMPY_GH_TOKEN if available.
|
|
13
|
+
*
|
|
14
|
+
* Force is required because `gh release create --draft --target SHA` creates
|
|
15
|
+
* the tag on the remote at draft-creation time. If a previous publish attempt
|
|
16
|
+
* failed and HEAD has since moved, the remote tag points at the stale SHA —
|
|
17
|
+
* `git push --tags` would reject. The caller is responsible for ensuring the
|
|
18
|
+
* local tag is at the correct SHA (i.e. only call after a successful publish).
|
|
19
|
+
*/
|
|
20
|
+
function forcePushTag(tag, opts) {
|
|
13
21
|
withGitToken(opts?.cwd, () => {
|
|
14
22
|
runArgs([
|
|
15
23
|
"git",
|
|
16
24
|
"push",
|
|
17
|
-
"
|
|
25
|
+
"origin",
|
|
26
|
+
`refs/tags/${tag}`,
|
|
27
|
+
"--force"
|
|
18
28
|
], opts);
|
|
19
29
|
});
|
|
20
30
|
}
|
|
@@ -259,5 +269,16 @@ function getFileStatuses(dir, opts) {
|
|
|
259
269
|
}
|
|
260
270
|
return statuses;
|
|
261
271
|
}
|
|
272
|
+
/** Get all tags matching a pattern */
|
|
273
|
+
function listTags(pattern, opts) {
|
|
274
|
+
const result = tryRunArgs([
|
|
275
|
+
"git",
|
|
276
|
+
"tag",
|
|
277
|
+
"-l",
|
|
278
|
+
pattern
|
|
279
|
+
], opts);
|
|
280
|
+
if (!result) return [];
|
|
281
|
+
return result.split("\n").filter(Boolean);
|
|
282
|
+
}
|
|
262
283
|
//#endregion
|
|
263
|
-
export {
|
|
284
|
+
export { getChangedFiles as a, getFilesChangedInCommit as c, readFileAtRef as d, tagExists as f, getBranchCommits as i, hasUncommittedChanges as l, forcePushTag as n, getCurrentBranch as o, withGitToken as p, getBaseCompareRef as r, getFileStatuses as s, createTag as t, listTags as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -53,9 +53,30 @@ interface PublishConfig {
|
|
|
53
53
|
*/
|
|
54
54
|
npmStaged: boolean;
|
|
55
55
|
}
|
|
56
|
+
interface ChannelConfig {
|
|
57
|
+
/** Branch that triggers this channel (required) */
|
|
58
|
+
branch: string;
|
|
59
|
+
/** Version suffix (preid), e.g. "rc" → 1.2.0-rc.0. Defaults to the channel name. */
|
|
60
|
+
preid?: string;
|
|
61
|
+
/** npm dist-tag for publishes. Defaults to the channel name. */
|
|
62
|
+
tag?: string;
|
|
63
|
+
/** Release PR overrides for this channel */
|
|
64
|
+
versionPr?: {
|
|
65
|
+
title?: string;
|
|
66
|
+
branch?: string; /** Enable auto-merge on the release PR */
|
|
67
|
+
automerge?: boolean;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
56
70
|
interface BumpyConfig {
|
|
57
71
|
baseBranch: string;
|
|
58
72
|
access: 'public' | 'restricted';
|
|
73
|
+
/**
|
|
74
|
+
* Prerelease channels, keyed by channel name. Each maps a long-lived branch
|
|
75
|
+
* to a prerelease line (version suffix + npm dist-tag). Shipped bump files
|
|
76
|
+
* are tracked in `.bumpy/<name>/`. Prerelease versions are never committed —
|
|
77
|
+
* they are derived from bump files, the registry, and git tags at publish time.
|
|
78
|
+
*/
|
|
79
|
+
channels: Record<string, ChannelConfig>;
|
|
59
80
|
/**
|
|
60
81
|
* Customize the commit message used when versioning.
|
|
61
82
|
* A string starting with "./" is treated as a path to a module that exports
|
|
@@ -136,6 +157,8 @@ interface BumpFile {
|
|
|
136
157
|
id: string;
|
|
137
158
|
releases: BumpFileRelease[];
|
|
138
159
|
summary: string;
|
|
160
|
+
/** Channel directory this file lives in (`.bumpy/<channel>/`), if any. Undefined = `.bumpy/` root. */
|
|
161
|
+
channel?: string;
|
|
139
162
|
}
|
|
140
163
|
interface WorkspacePackage {
|
|
141
164
|
name: string;
|
|
@@ -219,8 +242,15 @@ interface ReadBumpFilesResult {
|
|
|
219
242
|
bumpFiles: BumpFile[];
|
|
220
243
|
errors: string[];
|
|
221
244
|
}
|
|
222
|
-
|
|
223
|
-
|
|
245
|
+
interface ReadBumpFilesOptions {
|
|
246
|
+
/**
|
|
247
|
+
* Channel names whose `.bumpy/<name>/` subdirectories should also be read.
|
|
248
|
+
* Files from those dirs get their `channel` field set; root files don't.
|
|
249
|
+
*/
|
|
250
|
+
channels?: string[];
|
|
251
|
+
}
|
|
252
|
+
/** Read all bump files from .bumpy/ (and optionally channel subdirs), sorted by git creation order */
|
|
253
|
+
declare function readBumpFiles(rootDir: string, opts?: ReadBumpFilesOptions): Promise<ReadBumpFilesResult>;
|
|
224
254
|
interface BumpFileParseResult {
|
|
225
255
|
bumpFile: BumpFile | null;
|
|
226
256
|
errors: string[];
|
|
@@ -240,7 +270,19 @@ declare function writeBumpFile(rootDir: string, filename: string, releases: Bump
|
|
|
240
270
|
* Phase B — enforce fixed/linked group constraints
|
|
241
271
|
* Phase C — apply cascades and proactive propagation rules
|
|
242
272
|
*/
|
|
243
|
-
|
|
273
|
+
interface AssemblePlanOptions {
|
|
274
|
+
/**
|
|
275
|
+
* Prerelease preid for channel plans (e.g. "rc"). When set, Phase A checks range
|
|
276
|
+
* satisfaction against `<target>-<preid>.0` instead of the stable target. Since a
|
|
277
|
+
* prerelease never satisfies a normal range (`^1.0.0` doesn't match `1.5.0-rc.0`),
|
|
278
|
+
* every dependent of a bumped package goes out of range and joins the cycle —
|
|
279
|
+
* required so consumers can actually install the cycle together from the dist-tag.
|
|
280
|
+
* Planned versions remain stable targets; the prerelease suffix is applied later
|
|
281
|
+
* from the registry floor.
|
|
282
|
+
*/
|
|
283
|
+
prereleasePreid?: string;
|
|
284
|
+
}
|
|
285
|
+
declare function assembleReleasePlan(bumpFiles: BumpFile[], packages: Map<string, WorkspacePackage>, depGraph: DependencyGraph, config: BumpyConfig, opts?: AssemblePlanOptions): ReleasePlan;
|
|
244
286
|
//#endregion
|
|
245
287
|
//#region src/core/apply-release-plan.d.ts
|
|
246
288
|
/** Apply the release plan: bump versions, update changelogs, delete bump files */
|
|
@@ -322,4 +364,4 @@ interface PublishResult {
|
|
|
322
364
|
*/
|
|
323
365
|
declare function publishPackages(releasePlan: ReleasePlan, packages: Map<string, WorkspacePackage>, depGraph: DependencyGraph, config: BumpyConfig, rootDir: string, opts?: PublishOptions, catalogs?: CatalogMap, detectedPm?: PackageManager): Promise<PublishResult>;
|
|
324
366
|
//#endregion
|
|
325
|
-
export { BUMP_LEVELS, BumpFile, type BumpFileParseResult, BumpFileRelease, BumpFileReleaseCascade, BumpFileReleaseSimple, BumpType, BumpTypeWithNone, BumpyConfig, CascadeConfig, CascadeRule, type ChangelogContext, type ChangelogFormatter, DEFAULT_BUMP_RULES, DEFAULT_CONFIG, DEFAULT_PUBLISH_CONFIG, DEP_TYPES, DepType, DependencyBumpRule, DependencyGraph, DependentInfo, type GithubChangelogOptions, PackageConfig, PackageManager, PlannedRelease, PublishConfig, type ReadBumpFilesResult, ReleasePlan, WorkspacePackage, applyReleasePlan, assembleReleasePlan, bumpLevel, bumpVersion, defaultFormatter, discoverPackages, findRoot, generateChangelogEntry, getBumpyDir, hasCascade, loadConfig, loadFormatter, matchGlob, maxBump, normalizeCascadeConfig, parseBumpFile, prependToChangelog, publishPackages, readBumpFiles, satisfies, stripProtocol, writeBumpFile };
|
|
367
|
+
export { BUMP_LEVELS, BumpFile, type BumpFileParseResult, BumpFileRelease, BumpFileReleaseCascade, BumpFileReleaseSimple, BumpType, BumpTypeWithNone, BumpyConfig, CascadeConfig, CascadeRule, type ChangelogContext, type ChangelogFormatter, ChannelConfig, DEFAULT_BUMP_RULES, DEFAULT_CONFIG, DEFAULT_PUBLISH_CONFIG, DEP_TYPES, DepType, DependencyBumpRule, DependencyGraph, DependentInfo, type GithubChangelogOptions, PackageConfig, PackageManager, PlannedRelease, PublishConfig, type ReadBumpFilesResult, ReleasePlan, WorkspacePackage, applyReleasePlan, assembleReleasePlan, bumpLevel, bumpVersion, defaultFormatter, discoverPackages, findRoot, generateChangelogEntry, getBumpyDir, hasCascade, loadConfig, loadFormatter, matchGlob, maxBump, normalizeCascadeConfig, parseBumpFile, prependToChangelog, publishPackages, readBumpFiles, satisfies, stripProtocol, writeBumpFile };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as DEP_TYPES, c as maxBump, i as DEFAULT_PUBLISH_CONFIG, l as normalizeCascadeConfig, 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 {
|
|
4
|
-
import {
|
|
5
|
-
import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry, t as defaultFormatter } from "./changelog-
|
|
6
|
-
import { t as applyReleasePlan } from "./apply-release-plan-
|
|
7
|
-
import { t as publishPackages } from "./publish-pipeline-
|
|
1
|
+
import { a as DEP_TYPES, c as maxBump, i as DEFAULT_PUBLISH_CONFIG, l as normalizeCascadeConfig, n as DEFAULT_BUMP_RULES, o as bumpLevel, r as DEFAULT_CONFIG, s as hasCascade, t as BUMP_LEVELS } from "./types-lpiG-Zxh.mjs";
|
|
2
|
+
import { a as loadConfig, n as findRoot, r as getBumpyDir, s as matchGlob } from "./config-0we4ISZX.mjs";
|
|
3
|
+
import { i as readBumpFiles, o as writeBumpFile, r as parseBumpFile, s as discoverPackages } from "./bump-file-mRJeReRJ.mjs";
|
|
4
|
+
import { i as stripProtocol, n as bumpVersion, o as DependencyGraph, r as satisfies, t as assembleReleasePlan } from "./release-plan-C84pcBi-.mjs";
|
|
5
|
+
import { a as prependToChangelog, i as loadFormatter, n as generateChangelogEntry, t as defaultFormatter } from "./changelog-DuFhnJRO.mjs";
|
|
6
|
+
import { t as applyReleasePlan } from "./apply-release-plan-DxTsUSqa.mjs";
|
|
7
|
+
import { t as publishPackages } from "./publish-pipeline-BD8mLbL9.mjs";
|
|
8
8
|
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, normalizeCascadeConfig, parseBumpFile, prependToChangelog, publishPackages, readBumpFiles, satisfies, stripProtocol, writeBumpFile };
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { s as __toESM } from "./logger-BgksGFuf.mjs";
|
|
2
|
+
import { f as writeText, l as updateJsonFields, s as readText, u as updateJsonNestedField } from "./fs-CBXKZhoU.mjs";
|
|
3
|
+
import { a as require_semver } from "./release-plan-C84pcBi-.mjs";
|
|
4
|
+
import { r as runArgsAsync, s as tryRunArgs } from "./shell-C8KgKnMQ.mjs";
|
|
5
|
+
import { u as listTags } from "./git-DAWj8LyV.mjs";
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
//#region src/core/prerelease.ts
|
|
8
|
+
var import_semver = /* @__PURE__ */ __toESM(require_semver(), 1);
|
|
9
|
+
/**
|
|
10
|
+
* Extract existing prerelease counters for a target+preid from a list of published versions.
|
|
11
|
+
* Only exact `<target>-<preid>.<N>` versions count — other preids and targets are ignored.
|
|
12
|
+
*/
|
|
13
|
+
function extractPrereleaseCounters(versions, target, preid) {
|
|
14
|
+
const counters = [];
|
|
15
|
+
for (const v of versions) {
|
|
16
|
+
const parsed = import_semver.default.parse(v);
|
|
17
|
+
if (!parsed) continue;
|
|
18
|
+
if (`${parsed.major}.${parsed.minor}.${parsed.patch}` !== target) continue;
|
|
19
|
+
if (parsed.prerelease.length !== 2) continue;
|
|
20
|
+
if (parsed.prerelease[0] !== preid) continue;
|
|
21
|
+
const n = parsed.prerelease[1];
|
|
22
|
+
if (typeof n === "number") counters.push(n);
|
|
23
|
+
}
|
|
24
|
+
return counters;
|
|
25
|
+
}
|
|
26
|
+
/** Compute the next prerelease version: `<target>-<preid>.<max existing counter + 1>` */
|
|
27
|
+
function nextPrereleaseVersion(target, preid, existingCounters) {
|
|
28
|
+
return `${target}-${preid}.${existingCounters.length > 0 ? Math.max(...existingCounters) + 1 : 0}`;
|
|
29
|
+
}
|
|
30
|
+
/** Fetch all published versions of a package from the registry */
|
|
31
|
+
async function fetchPublishedVersions(name, registry) {
|
|
32
|
+
const args = [
|
|
33
|
+
"npm",
|
|
34
|
+
"info",
|
|
35
|
+
name,
|
|
36
|
+
"versions",
|
|
37
|
+
"--json"
|
|
38
|
+
];
|
|
39
|
+
if (registry) args.push("--registry", registry);
|
|
40
|
+
try {
|
|
41
|
+
const raw = await runArgsAsync(args);
|
|
42
|
+
const parsed = JSON.parse(raw);
|
|
43
|
+
if (Array.isArray(parsed)) return parsed.filter((v) => typeof v === "string");
|
|
44
|
+
if (typeof parsed === "string") return [parsed];
|
|
45
|
+
return [];
|
|
46
|
+
} catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Fetch the gitHead recorded for a published version (set by npm publish from a git checkout) */
|
|
51
|
+
async function fetchGitHead(name, version, registry) {
|
|
52
|
+
const args = [
|
|
53
|
+
"npm",
|
|
54
|
+
"info",
|
|
55
|
+
`${name}@${version}`,
|
|
56
|
+
"gitHead"
|
|
57
|
+
];
|
|
58
|
+
if (registry) args.push("--registry", registry);
|
|
59
|
+
try {
|
|
60
|
+
const sha = (await runArgsAsync(args)).trim();
|
|
61
|
+
return /^[0-9a-f]{40}$/.test(sha) ? sha : null;
|
|
62
|
+
} catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Whether a package publishes through the npm registry (vs custom command / git-tag tracking) */
|
|
67
|
+
function usesNpmRegistry(pkg) {
|
|
68
|
+
return !pkg.bumpy?.publishCommand && !pkg.bumpy?.skipNpmPublish && !pkg.private;
|
|
69
|
+
}
|
|
70
|
+
/** Query published prerelease state for one package at a target version */
|
|
71
|
+
async function getPublishedPrereleaseState(pkg, target, preid, rootDir) {
|
|
72
|
+
if (usesNpmRegistry(pkg)) {
|
|
73
|
+
const versions = await fetchPublishedVersions(pkg.name, pkg.bumpy?.registry);
|
|
74
|
+
return {
|
|
75
|
+
counters: extractPrereleaseCounters(versions, target, preid),
|
|
76
|
+
stablePublished: versions.includes(target)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
counters: extractPrereleaseCounters(listTags(`${pkg.name}@${target}-${preid}.*`, { cwd: rootDir }).map((t) => t.slice(pkg.name.length + 1)), target, preid),
|
|
81
|
+
stablePublished: listTags(`${pkg.name}@${target}`, { cwd: rootDir }).length > 0
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Transform a stable release plan (targets computed from bump files) into a channel
|
|
86
|
+
* prerelease plan: each release's newVersion becomes `<target>-<preid>.<N>` with N
|
|
87
|
+
* derived from the registry floor.
|
|
88
|
+
*
|
|
89
|
+
* Idempotency: if a package's latest published prerelease for this target records a
|
|
90
|
+
* gitHead equal to HEAD (or, for non-npm packages, its tag points at HEAD), the package
|
|
91
|
+
* was already published from this exact commit — it is skipped rather than re-counted.
|
|
92
|
+
*/
|
|
93
|
+
async function buildChannelReleasePlan(stablePlan, channel, packages, rootDir, opts = {}) {
|
|
94
|
+
const headSha = tryRunArgs([
|
|
95
|
+
"git",
|
|
96
|
+
"rev-parse",
|
|
97
|
+
"HEAD"
|
|
98
|
+
], { cwd: rootDir });
|
|
99
|
+
const warnings = [...stablePlan.warnings];
|
|
100
|
+
const alreadyPublished = [];
|
|
101
|
+
const releases = [];
|
|
102
|
+
await Promise.all(stablePlan.releases.map(async (release) => {
|
|
103
|
+
const pkg = packages.get(release.name);
|
|
104
|
+
if (!pkg) return;
|
|
105
|
+
if (pkg.private && !pkg.bumpy?.publishCommand) return;
|
|
106
|
+
const target = release.newVersion;
|
|
107
|
+
const state = await getPublishedPrereleaseState(pkg, target, channel.preid, rootDir);
|
|
108
|
+
if (state.stablePublished) warnings.push(`${release.name}@${target} is already published as a stable release — merge ${target}'s release into the "${channel.branch}" branch so the cycle retargets.`);
|
|
109
|
+
if (!opts.forDisplay && state.counters.length > 0 && headSha) {
|
|
110
|
+
const latest = `${target}-${channel.preid}.${Math.max(...state.counters)}`;
|
|
111
|
+
if (usesNpmRegistry(pkg) ? await fetchGitHead(pkg.name, latest, pkg.bumpy?.registry) === headSha : tryRunArgs([
|
|
112
|
+
"git",
|
|
113
|
+
"rev-parse",
|
|
114
|
+
`refs/tags/${pkg.name}@${latest}`
|
|
115
|
+
], { cwd: rootDir }) === headSha) {
|
|
116
|
+
alreadyPublished.push({
|
|
117
|
+
name: release.name,
|
|
118
|
+
version: latest
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
releases.push({
|
|
124
|
+
...release,
|
|
125
|
+
newVersion: nextPrereleaseVersion(target, channel.preid, state.counters)
|
|
126
|
+
});
|
|
127
|
+
}));
|
|
128
|
+
releases.sort((a, b) => a.name.localeCompare(b.name));
|
|
129
|
+
return {
|
|
130
|
+
plan: {
|
|
131
|
+
bumpFiles: stablePlan.bumpFiles,
|
|
132
|
+
releases,
|
|
133
|
+
warnings
|
|
134
|
+
},
|
|
135
|
+
alreadyPublished,
|
|
136
|
+
warnings
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Transiently write computed prerelease versions (and exact pins for in-cycle deps)
|
|
141
|
+
* into the working tree's package.json files. Returns a restore function that puts
|
|
142
|
+
* the original contents back — call it in a `finally` after publishing.
|
|
143
|
+
*
|
|
144
|
+
* Versions must be on disk before build/pack so that:
|
|
145
|
+
* - PM pack picks up the prerelease version for the tarball
|
|
146
|
+
* - builds that bake in the version (banners, __VERSION__) see the right one
|
|
147
|
+
*
|
|
148
|
+
* In-cycle dependencies are pinned EXACTLY (`"1.2.0-rc.0"`, no range) so any
|
|
149
|
+
* combination of packages installed from the channel dist-tag resolves to the
|
|
150
|
+
* coherent set it was published with.
|
|
151
|
+
*/
|
|
152
|
+
async function writeChannelVersionsInPlace(plan, packages) {
|
|
153
|
+
const releaseMap = new Map(plan.releases.map((r) => [r.name, r]));
|
|
154
|
+
const originals = /* @__PURE__ */ new Map();
|
|
155
|
+
for (const release of plan.releases) {
|
|
156
|
+
const pkg = packages.get(release.name);
|
|
157
|
+
if (!pkg) continue;
|
|
158
|
+
const pkgJsonPath = resolve(pkg.dir, "package.json");
|
|
159
|
+
originals.set(pkgJsonPath, await readText(pkgJsonPath));
|
|
160
|
+
await updateJsonFields(pkgJsonPath, { version: release.newVersion });
|
|
161
|
+
for (const depField of [
|
|
162
|
+
"dependencies",
|
|
163
|
+
"peerDependencies",
|
|
164
|
+
"optionalDependencies"
|
|
165
|
+
]) {
|
|
166
|
+
const deps = pkg[depField];
|
|
167
|
+
for (const depName of Object.keys(deps)) {
|
|
168
|
+
const depRelease = releaseMap.get(depName);
|
|
169
|
+
if (!depRelease) continue;
|
|
170
|
+
await updateJsonNestedField(pkgJsonPath, depField, depName, depRelease.newVersion);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return async () => {
|
|
175
|
+
for (const [path, content] of originals) await writeText(path, content);
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/** One-line summary of a channel plan's versions, for PR titles and commit messages */
|
|
179
|
+
function formatChannelVersionSummary(releases) {
|
|
180
|
+
if (releases.length === 0) return "";
|
|
181
|
+
const lead = releases.filter((r) => !r.isDependencyBump && !r.isCascadeBump && !r.isGroupBump)[0] ?? releases[0];
|
|
182
|
+
const rest = releases.length - 1;
|
|
183
|
+
return rest > 0 ? `${lead.name}@${lead.newVersion} (+${rest} more)` : `${lead.name}@${lead.newVersion}`;
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
export { formatChannelVersionSummary as n, writeChannelVersionsInPlace as r, buildChannelReleasePlan as t };
|