pubz 0.4.1 → 0.5.1
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 +86 -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,54 @@ 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
|
+
let stderr = "";
|
|
692
|
+
proc.stdout?.on("data", (data) => {
|
|
693
|
+
output += data.toString();
|
|
694
|
+
});
|
|
695
|
+
proc.stderr?.on("data", (data) => {
|
|
696
|
+
stderr += data.toString();
|
|
697
|
+
});
|
|
698
|
+
proc.on("close", (code) => {
|
|
699
|
+
if (code === 0 && output.trim()) {
|
|
700
|
+
resolve2(output.trim());
|
|
701
|
+
} else {
|
|
702
|
+
debug(`claude CLI exited with code ${code}`);
|
|
703
|
+
if (stderr.trim()) {
|
|
704
|
+
debug(`claude stderr: ${stderr.trim()}`);
|
|
705
|
+
}
|
|
706
|
+
if (!output.trim() && code === 0) {
|
|
707
|
+
debug("claude CLI returned empty output");
|
|
708
|
+
}
|
|
709
|
+
resolve2(null);
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
proc.on("error", (err) => {
|
|
713
|
+
debug(`Failed to spawn claude CLI: ${err.message}`);
|
|
714
|
+
resolve2(null);
|
|
715
|
+
});
|
|
716
|
+
});
|
|
717
|
+
}
|
|
658
718
|
async function createGitHubRelease(version, body, cwd, dryRun) {
|
|
659
719
|
const tagName = `v${version}`;
|
|
660
720
|
if (dryRun) {
|
|
@@ -1231,6 +1291,26 @@ async function main() {
|
|
|
1231
1291
|
console.log(changelog.terminal);
|
|
1232
1292
|
console.log("");
|
|
1233
1293
|
}
|
|
1294
|
+
let releaseNotes = changelog.markdown;
|
|
1295
|
+
if (!options.ci && changelog.commits.length > 0) {
|
|
1296
|
+
const claudeAvailable = await isClaudeAvailable();
|
|
1297
|
+
if (claudeAvailable) {
|
|
1298
|
+
const useAI = await confirm("Generate release notes with AI (claude)?");
|
|
1299
|
+
if (useAI) {
|
|
1300
|
+
console.log(cyan("Generating AI release notes..."));
|
|
1301
|
+
const aiNotes = await generateAIReleaseNotes(changelog.commits, newVersion);
|
|
1302
|
+
if (aiNotes) {
|
|
1303
|
+
releaseNotes = aiNotes;
|
|
1304
|
+
console.log("");
|
|
1305
|
+
console.log(bold("AI-generated release notes:"));
|
|
1306
|
+
console.log(aiNotes);
|
|
1307
|
+
console.log("");
|
|
1308
|
+
} else {
|
|
1309
|
+
console.log(yellow("AI generation failed, falling back to commit list.") + dim(" (run with --verbose for details)"));
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1234
1314
|
if (!options.dryRun) {
|
|
1235
1315
|
if (options.ci) {
|
|
1236
1316
|
console.log(cyan("Creating git tag..."));
|
|
@@ -1238,9 +1318,9 @@ async function main() {
|
|
|
1238
1318
|
if (tagResult.success) {
|
|
1239
1319
|
console.log(cyan("Pushing tag to origin..."));
|
|
1240
1320
|
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1241
|
-
if (
|
|
1321
|
+
if (releaseNotes) {
|
|
1242
1322
|
console.log(cyan("Creating GitHub release..."));
|
|
1243
|
-
const releaseResult = await createGitHubRelease(newVersion,
|
|
1323
|
+
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1244
1324
|
if (releaseResult.success && releaseResult.url) {
|
|
1245
1325
|
console.log(` Release created: ${cyan(releaseResult.url)}`);
|
|
1246
1326
|
} else if (!releaseResult.success) {
|
|
@@ -1260,10 +1340,10 @@ async function main() {
|
|
|
1260
1340
|
const shouldPush = skipConfirms || await confirm("Push tag to origin?");
|
|
1261
1341
|
if (shouldPush) {
|
|
1262
1342
|
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1263
|
-
if (
|
|
1343
|
+
if (releaseNotes) {
|
|
1264
1344
|
const shouldRelease = skipConfirms || await confirm("Create a GitHub release?");
|
|
1265
1345
|
if (shouldRelease) {
|
|
1266
|
-
const releaseResult = await createGitHubRelease(newVersion,
|
|
1346
|
+
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1267
1347
|
if (releaseResult.success && releaseResult.url) {
|
|
1268
1348
|
console.log(` Release created: ${cyan(releaseResult.url)}`);
|
|
1269
1349
|
} else if (!releaseResult.success) {
|