@varlock/bumpy 0.0.1 → 1.0.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/.claude-plugin/plugin.json +2 -2
- package/dist/add-CgCjs4d-.mjs +313 -0
- package/dist/{ai-B8ZL2x8z.mjs → ai-sMYUf3lP.mjs} +22 -5
- package/dist/{apply-release-plan-DtU3rVyL.mjs → apply-release-plan-CczGWJTk.mjs} +34 -25
- package/dist/bump-file-CCLXMLA8.mjs +143 -0
- package/dist/changelog-github-Cd8uJHZI.mjs +195 -0
- package/dist/{check-CkRubvuk.mjs → check-BOoxpWqk.mjs} +11 -17
- package/dist/ci-Bhx--Tj6.mjs +629 -0
- package/dist/ci-setup-qz4Y3v7T.mjs +211 -0
- package/dist/clack-CDRCHrC-.mjs +1216 -0
- package/dist/cli.mjs +37 -31
- package/dist/{config-CJ2orhTL.mjs → config-XZWUL3ma.mjs} +28 -23
- package/dist/fs-DYR2XuFE.mjs +81 -0
- package/dist/{generate-oOFD9ABC.mjs → generate-gYKTpvex.mjs} +31 -12
- package/dist/git-CGHVXXKw.mjs +78 -0
- package/dist/index.d.mts +63 -37
- package/dist/index.mjs +9 -9
- package/dist/{init-Blw2GfC_.mjs → init-lA9E5pEc.mjs} +3 -3
- package/dist/logger-C2dEe5Su.mjs +135 -0
- package/dist/{migrate-DvOrXSw0.mjs → migrate-DmOYgmfD.mjs} +23 -16
- package/dist/{names-C-u50ofE.mjs → names-9VubBmL0.mjs} +3 -2
- package/dist/package-manager-VCe10bjc.mjs +80 -0
- package/dist/{publish-DZ3m7qkX.mjs → publish-Cun-zQ1b.mjs} +90 -35
- package/dist/{publish-pipeline-1M5GmbdP.mjs → publish-pipeline-BwBuKCIk.mjs} +56 -65
- package/dist/release-plan-Bi5QNSEo.mjs +264 -0
- package/dist/{semver-DWO6NFKN.mjs → semver-DfQyVLM_.mjs} +14 -4
- package/dist/shell-Dj7JRD_q.mjs +92 -0
- package/dist/{status-DRpq_Mha.mjs → status-CfE63ti5.mjs} +27 -23
- package/dist/version-19vVt9dv.mjs +124 -0
- package/dist/workspace-C5ULTyUN.mjs +107 -0
- package/package.json +16 -2
- package/skills/add-change/SKILL.md +8 -12
- package/dist/add-u5V9V3L7.mjs +0 -131
- package/dist/changelog-github-n-3zV1p9.mjs +0 -59
- package/dist/changeset-ClCYsChu.mjs +0 -75
- package/dist/ci-8KWWhjXl.mjs +0 -224
- package/dist/fs-DbNNEyzq.mjs +0 -51
- package/dist/logger-ZqggsyGZ.mjs +0 -176
- package/dist/prompt-BP8toAOI.mjs +0 -46
- package/dist/release-plan-CFnutSHD.mjs +0 -173
- package/dist/shell-DPlltpzb.mjs +0 -44
- package/dist/version-CJwf8XIA.mjs +0 -81
- package/dist/workspace-mVjawG8g.mjs +0 -183
- /package/dist/{dep-graph-DiLeAhl9.mjs → dep-graph-E-9-eQ2J.mjs} +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { o as tryRunArgs } from "./shell-Dj7JRD_q.mjs";
|
|
2
|
+
//#region src/core/changelog-github.ts
|
|
3
|
+
/**
|
|
4
|
+
* GitHub-enhanced changelog formatter.
|
|
5
|
+
* Adds PR links, commit links, and contributor attribution when git/gh info is available.
|
|
6
|
+
*
|
|
7
|
+
* Usage in config:
|
|
8
|
+
* "changelog": "github"
|
|
9
|
+
* "changelog": ["github", { "repo": "dmno-dev/bumpy" }]
|
|
10
|
+
* "changelog": ["github", { "thankContributors": false }]
|
|
11
|
+
* "changelog": ["github", { "internalAuthors": ["theoephraim"] }]
|
|
12
|
+
*/
|
|
13
|
+
function createGithubFormatter(options = {}) {
|
|
14
|
+
const thankContributors = options.thankContributors ?? true;
|
|
15
|
+
const internalAuthorsSet = new Set((options.internalAuthors ?? []).map((a) => a.toLowerCase()));
|
|
16
|
+
return async (ctx) => {
|
|
17
|
+
const { release, bumpFiles, date } = ctx;
|
|
18
|
+
const repoSlug = options.repo ?? detectRepo();
|
|
19
|
+
const serverUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
|
|
20
|
+
const lines = [];
|
|
21
|
+
lines.push(`## ${release.newVersion}`);
|
|
22
|
+
lines.push("");
|
|
23
|
+
lines.push(`_${date}_`);
|
|
24
|
+
lines.push("");
|
|
25
|
+
const relevantBumpFiles = bumpFiles.filter((bf) => release.bumpFiles.includes(bf.id));
|
|
26
|
+
if (relevantBumpFiles.length > 0) for (const bf of relevantBumpFiles) {
|
|
27
|
+
if (!bf.summary) continue;
|
|
28
|
+
const { cleanSummary, overrides } = extractSummaryMeta(bf.summary);
|
|
29
|
+
const gitInfo = resolveBumpFileInfo(bf.id, repoSlug, serverUrl, overrides);
|
|
30
|
+
const summaryLines = cleanSummary.split("\n");
|
|
31
|
+
const firstLine = linkifyIssueRefs(summaryLines[0], serverUrl, repoSlug);
|
|
32
|
+
const prefix = formatPrefix(gitInfo, serverUrl, repoSlug, thankContributors, internalAuthorsSet);
|
|
33
|
+
lines.push(`-${prefix ? ` ${prefix} -` : ""} ${firstLine}`);
|
|
34
|
+
for (let i = 1; i < summaryLines.length; i++) if (summaryLines[i].trim()) lines.push(` ${linkifyIssueRefs(summaryLines[i], serverUrl, repoSlug)}`);
|
|
35
|
+
}
|
|
36
|
+
if (release.isDependencyBump && relevantBumpFiles.length === 0) lines.push("- Updated dependencies");
|
|
37
|
+
if (release.isCascadeBump && !release.isDependencyBump && relevantBumpFiles.length === 0) lines.push("- Version bump via cascade rule");
|
|
38
|
+
lines.push("");
|
|
39
|
+
return lines.join("\n");
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Extract metadata lines (pr, commit, author) from a bump file summary.
|
|
44
|
+
* These override git-derived info, matching the behavior of @changesets/changelog-github.
|
|
45
|
+
*/
|
|
46
|
+
function extractSummaryMeta(summary) {
|
|
47
|
+
const overrides = {};
|
|
48
|
+
return {
|
|
49
|
+
cleanSummary: summary.replace(/^\s*(?:pr|pull|pull\s+request):\s*#?(\d+)/im, (_, pr) => {
|
|
50
|
+
const num = Number(pr);
|
|
51
|
+
if (!isNaN(num)) overrides.pr = num;
|
|
52
|
+
return "";
|
|
53
|
+
}).replace(/^\s*commit:\s*([^\s]+)/im, (_, commit) => {
|
|
54
|
+
overrides.commit = commit;
|
|
55
|
+
return "";
|
|
56
|
+
}).replace(/^\s*(?:author|user):\s*@?([^\s]+)/gim, (_, user) => {
|
|
57
|
+
overrides.authors ??= [];
|
|
58
|
+
overrides.authors.push(user);
|
|
59
|
+
return "";
|
|
60
|
+
}).trim(),
|
|
61
|
+
overrides
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolve PR, commit, and author info for a bump file.
|
|
66
|
+
* Summary overrides take precedence over git-derived info.
|
|
67
|
+
*/
|
|
68
|
+
function resolveBumpFileInfo(bumpFileId, repo, serverUrl, overrides) {
|
|
69
|
+
if (overrides.pr !== void 0) {
|
|
70
|
+
const prInfo = lookupPr(overrides.pr, repo);
|
|
71
|
+
return {
|
|
72
|
+
prNumber: overrides.pr,
|
|
73
|
+
prUrl: prInfo?.url ?? `${serverUrl}/${repo}/pull/${overrides.pr}`,
|
|
74
|
+
commitHash: overrides.commit ?? prInfo?.commitHash,
|
|
75
|
+
author: overrides.authors?.[0] ?? prInfo?.author
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const gitInfo = findBumpFileCommitInfo(bumpFileId, repo);
|
|
79
|
+
return {
|
|
80
|
+
prNumber: gitInfo?.prNumber,
|
|
81
|
+
prUrl: gitInfo?.prUrl,
|
|
82
|
+
commitHash: overrides.commit ?? gitInfo?.commitHash,
|
|
83
|
+
author: overrides.authors?.[0] ?? gitInfo?.author
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** Look up a PR by number using gh CLI */
|
|
87
|
+
function lookupPr(prNumber, repo) {
|
|
88
|
+
try {
|
|
89
|
+
const ghArgs = [
|
|
90
|
+
"gh",
|
|
91
|
+
"pr",
|
|
92
|
+
"view",
|
|
93
|
+
String(prNumber),
|
|
94
|
+
"--json",
|
|
95
|
+
"url,author,mergeCommit"
|
|
96
|
+
];
|
|
97
|
+
if (repo) ghArgs.push("--repo", repo);
|
|
98
|
+
const result = tryRunArgs(ghArgs);
|
|
99
|
+
if (!result) return null;
|
|
100
|
+
const pr = JSON.parse(result);
|
|
101
|
+
return {
|
|
102
|
+
url: pr.url,
|
|
103
|
+
author: pr.author?.login,
|
|
104
|
+
commitHash: pr.mergeCommit?.oid
|
|
105
|
+
};
|
|
106
|
+
} catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Find the PR that introduced a bump file by checking git log
|
|
112
|
+
* for the commit that added the file, then looking up the PR.
|
|
113
|
+
*/
|
|
114
|
+
function findBumpFileCommitInfo(bumpFileId, repo) {
|
|
115
|
+
try {
|
|
116
|
+
const commitOutput = tryRunArgs([
|
|
117
|
+
"git",
|
|
118
|
+
"log",
|
|
119
|
+
"--diff-filter=A",
|
|
120
|
+
"--format=%H",
|
|
121
|
+
"--",
|
|
122
|
+
`.bumpy/${bumpFileId}.md`,
|
|
123
|
+
`.changeset/${bumpFileId}.md`
|
|
124
|
+
]);
|
|
125
|
+
if (!commitOutput) return null;
|
|
126
|
+
const commitHash = commitOutput.split("\n")[0].trim();
|
|
127
|
+
if (!commitHash) return null;
|
|
128
|
+
const ghArgs = [
|
|
129
|
+
"gh",
|
|
130
|
+
"pr",
|
|
131
|
+
"list",
|
|
132
|
+
"--search",
|
|
133
|
+
commitHash,
|
|
134
|
+
"--state",
|
|
135
|
+
"merged",
|
|
136
|
+
"--json",
|
|
137
|
+
"number,url,author",
|
|
138
|
+
"--jq",
|
|
139
|
+
".[0]"
|
|
140
|
+
];
|
|
141
|
+
if (repo) ghArgs.push("--repo", repo);
|
|
142
|
+
const prJson = tryRunArgs(ghArgs);
|
|
143
|
+
if (!prJson) return { commitHash };
|
|
144
|
+
const pr = JSON.parse(prJson);
|
|
145
|
+
if (!pr.number) return { commitHash };
|
|
146
|
+
return {
|
|
147
|
+
prNumber: pr.number,
|
|
148
|
+
prUrl: pr.url,
|
|
149
|
+
commitHash,
|
|
150
|
+
author: pr.author?.login
|
|
151
|
+
};
|
|
152
|
+
} catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Build the prefix portion of a changelog line: PR link, commit link, thanks.
|
|
158
|
+
* Matches the format used by @changesets/changelog-github.
|
|
159
|
+
*/
|
|
160
|
+
function formatPrefix(info, serverUrl, repo, thankContributors, internalAuthors) {
|
|
161
|
+
const parts = [];
|
|
162
|
+
if (info.prNumber && info.prUrl) parts.push(`[#${info.prNumber}](${info.prUrl})`);
|
|
163
|
+
if (info.commitHash && repo) {
|
|
164
|
+
const short = info.commitHash.slice(0, 7);
|
|
165
|
+
parts.push(`[\`${short}\`](${serverUrl}/${repo}/commit/${info.commitHash})`);
|
|
166
|
+
}
|
|
167
|
+
if (thankContributors && info.author && !internalAuthors.has(info.author.toLowerCase())) parts.push(`Thanks [@${info.author}](${serverUrl}/${info.author})!`);
|
|
168
|
+
return parts.join(" ");
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Linkify bare issue/PR references like #123 in text,
|
|
172
|
+
* but skip references already inside markdown links.
|
|
173
|
+
*/
|
|
174
|
+
function linkifyIssueRefs(line, serverUrl, repo) {
|
|
175
|
+
if (!repo) return line;
|
|
176
|
+
return line.replace(/\[.*?\]\(.*?\)|\B#([1-9]\d*)\b/g, (match, issue) => issue ? `[#${issue}](${serverUrl}/${repo}/issues/${issue})` : match);
|
|
177
|
+
}
|
|
178
|
+
/** Try to detect the repo slug from the gh CLI */
|
|
179
|
+
function detectRepo() {
|
|
180
|
+
try {
|
|
181
|
+
return tryRunArgs([
|
|
182
|
+
"gh",
|
|
183
|
+
"repo",
|
|
184
|
+
"view",
|
|
185
|
+
"--json",
|
|
186
|
+
"nameWithOwner",
|
|
187
|
+
"--jq",
|
|
188
|
+
".nameWithOwner"
|
|
189
|
+
])?.trim() || void 0;
|
|
190
|
+
} catch {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//#endregion
|
|
195
|
+
export { createGithubFormatter };
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { n as log, t as colorize } from "./logger-
|
|
2
|
-
import { a as loadConfig } from "./config-
|
|
3
|
-
import { n as discoverWorkspace } from "./workspace-
|
|
4
|
-
import { r as
|
|
5
|
-
import {
|
|
1
|
+
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
2
|
+
import { a as loadConfig } from "./config-XZWUL3ma.mjs";
|
|
3
|
+
import { n as discoverWorkspace } from "./workspace-C5ULTyUN.mjs";
|
|
4
|
+
import { r as readBumpFiles } from "./bump-file-CCLXMLA8.mjs";
|
|
5
|
+
import { n as getChangedFiles } from "./git-CGHVXXKw.mjs";
|
|
6
6
|
import { relative } from "node:path";
|
|
7
7
|
//#region src/commands/check.ts
|
|
8
8
|
/**
|
|
9
9
|
* Local check: detect which packages have changed on this branch
|
|
10
|
-
* and verify they have corresponding
|
|
10
|
+
* and verify they have corresponding bump files.
|
|
11
11
|
* Designed for pre-push hooks — no GitHub API needed.
|
|
12
12
|
*/
|
|
13
13
|
async function checkCommand(rootDir) {
|
|
14
14
|
const config = await loadConfig(rootDir);
|
|
15
15
|
const { packages } = await discoverWorkspace(rootDir, config);
|
|
16
|
-
const
|
|
16
|
+
const bumpFiles = await readBumpFiles(rootDir);
|
|
17
17
|
const coveredPackages = /* @__PURE__ */ new Set();
|
|
18
|
-
for (const
|
|
18
|
+
for (const bf of bumpFiles) for (const release of bf.releases) coveredPackages.add(release.name);
|
|
19
19
|
const baseBranch = config.baseBranch;
|
|
20
20
|
const changedFiles = getChangedFiles(rootDir, baseBranch);
|
|
21
21
|
if (changedFiles.length === 0) {
|
|
@@ -29,21 +29,15 @@ async function checkCommand(rootDir) {
|
|
|
29
29
|
}
|
|
30
30
|
const missing = changedPackages.filter((name) => !coveredPackages.has(name));
|
|
31
31
|
if (missing.length === 0) {
|
|
32
|
-
log.success(`All ${changedPackages.length} changed package(s) have
|
|
32
|
+
log.success(`All ${changedPackages.length} changed package(s) have bump files.`);
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
-
log.warn(`${missing.length} changed package(s) missing
|
|
35
|
+
log.warn(`${missing.length} changed package(s) missing bump files:\n`);
|
|
36
36
|
for (const name of missing) console.log(` ${colorize(name, "yellow")}`);
|
|
37
37
|
console.log();
|
|
38
|
-
log.dim("Run `bumpy add` to create a
|
|
38
|
+
log.dim("Run `bumpy add` to create a bump file, or `bumpy add --empty` if no release is needed.");
|
|
39
39
|
process.exit(1);
|
|
40
40
|
}
|
|
41
|
-
/** Get files changed on this branch compared to the base branch */
|
|
42
|
-
function getChangedFiles(rootDir, baseBranch) {
|
|
43
|
-
const diff = tryRun(`git diff --name-only ${tryRun(`git merge-base HEAD origin/${baseBranch}`, { cwd: rootDir }) || `origin/${baseBranch}`}`, { cwd: rootDir });
|
|
44
|
-
if (!diff) return [];
|
|
45
|
-
return diff.split("\n").filter(Boolean);
|
|
46
|
-
}
|
|
47
41
|
/** Map changed files to the packages they belong to */
|
|
48
42
|
function findChangedPackages(changedFiles, packages, rootDir) {
|
|
49
43
|
const changed = /* @__PURE__ */ new Set();
|