|
@@ -3,18 +3,29 @@ import { execSync } from 'child_process'
|
|
import inquirer from 'inquirer'
|
|
import inquirer from 'inquirer'
|
|
import fs from 'fs'
|
|
import fs from 'fs'
|
|
|
|
|
|
-function run(cmd) {
|
|
|
|
- execSync(cmd, { stdio: 'inherit' })
|
|
|
|
|
|
+function run(cmd, opts = {}) {
|
|
|
|
+ execSync(cmd, { stdio: 'inherit', ...opts })
|
|
|
|
+}
|
|
|
|
+function runOut(cmd) {
|
|
|
|
+ return execSync(cmd, { encoding: 'utf8' }).trim()
|
|
}
|
|
}
|
|
-
|
|
|
|
function getVersion() {
|
|
function getVersion() {
|
|
return JSON.parse(fs.readFileSync('package.json', 'utf8')).version
|
|
return JSON.parse(fs.readFileSync('package.json', 'utf8')).version
|
|
}
|
|
}
|
|
|
|
+function isGitClean() {
|
|
|
|
+ return runOut('git status --porcelain') === ''
|
|
|
|
+}
|
|
|
|
|
|
async function main() {
|
|
async function main() {
|
|
console.log('🚀 开始发布流程...')
|
|
console.log('🚀 开始发布流程...')
|
|
|
|
|
|
- // 1. 选择版本类型(默认 patch)
|
|
|
|
|
|
+ // 0. 保护:工作区必须干净(否则 npm version 会报错)
|
|
|
|
+ if (!isGitClean()) {
|
|
|
|
+ console.error('❌ Git 工作区有未提交的改动,请先提交/暂存后再发版!')
|
|
|
|
+ process.exit(1)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 1) 选择版本类型(默认 patch)
|
|
const { versionType } = await inquirer.prompt([
|
|
const { versionType } = await inquirer.prompt([
|
|
{
|
|
{
|
|
type: 'list',
|
|
type: 'list',
|
|
@@ -29,7 +40,7 @@ async function main() {
|
|
},
|
|
},
|
|
])
|
|
])
|
|
|
|
|
|
- // 2. 选择日志生成模式(默认 incremental)
|
|
|
|
|
|
+ // 2) 选择日志生成模式(默认增量)
|
|
const { changelogMode } = await inquirer.prompt([
|
|
const { changelogMode } = await inquirer.prompt([
|
|
{
|
|
{
|
|
type: 'list',
|
|
type: 'list',
|
|
@@ -37,32 +48,37 @@ async function main() {
|
|
message: '请选择 changelog 生成模式:',
|
|
message: '请选择 changelog 生成模式:',
|
|
default: 'incremental',
|
|
default: 'incremental',
|
|
choices: [
|
|
choices: [
|
|
- { name: '全量生成(会覆盖整个文件)', value: 'full' },
|
|
|
|
{ name: '增量生成(只追加本次更新的内容)', value: 'incremental' },
|
|
{ name: '增量生成(只追加本次更新的内容)', value: 'incremental' },
|
|
|
|
+ { name: '全量生成(会覆盖整个文件)', value: 'full' },
|
|
],
|
|
],
|
|
},
|
|
},
|
|
])
|
|
])
|
|
|
|
|
|
- // 3. 先生成 changelog
|
|
|
|
|
|
+ // 3) 先只更新 package.json 版本,不提交、不打 tag(确保 changelog 标题用到新版本)
|
|
|
|
+ run(`npm version ${versionType} --no-git-tag-version`)
|
|
|
|
+ const version = getVersion()
|
|
|
|
+
|
|
|
|
+ // 4) 生成 changelog(增量/全量)
|
|
console.log('📝 正在生成 changelog...')
|
|
console.log('📝 正在生成 changelog...')
|
|
|
|
+ // 确保文件存在,避免第一次运行时 in-place 报错
|
|
|
|
+ if (!fs.existsSync('CHANGELOG.md')) fs.writeFileSync('CHANGELOG.md', '')
|
|
if (changelogMode === 'full') {
|
|
if (changelogMode === 'full') {
|
|
run('npx conventional-changelog -p angular -i CHANGELOG.md -s -r 0')
|
|
run('npx conventional-changelog -p angular -i CHANGELOG.md -s -r 0')
|
|
} else {
|
|
} else {
|
|
run('npx conventional-changelog -p angular -i CHANGELOG.md -s')
|
|
run('npx conventional-changelog -p angular -i CHANGELOG.md -s')
|
|
}
|
|
}
|
|
|
|
|
|
- // 4. 提交 changelog
|
|
|
|
|
|
+ // 5) 一次性提交:把 package.json + CHANGELOG.md 一起提交,并打 tag(保证日志与版本同步)
|
|
|
|
+ run('git add package.json package-lock.json 2> NUL || :')
|
|
run('git add CHANGELOG.md')
|
|
run('git add CHANGELOG.md')
|
|
- run('git commit -m "chore: update changelog"')
|
|
|
|
-
|
|
|
|
- // 5. 更新版本号并生成 tag
|
|
|
|
- run(`npm version ${versionType} -m "new version published: v%s"`)
|
|
|
|
- const version = getVersion()
|
|
|
|
|
|
+ run(`git commit -m "chore(release): v${version}"`)
|
|
|
|
+ run(`git tag v${version}`)
|
|
|
|
|
|
- // 6. 推送代码 & tag
|
|
|
|
- run('git push --follow-tags')
|
|
|
|
|
|
+ // 6) 推送代码 & tag
|
|
|
|
+ run('git push')
|
|
|
|
+ run('git push --tags')
|
|
|
|
|
|
- // 7. 提示
|
|
|
|
|
|
+ // 7) 提示
|
|
console.log('\x1b[36m=========================\x1b[0m')
|
|
console.log('\x1b[36m=========================\x1b[0m')
|
|
console.log('\x1b[32m🎉 发布成功!\x1b[0m')
|
|
console.log('\x1b[32m🎉 发布成功!\x1b[0m')
|
|
console.log(`\x1b[33m📦 版本号:v${version}\x1b[0m`)
|
|
console.log(`\x1b[33m📦 版本号:v${version}\x1b[0m`)
|