123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- #!/usr/bin/env node
- import { execSync } from 'child_process'
- import inquirer from 'inquirer'
- import fs from 'fs'
- function run(cmd, options = {}) {
- execSync(cmd, { stdio: 'inherit', ...options })
- }
- function runSilent(cmd) {
- return execSync(cmd, { encoding: 'utf-8' }).trim()
- }
- function getVersion() {
- return JSON.parse(fs.readFileSync('package.json', 'utf8')).version
- }
- function getLastTag() {
- try {
- return runSilent('git describe --tags --abbrev=0')
- } catch {
- return null // 没有 tag
- }
- }
- function getCommitsSince(tag) {
- const range = tag ? `${tag}..HEAD` : ''
- try {
- return runSilent(`git log ${range} --pretty=format:"- %s (%h)"`)
- } catch {
- return ''
- }
- }
- function updateChangelog(version, mode = 'incremental') {
- const lastTag = getLastTag()
- const commits = getCommitsSince(lastTag)
- if (!commits) {
- console.log('⚠️ 没有新提交,但依旧会记录版本变化。')
- }
- const date = new Date().toISOString().slice(0, 10)
- const newEntry = `\n## ${version} (${date})\n${commits || '- No changes'}\n`
- let changelog = ''
- if (fs.existsSync('CHANGELOG.md')) {
- changelog = fs.readFileSync('CHANGELOG.md', 'utf-8')
- }
- if (mode === 'full') {
- fs.writeFileSync('CHANGELOG.md', newEntry, 'utf-8')
- } else {
- fs.writeFileSync('CHANGELOG.md', newEntry + changelog, 'utf-8')
- }
- console.log(`✅ changelog 已更新到版本 ${version}`)
- }
- async function main() {
- console.log('🚀 开始发布流程...')
- // 选择版本类型
- const { versionType } = await inquirer.prompt([
- {
- type: 'list',
- name: 'versionType',
- message: '请选择版本类型:',
- default: 'patch',
- choices: [
- { name: '补丁版本 (patch)', value: 'patch' },
- { name: '小版本 (minor)', value: 'minor' },
- { name: '大版本 (major)', value: 'major' },
- ],
- },
- ])
- // 更新版本号(不自动打 tag)
- run(`npm version ${versionType} --no-git-tag-version`)
- const version = getVersion()
- // 同步远程 tag,防止增量 changelog 范围不准
- console.log('🔄 正在同步远程标签...')
- run('git fetch --tags')
- console.log('✅ 远程标签已同步')
- // 选择 changelog 生成模式
- const { changelogMode } = await inquirer.prompt([
- {
- type: 'list',
- name: 'changelogMode',
- message: '请选择 changelog 生成模式:',
- default: 'incremental',
- choices: [
- // { name: '全量生成(会覆盖整个文件)', value: 'full' },
- { name: '增量生成(只追加本次更新的内容)', value: 'incremental' },
- ],
- },
- ])
- // 生成 changelog
- updateChangelog(`v${version}`, changelogMode)
- // 提交变更
- if (fs.existsSync('package-lock.json')) {
- run('git add package.json package-lock.json')
- } else {
- run('git add package.json')
- }
- run('git add CHANGELOG.md')
- try {
- run(`git diff --cached --quiet || git commit -m "chore: release v${version}"`)
- } catch {
- console.log('⚠️ 没有需要提交的文件,跳过 commit')
- }
- // 打 tag & 推送
- run(`git tag v${version}`)
- run('git push && git push --tags')
- console.log('\x1b[36m=========================\x1b[0m')
- console.log('\x1b[32m🎉 发布成功!\x1b[0m')
- console.log(`\x1b[33m📦 版本号:v${version}\x1b[0m`)
- console.log('\x1b[35m⚙️ 同步代码:\x1b[0m')
- console.log('\x1b[34m * 同步dev分支代码到prod分支:bash scripts/merge_dev_to_pro.sh\x1b[0m')
- console.log('\x1b[36m=========================\x1b[0m')
- }
- main()
|