@varlock/bumpy 0.0.1 → 0.0.2
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/dist/add-BjyVIUlr.mjs +175 -0
- package/dist/{ai-B8ZL2x8z.mjs → ai-CQhUyHAG.mjs} +2 -2
- package/dist/{apply-release-plan-DtU3rVyL.mjs → apply-release-plan-D6TSrcwX.mjs} +11 -6
- package/dist/changelog-github-Du62krXi.mjs +193 -0
- package/dist/{changeset-ClCYsChu.mjs → changeset-UCZdSRDv.mjs} +36 -3
- package/dist/{check-CkRubvuk.mjs → check-jIwike9F.mjs} +5 -11
- package/dist/ci-D6LQbR38.mjs +585 -0
- package/dist/ci-setup-C6FlOfW5.mjs +211 -0
- package/dist/clack-CDRCHrC-.mjs +1216 -0
- package/dist/cli.mjs +20 -16
- package/dist/{config-CJ2orhTL.mjs → config-BkwIEaQg.mjs} +2 -2
- package/dist/{fs-DbNNEyzq.mjs → fs-0AtnPUUe.mjs} +1 -1
- package/dist/{generate-oOFD9ABC.mjs → generate-Btrsn1qi.mjs} +28 -9
- package/dist/git-CGHVXXKw.mjs +78 -0
- package/dist/index.d.mts +10 -2
- package/dist/index.mjs +8 -8
- package/dist/{init-Blw2GfC_.mjs → init-B0q3wEQW.mjs} +2 -2
- package/dist/logger-C2dEe5Su.mjs +135 -0
- package/dist/{migrate-DvOrXSw0.mjs → migrate-CfQNwD0T.mjs} +18 -11
- package/dist/{names-C-u50ofE.mjs → names-Ck8cun7B.mjs} +2 -1
- package/dist/package-manager-DcI5TdDE.mjs +80 -0
- package/dist/{publish-DZ3m7qkX.mjs → publish-D_7RqEYL.mjs} +74 -20
- package/dist/{publish-pipeline-1M5GmbdP.mjs → publish-pipeline-ChnqW8nR.mjs} +40 -54
- package/dist/{release-plan-CFnutSHD.mjs → release-plan-BEzwApuK.mjs} +2 -2
- package/dist/{semver-DWO6NFKN.mjs → semver-BTzYh8vc.mjs} +1 -1
- package/dist/shell-Dj7JRD_q.mjs +92 -0
- package/dist/{status-DRpq_Mha.mjs → status--Q8yAxQ4.mjs} +7 -7
- package/dist/{version-CJwf8XIA.mjs → version-cAUkfYPx.mjs} +60 -21
- package/dist/workspace-CxEKakDm.mjs +107 -0
- package/package.json +4 -2
- package/dist/add-u5V9V3L7.mjs +0 -131
- package/dist/changelog-github-n-3zV1p9.mjs +0 -59
- package/dist/ci-8KWWhjXl.mjs +0 -224
- package/dist/logger-ZqggsyGZ.mjs +0 -176
- package/dist/prompt-BP8toAOI.mjs +0 -46
- package/dist/shell-DPlltpzb.mjs +0 -44
- package/dist/workspace-mVjawG8g.mjs +0 -183
- /package/dist/{dep-graph-DiLeAhl9.mjs → dep-graph-E-9-eQ2J.mjs} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@varlock/bumpy",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Modern monorepo versioning and changelog tool",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,14 +24,16 @@
|
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsdown",
|
|
27
|
+
"check": "bun run tsc --noEmit",
|
|
27
28
|
"test": "bun test"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
31
|
+
"@clack/prompts": "^1.2.0",
|
|
30
32
|
"@types/bun": "latest",
|
|
31
33
|
"@types/js-yaml": "^4.0.9",
|
|
32
34
|
"@types/semver": "^7.7.0",
|
|
33
|
-
"ansis": "^4.2.0",
|
|
34
35
|
"js-yaml": "^4.1.0",
|
|
36
|
+
"picocolors": "^1.1.1",
|
|
35
37
|
"semver": "^7.7.2",
|
|
36
38
|
"tsdown": "^0.21.8"
|
|
37
39
|
}
|
package/dist/add-u5V9V3L7.mjs
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { n as log, t as colorize } from "./logger-ZqggsyGZ.mjs";
|
|
2
|
-
import { n as exists, t as ensureDir } from "./fs-DbNNEyzq.mjs";
|
|
3
|
-
import { a as loadConfig, r as getBumpyDir, s as matchGlob } from "./config-CJ2orhTL.mjs";
|
|
4
|
-
import { t as discoverPackages } from "./workspace-mVjawG8g.mjs";
|
|
5
|
-
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
6
|
-
import { i as writeChangeset } from "./changeset-ClCYsChu.mjs";
|
|
7
|
-
import { i as select, n as confirm, r as multiSelect, t as ask } from "./prompt-BP8toAOI.mjs";
|
|
8
|
-
import { n as slugify, t as randomName } from "./names-C-u50ofE.mjs";
|
|
9
|
-
import { resolve } from "node:path";
|
|
10
|
-
//#region src/commands/add.ts
|
|
11
|
-
const BUMP_CHOICES = [
|
|
12
|
-
{
|
|
13
|
-
label: "patch",
|
|
14
|
-
value: "patch"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
label: "minor",
|
|
18
|
-
value: "minor"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
label: "major",
|
|
22
|
-
value: "major"
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
label: "patch (isolated - no cascade)",
|
|
26
|
-
value: "patch-isolated"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
label: "minor (isolated - no cascade)",
|
|
30
|
-
value: "minor-isolated"
|
|
31
|
-
}
|
|
32
|
-
];
|
|
33
|
-
async function addCommand(rootDir, opts) {
|
|
34
|
-
const config = await loadConfig(rootDir);
|
|
35
|
-
const bumpyDir = getBumpyDir(rootDir);
|
|
36
|
-
await ensureDir(bumpyDir);
|
|
37
|
-
if (opts.empty) {
|
|
38
|
-
const filename = opts.name ? slugify(opts.name) : randomName();
|
|
39
|
-
const filePath = resolve(bumpyDir, `${filename}.md`);
|
|
40
|
-
const { writeText } = await import("./fs-DbNNEyzq.mjs").then((n) => n.r);
|
|
41
|
-
await writeText(filePath, "---\n---\n");
|
|
42
|
-
log.success(`Created empty changeset: .bumpy/${filename}.md`);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
let releases;
|
|
46
|
-
let summary;
|
|
47
|
-
if (opts.packages) {
|
|
48
|
-
releases = parsePackagesFlag(opts.packages);
|
|
49
|
-
summary = opts.message || "";
|
|
50
|
-
} else {
|
|
51
|
-
const pkgs = await discoverPackages(rootDir, config);
|
|
52
|
-
const depGraph = new DependencyGraph(pkgs);
|
|
53
|
-
const selected = await multiSelect("Which packages should be included in this changeset?", [...pkgs.values()].map((p) => ({
|
|
54
|
-
label: `${p.name} (${p.version})`,
|
|
55
|
-
value: p.name
|
|
56
|
-
})));
|
|
57
|
-
if (selected.length === 0) {
|
|
58
|
-
log.warn("No packages selected. Aborting.");
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
releases = [];
|
|
62
|
-
for (const name of selected) {
|
|
63
|
-
const bumpType = await select(`Bump type for ${colorize(name, "cyan")}:`, BUMP_CHOICES);
|
|
64
|
-
const release = {
|
|
65
|
-
name,
|
|
66
|
-
type: bumpType
|
|
67
|
-
};
|
|
68
|
-
if (!bumpType.endsWith("-isolated")) {
|
|
69
|
-
const dependents = depGraph.getDependents(name);
|
|
70
|
-
const cascadeTargets = pkgs.get(name).bumpy?.cascadeTo;
|
|
71
|
-
if (dependents.length > 0 || cascadeTargets) {
|
|
72
|
-
if (await confirm(`${name} has ${dependents.length} dependents. Specify explicit cascades?`, false)) {
|
|
73
|
-
const allTargets = /* @__PURE__ */ new Set();
|
|
74
|
-
for (const d of dependents) allTargets.add(d.name);
|
|
75
|
-
if (cascadeTargets) {
|
|
76
|
-
for (const pattern of Object.keys(cascadeTargets)) for (const [pName] of pkgs) if (matchGlob(pName, pattern)) allTargets.add(pName);
|
|
77
|
-
}
|
|
78
|
-
const cascadeSelected = await multiSelect("Which packages should cascade?", [...allTargets].map((n) => ({
|
|
79
|
-
label: n,
|
|
80
|
-
value: n
|
|
81
|
-
})));
|
|
82
|
-
if (cascadeSelected.length > 0) {
|
|
83
|
-
const cascadeBump = await select("Cascade bump type:", [
|
|
84
|
-
{
|
|
85
|
-
label: "patch",
|
|
86
|
-
value: "patch"
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
label: "minor",
|
|
90
|
-
value: "minor"
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
label: "major",
|
|
94
|
-
value: "major"
|
|
95
|
-
}
|
|
96
|
-
]);
|
|
97
|
-
const cascade = {};
|
|
98
|
-
for (const target of cascadeSelected) cascade[target] = cascadeBump;
|
|
99
|
-
release.cascade = cascade;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
releases.push(release);
|
|
105
|
-
}
|
|
106
|
-
summary = await ask("Summary (what changed and why)");
|
|
107
|
-
}
|
|
108
|
-
let filename;
|
|
109
|
-
if (opts.name) filename = slugify(opts.name);
|
|
110
|
-
else if (opts.packages) filename = randomName();
|
|
111
|
-
else filename = slugify(await ask("Changeset name", randomName())) || randomName();
|
|
112
|
-
if (await exists(resolve(bumpyDir, `${filename}.md`))) filename = `${filename}-${Date.now()}`;
|
|
113
|
-
await writeChangeset(rootDir, filename, releases, summary);
|
|
114
|
-
log.success(`Created changeset: .bumpy/${filename}.md`);
|
|
115
|
-
for (const r of releases) {
|
|
116
|
-
const cascade = "cascade" in r && Object.keys(r.cascade).length > 0 ? ` (cascade: ${Object.entries(r.cascade).map(([k, v]) => `${k}:${v}`).join(", ")})` : "";
|
|
117
|
-
log.dim(` ${r.name}: ${r.type}${cascade}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function parsePackagesFlag(input) {
|
|
121
|
-
return input.split(",").map((entry) => {
|
|
122
|
-
const [name, type] = entry.trim().split(":");
|
|
123
|
-
if (!name || !type) throw new Error(`Invalid package format: "${entry}". Expected "name:bumpType"`);
|
|
124
|
-
return {
|
|
125
|
-
name: name.trim(),
|
|
126
|
-
type: type.trim()
|
|
127
|
-
};
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
//#endregion
|
|
131
|
-
export { addCommand };
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { i as tryRun } from "./shell-DPlltpzb.mjs";
|
|
2
|
-
//#region src/core/changelog-github.ts
|
|
3
|
-
/**
|
|
4
|
-
* GitHub-enhanced changelog formatter.
|
|
5
|
-
* Adds PR links and author attribution when git/gh info is available.
|
|
6
|
-
*
|
|
7
|
-
* Usage in config:
|
|
8
|
-
* "changelog": "github"
|
|
9
|
-
* "changelog": ["github", { "repo": "dmno-dev/bumpy" }]
|
|
10
|
-
*/
|
|
11
|
-
function createGithubFormatter(options = {}) {
|
|
12
|
-
return async (ctx) => {
|
|
13
|
-
const { release, changesets, date } = ctx;
|
|
14
|
-
const lines = [];
|
|
15
|
-
lines.push(`## ${release.newVersion}`);
|
|
16
|
-
lines.push("");
|
|
17
|
-
lines.push(`_${date}_`);
|
|
18
|
-
lines.push("");
|
|
19
|
-
const relevantChangesets = changesets.filter((cs) => release.changesets.includes(cs.id));
|
|
20
|
-
if (relevantChangesets.length > 0) for (const cs of relevantChangesets) {
|
|
21
|
-
if (!cs.summary) continue;
|
|
22
|
-
const firstLine = cs.summary.split("\n")[0];
|
|
23
|
-
const prInfo = await findPrForChangeset(cs.id, options.repo);
|
|
24
|
-
if (prInfo) lines.push(`- ${firstLine} ([#${prInfo.number}](${prInfo.url})) by @${prInfo.author}`);
|
|
25
|
-
else lines.push(`- ${firstLine}`);
|
|
26
|
-
const summaryLines = cs.summary.split("\n");
|
|
27
|
-
for (let i = 1; i < summaryLines.length; i++) if (summaryLines[i].trim()) lines.push(` ${summaryLines[i]}`);
|
|
28
|
-
}
|
|
29
|
-
if (release.isDependencyBump && relevantChangesets.length === 0) lines.push("- Updated dependencies");
|
|
30
|
-
if (release.isCascadeBump && !release.isDependencyBump && relevantChangesets.length === 0) lines.push("- Version bump via cascade rule");
|
|
31
|
-
lines.push("");
|
|
32
|
-
return lines.join("\n");
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Find the PR that introduced a changeset file by checking git log
|
|
37
|
-
* for the commit that added the file, then looking up the PR.
|
|
38
|
-
*/
|
|
39
|
-
async function findPrForChangeset(changesetId, repo) {
|
|
40
|
-
try {
|
|
41
|
-
const commitHash = tryRun(`git log --diff-filter=A --format="%H" -- ".bumpy/${changesetId}.md" ".changeset/${changesetId}.md"`);
|
|
42
|
-
if (!commitHash) return null;
|
|
43
|
-
const hash = commitHash.split("\n")[0].trim();
|
|
44
|
-
if (!hash) return null;
|
|
45
|
-
const prJson = tryRun(`gh pr list --search "${hash}" --state merged --json number,url,author --jq ".[0]" ${repo ? `--repo ${repo}` : ""}`);
|
|
46
|
-
if (!prJson) return null;
|
|
47
|
-
const pr = JSON.parse(prJson);
|
|
48
|
-
if (!pr.number) return null;
|
|
49
|
-
return {
|
|
50
|
-
number: pr.number,
|
|
51
|
-
url: pr.url,
|
|
52
|
-
author: pr.author?.login || "unknown"
|
|
53
|
-
};
|
|
54
|
-
} catch {
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
//#endregion
|
|
59
|
-
export { createGithubFormatter };
|
package/dist/ci-8KWWhjXl.mjs
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import { n as log, t as colorize } from "./logger-ZqggsyGZ.mjs";
|
|
2
|
-
import { a as loadConfig } from "./config-CJ2orhTL.mjs";
|
|
3
|
-
import { n as discoverWorkspace } from "./workspace-mVjawG8g.mjs";
|
|
4
|
-
import { t as DependencyGraph } from "./dep-graph-DiLeAhl9.mjs";
|
|
5
|
-
import { r as readChangesets } from "./changeset-ClCYsChu.mjs";
|
|
6
|
-
import { t as assembleReleasePlan } from "./release-plan-CFnutSHD.mjs";
|
|
7
|
-
import { i as tryRun, n as runAsync, t as run } from "./shell-DPlltpzb.mjs";
|
|
8
|
-
//#region src/commands/ci.ts
|
|
9
|
-
/** Configure git identity for CI commits if not already set */
|
|
10
|
-
function ensureGitIdentity(rootDir, config) {
|
|
11
|
-
if (!tryRun("git config user.name", { cwd: rootDir })) {
|
|
12
|
-
const { name: gitName, email: gitEmail } = config.gitUser;
|
|
13
|
-
run(`git config user.name "${gitName}"`, { cwd: rootDir });
|
|
14
|
-
run(`git config user.email "${gitEmail}"`, { cwd: rootDir });
|
|
15
|
-
log.dim(` Using git identity: ${gitName} <${gitEmail}>`);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* CI check: report on pending changesets.
|
|
20
|
-
* Designed for PR workflows — shows what would be released and optionally comments on the PR.
|
|
21
|
-
*/
|
|
22
|
-
async function ciCheckCommand(rootDir, opts) {
|
|
23
|
-
const config = await loadConfig(rootDir);
|
|
24
|
-
const { packages } = await discoverWorkspace(rootDir, config);
|
|
25
|
-
const depGraph = new DependencyGraph(packages);
|
|
26
|
-
const changesets = await readChangesets(rootDir);
|
|
27
|
-
const inCI = !!process.env.CI;
|
|
28
|
-
const shouldComment = opts.comment ?? inCI;
|
|
29
|
-
const prNumber = detectPrNumber();
|
|
30
|
-
if (changesets.length === 0) {
|
|
31
|
-
log.info("No changesets found in this PR.");
|
|
32
|
-
if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatNoChangesetsComment(), rootDir);
|
|
33
|
-
if (opts.failOnMissing) process.exit(1);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const plan = assembleReleasePlan(changesets, packages, depGraph, config);
|
|
37
|
-
log.bold(`${changesets.length} changeset(s) → ${plan.releases.length} package(s) to release\n`);
|
|
38
|
-
for (const r of plan.releases) {
|
|
39
|
-
const tag = r.isDependencyBump ? " (dep)" : r.isCascadeBump ? " (cascade)" : "";
|
|
40
|
-
console.log(` ${r.name}: ${r.oldVersion} → ${colorize(r.newVersion, "cyan")}${tag}`);
|
|
41
|
-
}
|
|
42
|
-
if (shouldComment && prNumber) await postOrUpdatePrComment(prNumber, formatReleasePlanComment(plan, changesets.length), rootDir);
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* CI release: either auto-publish or create a version PR.
|
|
46
|
-
* Designed for merge-to-main workflows.
|
|
47
|
-
*/
|
|
48
|
-
async function ciReleaseCommand(rootDir, opts) {
|
|
49
|
-
const config = await loadConfig(rootDir);
|
|
50
|
-
ensureGitIdentity(rootDir, config);
|
|
51
|
-
const { packages } = await discoverWorkspace(rootDir, config);
|
|
52
|
-
const depGraph = new DependencyGraph(packages);
|
|
53
|
-
const changesets = await readChangesets(rootDir);
|
|
54
|
-
if (changesets.length === 0) {
|
|
55
|
-
log.info("No pending changesets — checking for unpublished packages...");
|
|
56
|
-
const { publishCommand } = await import("./publish-DZ3m7qkX.mjs");
|
|
57
|
-
await publishCommand(rootDir, { tag: opts.tag });
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const plan = assembleReleasePlan(changesets, packages, depGraph, config);
|
|
61
|
-
if (plan.releases.length === 0) {
|
|
62
|
-
log.info("Changesets found but no packages would be released.");
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (opts.mode === "auto-publish") await autoPublish(rootDir, config, opts.tag);
|
|
66
|
-
else await createVersionPr(rootDir, plan, config, opts.branch);
|
|
67
|
-
}
|
|
68
|
-
async function autoPublish(rootDir, config, tag) {
|
|
69
|
-
log.step("Running bumpy version...");
|
|
70
|
-
const { versionCommand } = await import("./version-CJwf8XIA.mjs");
|
|
71
|
-
await versionCommand(rootDir);
|
|
72
|
-
log.step("Committing version changes...");
|
|
73
|
-
run("git add -A", { cwd: rootDir });
|
|
74
|
-
if (tryRun("git status --porcelain", { cwd: rootDir })) {
|
|
75
|
-
run("git commit -m \"Version packages\"", { cwd: rootDir });
|
|
76
|
-
run("git push", { cwd: rootDir });
|
|
77
|
-
}
|
|
78
|
-
log.step("Running bumpy publish...");
|
|
79
|
-
const { publishCommand } = await import("./publish-DZ3m7qkX.mjs");
|
|
80
|
-
await publishCommand(rootDir, { tag });
|
|
81
|
-
}
|
|
82
|
-
async function createVersionPr(rootDir, plan, config, branchName) {
|
|
83
|
-
const branch = branchName || config.versionPr.branch;
|
|
84
|
-
const baseBranch = tryRun("git rev-parse --abbrev-ref HEAD", { cwd: rootDir }) || "main";
|
|
85
|
-
const existingPr = tryRun(`gh pr list --head "${branch}" --json number --jq ".[0].number"`, { cwd: rootDir });
|
|
86
|
-
log.step(`Creating branch ${branch}...`);
|
|
87
|
-
if (tryRun(`git rev-parse --verify ${branch}`, { cwd: rootDir }) !== null) {
|
|
88
|
-
run(`git checkout ${branch}`, { cwd: rootDir });
|
|
89
|
-
run(`git reset --hard ${baseBranch}`, { cwd: rootDir });
|
|
90
|
-
} else run(`git checkout -b ${branch}`, { cwd: rootDir });
|
|
91
|
-
log.step("Running bumpy version...");
|
|
92
|
-
const { versionCommand } = await import("./version-CJwf8XIA.mjs");
|
|
93
|
-
await versionCommand(rootDir);
|
|
94
|
-
run("git add -A", { cwd: rootDir });
|
|
95
|
-
if (!tryRun("git status --porcelain", { cwd: rootDir })) {
|
|
96
|
-
log.info("No version changes to commit.");
|
|
97
|
-
run(`git checkout ${baseBranch}`, { cwd: rootDir });
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
run("git commit -F -", {
|
|
101
|
-
cwd: rootDir,
|
|
102
|
-
input: [
|
|
103
|
-
"Version packages",
|
|
104
|
-
"",
|
|
105
|
-
...plan.releases.map((r) => `${r.name}@${r.newVersion}`)
|
|
106
|
-
].join("\n")
|
|
107
|
-
});
|
|
108
|
-
run(`git push -u origin ${branch} --force`, { cwd: rootDir });
|
|
109
|
-
const prBody = formatVersionPrBody(plan, config.versionPr.preamble);
|
|
110
|
-
if (existingPr) {
|
|
111
|
-
log.step(`Updating existing PR #${existingPr}...`);
|
|
112
|
-
await runAsync(`gh pr edit ${existingPr} --title "${config.versionPr.title}" --body-file -`, {
|
|
113
|
-
cwd: rootDir,
|
|
114
|
-
input: prBody
|
|
115
|
-
});
|
|
116
|
-
log.success(`Updated PR #${existingPr}`);
|
|
117
|
-
} else {
|
|
118
|
-
log.step("Creating version PR...");
|
|
119
|
-
const prTitle = config.versionPr.title;
|
|
120
|
-
const result = await runAsync(`gh pr create --title "${prTitle}" --body-file - --base "${baseBranch}" --head "${branch}"`, {
|
|
121
|
-
cwd: rootDir,
|
|
122
|
-
input: prBody
|
|
123
|
-
});
|
|
124
|
-
log.success(`Created PR: ${result}`);
|
|
125
|
-
}
|
|
126
|
-
run(`git checkout ${baseBranch}`, { cwd: rootDir });
|
|
127
|
-
}
|
|
128
|
-
function formatReleasePlanComment(plan, changesetCount) {
|
|
129
|
-
const lines = [];
|
|
130
|
-
lines.push("## 🐸 Bumpy Release Plan\n");
|
|
131
|
-
lines.push(`**${changesetCount}** changeset(s) → **${plan.releases.length}** package(s) to release\n`);
|
|
132
|
-
const groups = [
|
|
133
|
-
["🔴 Major", plan.releases.filter((r) => r.type === "major")],
|
|
134
|
-
["🟡 Minor", plan.releases.filter((r) => r.type === "minor")],
|
|
135
|
-
["🟢 Patch", plan.releases.filter((r) => r.type === "patch")]
|
|
136
|
-
];
|
|
137
|
-
for (const [label, group] of groups) {
|
|
138
|
-
if (group.length === 0) continue;
|
|
139
|
-
lines.push(`### ${label}\n`);
|
|
140
|
-
lines.push("| Package | Change |");
|
|
141
|
-
lines.push("|---------|--------|");
|
|
142
|
-
for (const r of group) {
|
|
143
|
-
const suffix = r.isDependencyBump ? " _(dep)_" : r.isCascadeBump ? " _(cascade)_" : "";
|
|
144
|
-
lines.push(`| \`${r.name}\` | ${r.oldVersion} → **${r.newVersion}**${suffix} |`);
|
|
145
|
-
}
|
|
146
|
-
lines.push("");
|
|
147
|
-
}
|
|
148
|
-
lines.push("---");
|
|
149
|
-
lines.push(`_This comment is maintained by [bumpy](https://github.com/dmno-dev/bumpy)._`);
|
|
150
|
-
return lines.join("\n");
|
|
151
|
-
}
|
|
152
|
-
function formatNoChangesetsComment() {
|
|
153
|
-
return [
|
|
154
|
-
"## 🐸 Bumpy Release Plan\n",
|
|
155
|
-
"No changesets found in this PR. If this PR should trigger a release, run:\n",
|
|
156
|
-
"```bash",
|
|
157
|
-
"bumpy add",
|
|
158
|
-
"```\n",
|
|
159
|
-
"---",
|
|
160
|
-
`_This comment is maintained by [bumpy](https://github.com/dmno-dev/bumpy)._`
|
|
161
|
-
].join("\n");
|
|
162
|
-
}
|
|
163
|
-
const FROG_IMG_BASE = "https://raw.githubusercontent.com/dmno-dev/bumpy/main/images";
|
|
164
|
-
function bumpSectionHeader(type) {
|
|
165
|
-
return `### ${`<img src="${FROG_IMG_BASE}/frog-${type}.png" alt="${type}" width="52" style="image-rendering: pixelated;" align="right" />`} ${type.charAt(0).toUpperCase() + type.slice(1)} releases`;
|
|
166
|
-
}
|
|
167
|
-
function formatVersionPrBody(plan, preamble) {
|
|
168
|
-
const lines = [];
|
|
169
|
-
lines.push(preamble);
|
|
170
|
-
lines.push("");
|
|
171
|
-
const groups = {
|
|
172
|
-
major: [],
|
|
173
|
-
minor: [],
|
|
174
|
-
patch: []
|
|
175
|
-
};
|
|
176
|
-
for (const r of plan.releases) groups[r.type]?.push(r);
|
|
177
|
-
for (const type of [
|
|
178
|
-
"major",
|
|
179
|
-
"minor",
|
|
180
|
-
"patch"
|
|
181
|
-
]) {
|
|
182
|
-
const releases = groups[type];
|
|
183
|
-
if (!releases || releases.length === 0) continue;
|
|
184
|
-
lines.push(bumpSectionHeader(type));
|
|
185
|
-
lines.push("");
|
|
186
|
-
for (const r of releases) {
|
|
187
|
-
const suffix = r.isDependencyBump ? " (dep)" : r.isCascadeBump ? " (cascade)" : "";
|
|
188
|
-
lines.push(`- \`${r.name}\` ${r.oldVersion} → **${r.newVersion}**${suffix}`);
|
|
189
|
-
}
|
|
190
|
-
lines.push("");
|
|
191
|
-
}
|
|
192
|
-
return lines.join("\n");
|
|
193
|
-
}
|
|
194
|
-
const COMMENT_MARKER = "<!-- bumpy-release-plan -->";
|
|
195
|
-
async function postOrUpdatePrComment(prNumber, body, rootDir) {
|
|
196
|
-
const markedBody = `${COMMENT_MARKER}\n${body}`;
|
|
197
|
-
try {
|
|
198
|
-
const existingComment = tryRun(`gh pr view ${prNumber} --json comments --jq '.comments[] | select(.body | startswith("${COMMENT_MARKER}")) | .id' | head -1`, { cwd: rootDir });
|
|
199
|
-
if (existingComment) {
|
|
200
|
-
await runAsync(`gh api repos/{owner}/{repo}/issues/comments/${existingComment} -X PATCH -f body=@-`, {
|
|
201
|
-
cwd: rootDir,
|
|
202
|
-
input: markedBody
|
|
203
|
-
});
|
|
204
|
-
log.dim(" Updated PR comment");
|
|
205
|
-
} else {
|
|
206
|
-
await runAsync(`gh pr comment ${prNumber} --body-file -`, {
|
|
207
|
-
cwd: rootDir,
|
|
208
|
-
input: markedBody
|
|
209
|
-
});
|
|
210
|
-
log.dim(" Posted PR comment");
|
|
211
|
-
}
|
|
212
|
-
} catch (err) {
|
|
213
|
-
log.warn(` Failed to comment on PR: ${err instanceof Error ? err.message : err}`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
function detectPrNumber() {
|
|
217
|
-
if (process.env.GITHUB_EVENT_NAME === "pull_request") {
|
|
218
|
-
const match = process.env.GITHUB_REF?.match(/refs\/pull\/(\d+)\//);
|
|
219
|
-
if (match) return match[1];
|
|
220
|
-
}
|
|
221
|
-
return process.env.BUMPY_PR_NUMBER || process.env.PR_NUMBER || null;
|
|
222
|
-
}
|
|
223
|
-
//#endregion
|
|
224
|
-
export { ciCheckCommand, ciReleaseCommand };
|
package/dist/logger-ZqggsyGZ.mjs
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
9
|
-
var __exportAll = (all, no_symbols) => {
|
|
10
|
-
let target = {};
|
|
11
|
-
for (var name in all) __defProp(target, name, {
|
|
12
|
-
get: all[name],
|
|
13
|
-
enumerable: true
|
|
14
|
-
});
|
|
15
|
-
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
|
-
return target;
|
|
17
|
-
};
|
|
18
|
-
var __copyProps = (to, from, except, desc) => {
|
|
19
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
20
|
-
key = keys[i];
|
|
21
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
22
|
-
get: ((k) => from[k]).bind(null, key),
|
|
23
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
return to;
|
|
27
|
-
};
|
|
28
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
29
|
-
value: mod,
|
|
30
|
-
enumerable: true
|
|
31
|
-
}) : target, mod));
|
|
32
|
-
const { Ansis, fg, bg, rgb, bgRgb, hex, bgHex, reset, inverse, hidden, visible, bold, dim, italic, underline, strikethrough, black, red, green, yellow, blue, magenta, cyan, white, gray, redBright, greenBright, yellowBright, blueBright, magentaBright, cyanBright, whiteBright, bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite, bgGray, bgRedBright, bgGreenBright, bgYellowBright, bgBlueBright, bgMagentaBright, bgCyanBright, bgWhiteBright } = (/* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
33
|
-
let e, t, r, { defineProperty: l, setPrototypeOf: n, create: o, keys: s } = Object, i = "", { round: c, max: a } = Math, p = (e) => {
|
|
34
|
-
let t = /([a-f\d]{3,6})/i.exec(e)?.[1], r = t?.length, l = parseInt(6 ^ r ? 3 ^ r ? "0" : t[0] + t[0] + t[1] + t[1] + t[2] + t[2] : t, 16);
|
|
35
|
-
return [
|
|
36
|
-
l >> 16 & 255,
|
|
37
|
-
l >> 8 & 255,
|
|
38
|
-
255 & l
|
|
39
|
-
];
|
|
40
|
-
}, u = (e, t, r) => e ^ t || t ^ r ? 16 + 36 * c(e / 51) + 6 * c(t / 51) + c(r / 51) : 8 > e ? 16 : e > 248 ? 231 : c(24 * (e - 8) / 247) + 232, d = (e) => {
|
|
41
|
-
let t, r, l, n, o;
|
|
42
|
-
return 8 > e ? 30 + e : 16 > e ? e - 8 + 90 : (232 > e ? (o = (e -= 16) % 36, t = (e / 36 | 0) / 5, r = (o / 6 | 0) / 5, l = o % 6 / 5) : t = r = l = (10 * (e - 232) + 8) / 255, n = 2 * a(t, r, l), n ? 30 + (c(l) << 2 | c(r) << 1 | c(t)) + (2 ^ n ? 0 : 60) : 30);
|
|
43
|
-
}, f = (() => {
|
|
44
|
-
let r = (e) => o.some(((t) => e.test(t))), l = globalThis, n = l.process ?? {}, o = n.argv ?? [], i = n.env ?? {}, c = -1;
|
|
45
|
-
try {
|
|
46
|
-
e = "," + s(i).join(",");
|
|
47
|
-
} catch (e) {
|
|
48
|
-
i = {}, c = 0;
|
|
49
|
-
}
|
|
50
|
-
let a = "FORCE_COLOR", p = {
|
|
51
|
-
false: 0,
|
|
52
|
-
0: 0,
|
|
53
|
-
1: 1,
|
|
54
|
-
2: 2,
|
|
55
|
-
3: 3
|
|
56
|
-
}[i[a]] ?? -1, u = a in i && p || r(/^--color=?(true|always)?$/);
|
|
57
|
-
return u && (c = p), ~c || (c = ((r, l, n) => (t = r.TERM, {
|
|
58
|
-
"24bit": 3,
|
|
59
|
-
truecolor: 3,
|
|
60
|
-
ansi256: 2,
|
|
61
|
-
ansi: 1
|
|
62
|
-
}[r.COLORTERM] || (r.CI ? /,GITHUB/.test(e) ? 3 : 1 : l && "dumb" !== t ? n ? 3 : /-256/.test(t) ? 2 : 1 : 0)))(i, !!i.PM2_HOME || i.NEXT_RUNTIME?.includes("edge") || !!n.stdout?.isTTY, "win32" === n.platform)), !p || i.NO_COLOR || r(/^--(no-color|color=(false|never))$/) ? 0 : l.window?.chrome || u && !c ? 3 : c;
|
|
63
|
-
})(), g = {
|
|
64
|
-
open: i,
|
|
65
|
-
close: i
|
|
66
|
-
}, h = 39, b = 49, O = {}, m = ({ p: e }, { open: t, close: l }) => {
|
|
67
|
-
let o = (e, ...r) => {
|
|
68
|
-
if (!e) {
|
|
69
|
-
if (t && t === l) return t;
|
|
70
|
-
if ((e ?? i) === i) return i;
|
|
71
|
-
}
|
|
72
|
-
let n, s = e.raw ? String.raw({ raw: e }, ...r) : i + e, c = o.p, a = c.o, p = c.c;
|
|
73
|
-
if (s.includes("\x1B")) for (; c; c = c.p) {
|
|
74
|
-
let { open: e, close: t } = c, r = t.length, l = i, o = 0;
|
|
75
|
-
if (r) for (; ~(n = s.indexOf(t, o)); o = n + r) l += s.slice(o, n) + e;
|
|
76
|
-
s = l + s.slice(o);
|
|
77
|
-
}
|
|
78
|
-
return a + (s.includes("\n") ? s.replace(/(\r?\n)/g, p + "$1" + a) : s) + p;
|
|
79
|
-
}, s = t, c = l;
|
|
80
|
-
return e && (s = e.o + t, c = l + e.c), n(o, r), o.p = {
|
|
81
|
-
open: t,
|
|
82
|
-
close: l,
|
|
83
|
-
o: s,
|
|
84
|
-
c,
|
|
85
|
-
p: e
|
|
86
|
-
}, o.open = s, o.close = c, o;
|
|
87
|
-
};
|
|
88
|
-
const w = new function e(t = f) {
|
|
89
|
-
let s = {
|
|
90
|
-
Ansis: e,
|
|
91
|
-
level: t,
|
|
92
|
-
isSupported: () => a,
|
|
93
|
-
strip: (e) => e.replace(/[][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, i),
|
|
94
|
-
extend(e) {
|
|
95
|
-
for (let t in e) {
|
|
96
|
-
let r = e[t], l = (typeof r)[0];
|
|
97
|
-
"s" === l ? (c(t, T(...p(r))), c(_(t), v(...p(r)))) : c(t, r, "f" === l);
|
|
98
|
-
}
|
|
99
|
-
return r = o({}, O), n(s, r), s;
|
|
100
|
-
}
|
|
101
|
-
}, c = (e, t, r) => {
|
|
102
|
-
O[e] = { get() {
|
|
103
|
-
let n = r ? (...e) => m(this, t(...e)) : m(this, t);
|
|
104
|
-
return l(this, e, { value: n }), n;
|
|
105
|
-
} };
|
|
106
|
-
}, a = t > 0, w = (e, t) => a ? {
|
|
107
|
-
open: `[${e}m`,
|
|
108
|
-
close: `[${t}m`
|
|
109
|
-
} : g, y = (e) => (t) => e(...p(t)), R = (e, t) => (r, l, n) => w(`${e}8;2;${r};${l};${n}`, t), $ = (e, t) => (r, l, n) => w(((e, t, r) => d(u(e, t, r)))(r, l, n) + e, t), x = (e) => (t, r, l) => e(u(t, r, l)), T = R(3, h), v = R(4, b), C = (e) => w("38;5;" + e, h), E = (e) => w("48;5;" + e, b);
|
|
110
|
-
2 === t ? (T = x(C), v = x(E)) : 1 === t && (T = $(0, h), v = $(10, b), C = (e) => w(d(e), h), E = (e) => w(d(e) + 10, b));
|
|
111
|
-
let M, I = {
|
|
112
|
-
fg: C,
|
|
113
|
-
bg: E,
|
|
114
|
-
rgb: T,
|
|
115
|
-
bgRgb: v,
|
|
116
|
-
hex: y(T),
|
|
117
|
-
bgHex: y(v),
|
|
118
|
-
visible: g,
|
|
119
|
-
reset: w(0, 0),
|
|
120
|
-
bold: w(1, 22),
|
|
121
|
-
dim: w(2, 22),
|
|
122
|
-
italic: w(3, 23),
|
|
123
|
-
underline: w(4, 24),
|
|
124
|
-
inverse: w(7, 27),
|
|
125
|
-
hidden: w(8, 28),
|
|
126
|
-
strikethrough: w(9, 29)
|
|
127
|
-
}, _ = (e) => "bg" + e[0].toUpperCase() + e.slice(1), k = "Bright";
|
|
128
|
-
return "black,red,green,yellow,blue,magenta,cyan,white,gray".split(",").map(((e, t) => {
|
|
129
|
-
M = _(e), 8 > t ? (I[e + k] = w(90 + t, h), I[M + k] = w(100 + t, b)) : t = 60, I[e] = w(30 + t, h), I[M] = w(40 + t, b);
|
|
130
|
-
})), s.extend(I);
|
|
131
|
-
}();
|
|
132
|
-
module.exports = w, w.default = w;
|
|
133
|
-
})))(), 1)).default;
|
|
134
|
-
//#endregion
|
|
135
|
-
//#region src/utils/logger.ts
|
|
136
|
-
const log = {
|
|
137
|
-
info(msg) {
|
|
138
|
-
console.log(`${blue`info`} ${msg}`);
|
|
139
|
-
},
|
|
140
|
-
success(msg) {
|
|
141
|
-
console.log(`${green`done`} ${msg}`);
|
|
142
|
-
},
|
|
143
|
-
warn(msg) {
|
|
144
|
-
console.log(`${yellow`warn`} ${msg}`);
|
|
145
|
-
},
|
|
146
|
-
error(msg) {
|
|
147
|
-
console.error(`${red`error`} ${msg}`);
|
|
148
|
-
},
|
|
149
|
-
step(msg) {
|
|
150
|
-
console.log(`${cyan`=>`} ${msg}`);
|
|
151
|
-
},
|
|
152
|
-
dim(msg) {
|
|
153
|
-
console.log(dim`${msg}`);
|
|
154
|
-
},
|
|
155
|
-
bold(msg) {
|
|
156
|
-
console.log(bold`${msg}`);
|
|
157
|
-
},
|
|
158
|
-
table(rows) {
|
|
159
|
-
if (rows.length === 0) return;
|
|
160
|
-
const colWidths = rows[0].map((_, i) => Math.max(...rows.map((r) => (r[i] ?? "").length)));
|
|
161
|
-
for (const row of rows) console.log(row.map((cell, i) => cell.padEnd(colWidths[i])).join(" "));
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
function colorize(text, color) {
|
|
165
|
-
return {
|
|
166
|
-
red,
|
|
167
|
-
green,
|
|
168
|
-
yellow,
|
|
169
|
-
blue,
|
|
170
|
-
cyan,
|
|
171
|
-
dim,
|
|
172
|
-
bold
|
|
173
|
-
}[color](text);
|
|
174
|
-
}
|
|
175
|
-
//#endregion
|
|
176
|
-
export { __toESM as a, __exportAll as i, log as n, __commonJSMin as r, colorize as t };
|
package/dist/prompt-BP8toAOI.mjs
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import * as readline from "node:readline";
|
|
2
|
-
//#region src/utils/prompt.ts
|
|
3
|
-
function createInterface() {
|
|
4
|
-
return readline.createInterface({
|
|
5
|
-
input: process.stdin,
|
|
6
|
-
output: process.stdout
|
|
7
|
-
});
|
|
8
|
-
}
|
|
9
|
-
async function ask(question, defaultValue) {
|
|
10
|
-
const rl = createInterface();
|
|
11
|
-
const suffix = defaultValue ? ` (${defaultValue})` : "";
|
|
12
|
-
return new Promise((resolve) => {
|
|
13
|
-
rl.question(`${question}${suffix}: `, (answer) => {
|
|
14
|
-
rl.close();
|
|
15
|
-
resolve(answer.trim() || defaultValue || "");
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
async function confirm(question, defaultYes = true) {
|
|
20
|
-
const answer = await ask(`${question} [${defaultYes ? "Y/n" : "y/N"}]`);
|
|
21
|
-
if (!answer) return defaultYes;
|
|
22
|
-
return answer.toLowerCase().startsWith("y");
|
|
23
|
-
}
|
|
24
|
-
async function select(question, options) {
|
|
25
|
-
console.log(question);
|
|
26
|
-
for (let i = 0; i < options.length; i++) console.log(` ${i + 1}) ${options[i].label}`);
|
|
27
|
-
const answer = await ask("Choose");
|
|
28
|
-
const idx = parseInt(answer, 10) - 1;
|
|
29
|
-
if (idx >= 0 && idx < options.length) return options[idx].value;
|
|
30
|
-
const match = options.find((o) => o.value === answer || o.label.toLowerCase() === answer.toLowerCase());
|
|
31
|
-
if (match) return match.value;
|
|
32
|
-
return options[0].value;
|
|
33
|
-
}
|
|
34
|
-
async function multiSelect(question, options) {
|
|
35
|
-
console.log(question);
|
|
36
|
-
for (let i = 0; i < options.length; i++) {
|
|
37
|
-
const mark = options[i].checked ? "[x]" : "[ ]";
|
|
38
|
-
console.log(` ${i + 1}) ${mark} ${options[i].label}`);
|
|
39
|
-
}
|
|
40
|
-
const answer = await ask("Select (comma-separated numbers, or 'all')");
|
|
41
|
-
if (answer.toLowerCase() === "all") return options.map((o) => o.value);
|
|
42
|
-
if (!answer) return options.filter((o) => o.checked).map((o) => o.value);
|
|
43
|
-
return answer.split(",").map((s) => parseInt(s.trim(), 10) - 1).filter((i) => i >= 0 && i < options.length).map((i) => options[i].value);
|
|
44
|
-
}
|
|
45
|
-
//#endregion
|
|
46
|
-
export { select as i, confirm as n, multiSelect as r, ask as t };
|