pubz 0.4.1 → 0.5.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/dist/cli.js +72 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -97,6 +97,7 @@ async function discoverPackages(cwd) {
|
|
|
97
97
|
const rootPackageJson = await readPackageJson(rootPackageJsonPath);
|
|
98
98
|
const workspacePatterns = getWorkspacePatterns(rootPackageJson);
|
|
99
99
|
let packageDirs = [];
|
|
100
|
+
const rootIsPublishable = !rootPackageJson.private && rootPackageJson.name && rootPackageJson.version;
|
|
100
101
|
if (workspacePatterns.length > 0) {
|
|
101
102
|
for (const pattern of workspacePatterns) {
|
|
102
103
|
const matches = await glob(pattern, cwd);
|
|
@@ -118,6 +119,10 @@ async function discoverPackages(cwd) {
|
|
|
118
119
|
}
|
|
119
120
|
const packages = [];
|
|
120
121
|
const packageNames = new Set;
|
|
122
|
+
if (rootIsPublishable) {
|
|
123
|
+
packageNames.add(rootPackageJson.name);
|
|
124
|
+
packages.push(await packageFromPath(cwd, rootPackageJsonPath, rootPackageJson, []));
|
|
125
|
+
}
|
|
121
126
|
for (const dir of packageDirs) {
|
|
122
127
|
const pkgPath = resolve(cwd, dir);
|
|
123
128
|
const pkgJsonPath = join2(pkgPath, "package.json");
|
|
@@ -552,6 +557,10 @@ async function pushGitTag(version, cwd, dryRun) {
|
|
|
552
557
|
console.log(`[DRY RUN] Would push git tag: ${tagName}`);
|
|
553
558
|
return { success: true };
|
|
554
559
|
}
|
|
560
|
+
const branchResult = await run("git", ["push"], cwd);
|
|
561
|
+
if (branchResult.code !== 0) {
|
|
562
|
+
return { success: false, error: "Failed to push bump commit to origin" };
|
|
563
|
+
}
|
|
555
564
|
const result = await run("git", ["push", "origin", tagName], cwd);
|
|
556
565
|
if (result.code !== 0) {
|
|
557
566
|
return { success: false, error: `Failed to push tag ${tagName}` };
|
|
@@ -621,15 +630,18 @@ async function getCommitsSince(ref, cwd) {
|
|
|
621
630
|
function isReleaseCommit(message) {
|
|
622
631
|
return /^chore: release v/.test(message);
|
|
623
632
|
}
|
|
633
|
+
function isMergeCommit(message) {
|
|
634
|
+
return /^Merge /.test(message);
|
|
635
|
+
}
|
|
624
636
|
function formatChangelogTerminal(commits) {
|
|
625
|
-
const filtered = commits.filter((c) => !isReleaseCommit(c.message));
|
|
637
|
+
const filtered = commits.filter((c) => !isReleaseCommit(c.message) && !isMergeCommit(c.message));
|
|
626
638
|
if (filtered.length === 0)
|
|
627
639
|
return "";
|
|
628
640
|
return filtered.map((c) => ` ${dim(c.sha)} ${c.message}`).join(`
|
|
629
641
|
`);
|
|
630
642
|
}
|
|
631
643
|
function formatChangelogMarkdown(commits, repoUrl) {
|
|
632
|
-
const filtered = commits.filter((c) => !isReleaseCommit(c.message));
|
|
644
|
+
const filtered = commits.filter((c) => !isReleaseCommit(c.message) && !isMergeCommit(c.message));
|
|
633
645
|
if (filtered.length === 0)
|
|
634
646
|
return "";
|
|
635
647
|
return filtered.map((c) => {
|
|
@@ -655,6 +667,40 @@ async function generateChangelog(cwd) {
|
|
|
655
667
|
const markdown = formatChangelogMarkdown(commits, repoUrl);
|
|
656
668
|
return { commits, terminal, markdown, previousTag, repoUrl };
|
|
657
669
|
}
|
|
670
|
+
async function isClaudeAvailable() {
|
|
671
|
+
const result = await runSilent("which", ["claude"], process.cwd());
|
|
672
|
+
return result.code === 0;
|
|
673
|
+
}
|
|
674
|
+
async function generateAIReleaseNotes(commits, version) {
|
|
675
|
+
const filtered = commits.filter((c) => !isReleaseCommit(c.message));
|
|
676
|
+
if (filtered.length === 0)
|
|
677
|
+
return null;
|
|
678
|
+
const commitList = filtered.map((c) => `- ${c.sha} ${c.message}`).join(`
|
|
679
|
+
`);
|
|
680
|
+
const prompt2 = `You are writing release notes for version ${version} of a software package.
|
|
681
|
+
|
|
682
|
+
Here are the commits included in this release:
|
|
683
|
+
${commitList}
|
|
684
|
+
|
|
685
|
+
Write concise, user-friendly release notes in markdown. Group related changes under headings if appropriate (e.g. Features, Bug Fixes, Improvements). Focus on what changed and why it matters to users — not implementation details. Do not include a title or version header. Output only the markdown body.`;
|
|
686
|
+
return new Promise((resolve2) => {
|
|
687
|
+
const proc = spawn3("claude", ["-p", prompt2], {
|
|
688
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
689
|
+
});
|
|
690
|
+
let output = "";
|
|
691
|
+
proc.stdout?.on("data", (data) => {
|
|
692
|
+
output += data.toString();
|
|
693
|
+
});
|
|
694
|
+
proc.on("close", (code) => {
|
|
695
|
+
if (code === 0 && output.trim()) {
|
|
696
|
+
resolve2(output.trim());
|
|
697
|
+
} else {
|
|
698
|
+
resolve2(null);
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
proc.on("error", () => resolve2(null));
|
|
702
|
+
});
|
|
703
|
+
}
|
|
658
704
|
async function createGitHubRelease(version, body, cwd, dryRun) {
|
|
659
705
|
const tagName = `v${version}`;
|
|
660
706
|
if (dryRun) {
|
|
@@ -1231,6 +1277,26 @@ async function main() {
|
|
|
1231
1277
|
console.log(changelog.terminal);
|
|
1232
1278
|
console.log("");
|
|
1233
1279
|
}
|
|
1280
|
+
let releaseNotes = changelog.markdown;
|
|
1281
|
+
if (!options.ci && changelog.commits.length > 0) {
|
|
1282
|
+
const claudeAvailable = await isClaudeAvailable();
|
|
1283
|
+
if (claudeAvailable) {
|
|
1284
|
+
const useAI = await confirm("Generate release notes with AI (claude)?");
|
|
1285
|
+
if (useAI) {
|
|
1286
|
+
console.log(cyan("Generating AI release notes..."));
|
|
1287
|
+
const aiNotes = await generateAIReleaseNotes(changelog.commits, newVersion);
|
|
1288
|
+
if (aiNotes) {
|
|
1289
|
+
releaseNotes = aiNotes;
|
|
1290
|
+
console.log("");
|
|
1291
|
+
console.log(bold("AI-generated release notes:"));
|
|
1292
|
+
console.log(aiNotes);
|
|
1293
|
+
console.log("");
|
|
1294
|
+
} else {
|
|
1295
|
+
console.log(yellow("AI generation failed, falling back to commit list."));
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1234
1300
|
if (!options.dryRun) {
|
|
1235
1301
|
if (options.ci) {
|
|
1236
1302
|
console.log(cyan("Creating git tag..."));
|
|
@@ -1238,9 +1304,9 @@ async function main() {
|
|
|
1238
1304
|
if (tagResult.success) {
|
|
1239
1305
|
console.log(cyan("Pushing tag to origin..."));
|
|
1240
1306
|
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1241
|
-
if (
|
|
1307
|
+
if (releaseNotes) {
|
|
1242
1308
|
console.log(cyan("Creating GitHub release..."));
|
|
1243
|
-
const releaseResult = await createGitHubRelease(newVersion,
|
|
1309
|
+
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1244
1310
|
if (releaseResult.success && releaseResult.url) {
|
|
1245
1311
|
console.log(` Release created: ${cyan(releaseResult.url)}`);
|
|
1246
1312
|
} else if (!releaseResult.success) {
|
|
@@ -1260,10 +1326,10 @@ async function main() {
|
|
|
1260
1326
|
const shouldPush = skipConfirms || await confirm("Push tag to origin?");
|
|
1261
1327
|
if (shouldPush) {
|
|
1262
1328
|
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1263
|
-
if (
|
|
1329
|
+
if (releaseNotes) {
|
|
1264
1330
|
const shouldRelease = skipConfirms || await confirm("Create a GitHub release?");
|
|
1265
1331
|
if (shouldRelease) {
|
|
1266
|
-
const releaseResult = await createGitHubRelease(newVersion,
|
|
1332
|
+
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1267
1333
|
if (releaseResult.success && releaseResult.url) {
|
|
1268
1334
|
console.log(` Release created: ${cyan(releaseResult.url)}`);
|
|
1269
1335
|
} else if (!releaseResult.success) {
|