diff --git a/scripts/release.ts b/scripts/release.ts index 4884e31..8969389 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -97,12 +97,98 @@ async function runTests(): Promise { } } +async function stepGitCommitTag(version: string): Promise { + // 检查工作区状态 + const statusProc = Bun.spawn(["git", "status", "--porcelain"], { + stdio: ["inherit", "pipe", "inherit"], + }); + const statusOutput = await new Response(statusProc.stdout).text(); + const statusLines = statusOutput.trim().split("\n").filter(Boolean); + const nonPkgChanges = statusLines.filter((line) => !line.includes("package.json")); + if (nonPkgChanges.length > 0) { + throw new Error("工作区有其他未提交变更,请先清理后再运行 release"); + } + + console.log("\n准备提交:"); + console.log(` git add package.json`); + console.log(` git commit -m "chore: release v${version}"`); + console.log(` git tag v${version}`); + + const answer = await ask("确认执行以上 git 操作? [y/N]: "); + if (answer.toLowerCase() !== "y") { + console.log("已取消 git 操作"); + process.exit(0); + } + + // git add package.json + const addProc = Bun.spawn(["git", "add", "package.json"], { + stdio: ["inherit", "inherit", "inherit"], + }); + const addExit = await addProc.exited; + if (addExit !== 0) { + throw new Error("git add 失败"); + } + + // git commit + const commitProc = Bun.spawn(["git", "commit", "-m", `chore: release v${version}`], { + stdio: ["inherit", "inherit", "inherit"], + }); + const commitExit = await commitProc.exited; + if (commitExit !== 0) { + throw new Error("git commit 失败"); + } + + // git tag + const tagProc = Bun.spawn(["git", "tag", `v${version}`], { + stdio: ["inherit", "inherit", "inherit"], + }); + const tagExit = await tagProc.exited; + if (tagExit !== 0) { + throw new Error("git tag 失败"); + } + + console.log(`git commit 和 tag v${version} 已完成`); +} + +async function stepNpmPublish(): Promise { + console.log("\nnpm 发布预览:"); + const dryRunProc = Bun.spawn(["bun", "publish", "--dry-run"], { + stdio: ["inherit", "inherit", "inherit"], + }); + const dryRunExit = await dryRunProc.exited; + if (dryRunExit !== 0) { + throw new Error("npm publish --dry-run 失败"); + } + + const answer = await ask("确认发布到 npm? [y/N]: "); + if (answer.toLowerCase() !== "y") { + console.log("已取消发布"); + process.exit(0); + } + + const proc = Bun.spawn(["bun", "publish", "--access", "public"], { + stdio: ["inherit", "inherit", "inherit"], + }); + const exitCode = await proc.exited; + if (exitCode !== 0) { + throw new Error(`npm publish 失败 (exit code: ${exitCode}),请检查 npm 登录状态 (npm whoami)`); + } + + console.log("npm 发布成功"); +} + async function main(): Promise { const newVersion = await stepBumpVersion(); console.log(`[1/4] 版本号递增完成: ${newVersion}`); await runTests(); console.log("[2/4] 测试通过"); + + await stepGitCommitTag(newVersion); + console.log(`[3/4] git commit 和 tag v${newVersion} 完成`); + + await stepNpmPublish(); + console.log("[4/4] npm 发布完成"); } main().catch((err: unknown) => {