pubz 0.4.0 → 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/README.md +60 -51
- package/dist/cli.js +106 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ bunx pubz
|
|
|
21
21
|
9. Transforms `workspace:` definitions to hard version numbers (so `npm` can be used for publishing with OIDC support).
|
|
22
22
|
10. Publishes to npm
|
|
23
23
|
11. Prompts you to create a `git tag` and push it
|
|
24
|
+
12. Generates a changelog and creates a GitHub Release
|
|
24
25
|
|
|
25
26
|
## Options
|
|
26
27
|
|
|
@@ -186,49 +187,35 @@ Discovering packages...
|
|
|
186
187
|
|
|
187
188
|
Found 1 publishable package(s):
|
|
188
189
|
|
|
189
|
-
• pubz@0.
|
|
190
|
+
• pubz@0.4.0
|
|
190
191
|
|
|
191
192
|
Step 1: Version Management
|
|
192
193
|
──────────────────────────────
|
|
193
194
|
|
|
194
|
-
Current version: 0.
|
|
195
|
-
|
|
196
|
-
? Bump version before publishing? [Y/n]
|
|
197
|
-
? Select version bump type:
|
|
198
|
-
|
|
199
|
-
> 1) patch (0.2.2 -> 0.2.3)
|
|
200
|
-
2) minor (0.2.2 -> 0.3.0)
|
|
201
|
-
3) major (0.2.2 -> 1.0.0)
|
|
202
|
-
|
|
203
|
-
Enter choice [1-3] (default: 1): 1
|
|
204
|
-
|
|
205
|
-
Updating version to 0.2.3 in all packages...
|
|
206
|
-
|
|
207
|
-
Updated pubz: 0.2.2 -> 0.2.3
|
|
208
|
-
M package.json
|
|
209
|
-
Committing version bump...
|
|
210
|
-
[main 945e1a3] chore: release v0.2.3
|
|
211
|
-
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
212
|
-
Changes committed
|
|
195
|
+
Current version: 0.4.0
|
|
213
196
|
|
|
197
|
+
? Bump version before publishing? [Y/n] n
|
|
214
198
|
? Select publish target:
|
|
215
199
|
|
|
216
200
|
> 1) Public npm registry (https://registry.npmjs.org)
|
|
217
201
|
2) GitHub Packages (https://npm.pkg.github.com)
|
|
218
202
|
|
|
219
|
-
Enter choice [1-2] (default: 1):
|
|
203
|
+
Enter choice [1-2] (default: 1):
|
|
220
204
|
|
|
221
205
|
Publishing to: https://registry.npmjs.org
|
|
222
206
|
|
|
207
|
+
Verifying npm authentication...
|
|
208
|
+
Authenticated as zdavison
|
|
209
|
+
|
|
223
210
|
Step 2: Building Packages
|
|
224
211
|
──────────────────────────────
|
|
225
212
|
|
|
226
213
|
Running build...
|
|
227
214
|
|
|
228
215
|
$ bun build src/cli.ts --outdir dist --target node
|
|
229
|
-
Bundled
|
|
216
|
+
Bundled 10 modules in 5ms
|
|
230
217
|
|
|
231
|
-
cli.js
|
|
218
|
+
cli.js 41.27 KB (entry point)
|
|
232
219
|
|
|
233
220
|
|
|
234
221
|
Build completed successfully
|
|
@@ -242,46 +229,68 @@ Step 3: Publishing to npm
|
|
|
242
229
|
|
|
243
230
|
About to publish the following packages:
|
|
244
231
|
|
|
245
|
-
• pubz@0.
|
|
232
|
+
• pubz@0.4.0
|
|
246
233
|
|
|
247
234
|
Registry: https://registry.npmjs.org
|
|
248
235
|
|
|
249
|
-
? Continue? [Y/n]
|
|
236
|
+
? Continue? [Y/n]
|
|
237
|
+
|
|
238
|
+
Preparing packages for publish...
|
|
250
239
|
|
|
251
240
|
Publishing packages...
|
|
252
241
|
|
|
253
|
-
Publishing pubz@0.
|
|
254
|
-
npm notice
|
|
255
|
-
npm notice 📦 pubz@0.
|
|
256
|
-
npm notice Tarball Contents
|
|
257
|
-
npm notice
|
|
258
|
-
npm notice
|
|
259
|
-
npm notice
|
|
260
|
-
npm notice Tarball Details
|
|
261
|
-
npm notice name: pubz
|
|
262
|
-
npm notice version: 0.
|
|
263
|
-
npm notice filename: pubz-0.
|
|
264
|
-
npm notice package size:
|
|
265
|
-
npm notice unpacked size:
|
|
266
|
-
npm notice shasum:
|
|
267
|
-
npm notice integrity: sha512-
|
|
268
|
-
npm notice total files: 3
|
|
269
|
-
npm notice
|
|
270
|
-
|
|
242
|
+
Publishing pubz@0.4.0...
|
|
243
|
+
npm notice
|
|
244
|
+
npm notice 📦 pubz@0.4.0
|
|
245
|
+
npm notice === Tarball Contents ===
|
|
246
|
+
npm notice 7.1kB README.md
|
|
247
|
+
npm notice 41.3kB dist/cli.js
|
|
248
|
+
npm notice 697B package.json
|
|
249
|
+
npm notice === Tarball Details ===
|
|
250
|
+
npm notice name: pubz
|
|
251
|
+
npm notice version: 0.4.0
|
|
252
|
+
npm notice filename: pubz-0.4.0.tgz
|
|
253
|
+
npm notice package size: 12.0 kB
|
|
254
|
+
npm notice unpacked size: 49.1 kB
|
|
255
|
+
npm notice shasum: 3026a7936458dcaa84030a0ce2e206b9f74aa65d
|
|
256
|
+
npm notice integrity: sha512-6vKMOsC7sZa87[...]w8KNx1fD45u/A==
|
|
257
|
+
npm notice total files: 3
|
|
258
|
+
npm notice
|
|
259
|
+
npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access
|
|
260
|
+
Authenticate your account at:
|
|
261
|
+
https://www.npmjs.com/auth/cli/c47d9bee-2a1e-4adf-9aab-63d15acfade2
|
|
262
|
+
Press ENTER to open in the browser...
|
|
263
|
+
|
|
264
|
+
+ pubz@0.4.0
|
|
271
265
|
pubz published successfully
|
|
272
266
|
|
|
273
267
|
══════════════════════════════
|
|
274
268
|
Publishing complete!
|
|
275
269
|
|
|
276
|
-
Published version: 0.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
270
|
+
Published version: 0.4.0
|
|
271
|
+
|
|
272
|
+
Changes since v0.2.12:
|
|
273
|
+
5553c95 Fix ENTER to open browser not working.
|
|
274
|
+
9aaddff Fix tag/push/release branch when using --yes.
|
|
275
|
+
0ce3ab8 Generate changlog and attach it to release page / print it out during publish.
|
|
276
|
+
5a29ca4 Merge branch 'main' of github.com:mm-zacharydavison/pubz
|
|
277
|
+
b4c47fc Clean up README.md formatting
|
|
278
|
+
2da403c Update README.md
|
|
279
|
+
88a4211 Update README with image and usage instructions
|
|
280
|
+
8a8148a Update README.md
|
|
281
|
+
2b45d21 Transform 'workspace:' definitions on publish, and restore them before any commit.
|
|
282
|
+
|
|
283
|
+
? Create a git tag for v0.4.0? [Y/n]
|
|
284
|
+
|
|
285
|
+
Tag v0.4.0 created
|
|
286
|
+
? Push tag to origin? [Y/n]
|
|
287
|
+
remote: This repository moved. Please use the new location:
|
|
288
|
+
remote: git@github.com:zdavison/pubz.git
|
|
282
289
|
To github.com:mm-zacharydavison/pubz.git
|
|
283
|
-
* [new tag] v0.
|
|
284
|
-
Tag v0.
|
|
290
|
+
* [new tag] v0.4.0 -> v0.4.0
|
|
291
|
+
Tag v0.4.0 pushed to origin
|
|
292
|
+
? Create a GitHub release? [Y/n]
|
|
293
|
+
Release created: https://github.com/zdavison/pubz/releases/tag/v0.4.0
|
|
285
294
|
|
|
286
295
|
Done!
|
|
287
296
|
```
|
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) => {
|
|
@@ -638,7 +650,11 @@ function formatChangelogMarkdown(commits, repoUrl) {
|
|
|
638
650
|
}).join(`
|
|
639
651
|
`);
|
|
640
652
|
}
|
|
653
|
+
async function fetchTags(cwd) {
|
|
654
|
+
await runSilent("git", ["fetch", "--tags"], cwd);
|
|
655
|
+
}
|
|
641
656
|
async function generateChangelog(cwd) {
|
|
657
|
+
await fetchTags(cwd);
|
|
642
658
|
const [previousTag, repoUrl] = await Promise.all([
|
|
643
659
|
getPreviousTag(cwd),
|
|
644
660
|
getRepoUrl(cwd)
|
|
@@ -651,6 +667,40 @@ async function generateChangelog(cwd) {
|
|
|
651
667
|
const markdown = formatChangelogMarkdown(commits, repoUrl);
|
|
652
668
|
return { commits, terminal, markdown, previousTag, repoUrl };
|
|
653
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
|
+
}
|
|
654
704
|
async function createGitHubRelease(version, body, cwd, dryRun) {
|
|
655
705
|
const tagName = `v${version}`;
|
|
656
706
|
if (dryRun) {
|
|
@@ -738,6 +788,9 @@ async function restoreWorkspaceProtocol(transforms) {
|
|
|
738
788
|
console.log(` Restored workspace references in ${byPath.size} package(s)`);
|
|
739
789
|
}
|
|
740
790
|
}
|
|
791
|
+
function isValidVersion(version) {
|
|
792
|
+
return /^\d+\.\d+\.\d+(-.+)?$/.test(version);
|
|
793
|
+
}
|
|
741
794
|
function bumpVersion(version, type) {
|
|
742
795
|
if (type === "none")
|
|
743
796
|
return version;
|
|
@@ -988,7 +1041,13 @@ async function main() {
|
|
|
988
1041
|
newVersion = bumpVersion(currentVersion, options.version);
|
|
989
1042
|
console.log(`Bumping version (${options.version}): ${yellow(currentVersion)} → ${green(newVersion)}`);
|
|
990
1043
|
} else {
|
|
991
|
-
|
|
1044
|
+
const cleaned = options.version.startsWith("v") ? options.version.slice(1) : options.version;
|
|
1045
|
+
if (!isValidVersion(cleaned)) {
|
|
1046
|
+
console.error(red(bold("Error:")) + ` Invalid version "${options.version}". Expected format: major.minor.patch (e.g. 1.2.3, 1.2.3-beta)`);
|
|
1047
|
+
closePrompt();
|
|
1048
|
+
process.exit(1);
|
|
1049
|
+
}
|
|
1050
|
+
newVersion = cleaned;
|
|
992
1051
|
console.log(`Using explicit version: ${green(newVersion)}`);
|
|
993
1052
|
}
|
|
994
1053
|
console.log("");
|
|
@@ -1011,7 +1070,7 @@ async function main() {
|
|
|
1011
1070
|
} else if (!skipAllPrompts) {
|
|
1012
1071
|
const shouldBump = skipConfirms || await confirm("Bump version before publishing?");
|
|
1013
1072
|
if (shouldBump) {
|
|
1014
|
-
const
|
|
1073
|
+
const bumpChoice = await select("Select version bump type:", [
|
|
1015
1074
|
{
|
|
1016
1075
|
label: `patch (${previewBump(currentVersion, "patch")})`,
|
|
1017
1076
|
value: "patch"
|
|
@@ -1023,9 +1082,27 @@ async function main() {
|
|
|
1023
1082
|
{
|
|
1024
1083
|
label: `major (${previewBump(currentVersion, "major")})`,
|
|
1025
1084
|
value: "major"
|
|
1085
|
+
},
|
|
1086
|
+
{
|
|
1087
|
+
label: "custom version",
|
|
1088
|
+
value: "custom"
|
|
1026
1089
|
}
|
|
1027
1090
|
]);
|
|
1028
|
-
|
|
1091
|
+
if (bumpChoice === "custom") {
|
|
1092
|
+
let customVersion = "";
|
|
1093
|
+
while (!customVersion) {
|
|
1094
|
+
const input = await prompt(` Enter version: `);
|
|
1095
|
+
const cleaned = input.startsWith("v") ? input.slice(1) : input;
|
|
1096
|
+
if (isValidVersion(cleaned)) {
|
|
1097
|
+
customVersion = cleaned;
|
|
1098
|
+
} else {
|
|
1099
|
+
console.log(yellow(" Invalid version. Expected format: major.minor.patch (e.g. 1.2.3, 1.2.3-beta)"));
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
newVersion = customVersion;
|
|
1103
|
+
} else {
|
|
1104
|
+
newVersion = bumpVersion(currentVersion, bumpChoice);
|
|
1105
|
+
}
|
|
1029
1106
|
console.log("");
|
|
1030
1107
|
console.log(`Updating version to ${green(newVersion)} in all packages...`);
|
|
1031
1108
|
console.log("");
|
|
@@ -1200,6 +1277,26 @@ async function main() {
|
|
|
1200
1277
|
console.log(changelog.terminal);
|
|
1201
1278
|
console.log("");
|
|
1202
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
|
+
}
|
|
1203
1300
|
if (!options.dryRun) {
|
|
1204
1301
|
if (options.ci) {
|
|
1205
1302
|
console.log(cyan("Creating git tag..."));
|
|
@@ -1207,9 +1304,9 @@ async function main() {
|
|
|
1207
1304
|
if (tagResult.success) {
|
|
1208
1305
|
console.log(cyan("Pushing tag to origin..."));
|
|
1209
1306
|
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1210
|
-
if (
|
|
1307
|
+
if (releaseNotes) {
|
|
1211
1308
|
console.log(cyan("Creating GitHub release..."));
|
|
1212
|
-
const releaseResult = await createGitHubRelease(newVersion,
|
|
1309
|
+
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1213
1310
|
if (releaseResult.success && releaseResult.url) {
|
|
1214
1311
|
console.log(` Release created: ${cyan(releaseResult.url)}`);
|
|
1215
1312
|
} else if (!releaseResult.success) {
|
|
@@ -1229,10 +1326,10 @@ async function main() {
|
|
|
1229
1326
|
const shouldPush = skipConfirms || await confirm("Push tag to origin?");
|
|
1230
1327
|
if (shouldPush) {
|
|
1231
1328
|
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1232
|
-
if (
|
|
1329
|
+
if (releaseNotes) {
|
|
1233
1330
|
const shouldRelease = skipConfirms || await confirm("Create a GitHub release?");
|
|
1234
1331
|
if (shouldRelease) {
|
|
1235
|
-
const releaseResult = await createGitHubRelease(newVersion,
|
|
1332
|
+
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1236
1333
|
if (releaseResult.success && releaseResult.url) {
|
|
1237
1334
|
console.log(` Release created: ${cyan(releaseResult.url)}`);
|
|
1238
1335
|
} else if (!releaseResult.success) {
|