release.js 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #!/usr/bin/env node
  2. import { execSync } from 'child_process'
  3. import inquirer from 'inquirer'
  4. import fs from 'fs'
  5. function run(cmd, opts = {}) {
  6. execSync(cmd, { stdio: 'inherit', ...opts })
  7. }
  8. function runOut(cmd) {
  9. return execSync(cmd, { encoding: 'utf8' }).trim()
  10. }
  11. function getVersion() {
  12. return JSON.parse(fs.readFileSync('package.json', 'utf8')).version
  13. }
  14. function isGitClean() {
  15. return runOut('git status --porcelain') === ''
  16. }
  17. async function main() {
  18. console.log('🚀 开始发布流程...')
  19. // 0. 保护:工作区必须干净(否则 npm version 会报错)
  20. if (!isGitClean()) {
  21. console.error('❌ Git 工作区有未提交的改动,请先提交/暂存后再发版!')
  22. process.exit(1)
  23. }
  24. // 1) 选择版本类型(默认 patch)
  25. const { versionType } = await inquirer.prompt([
  26. {
  27. type: 'list',
  28. name: 'versionType',
  29. message: '请选择版本类型:',
  30. default: 'patch',
  31. choices: [
  32. { name: '补丁版本 (patch)', value: 'patch' },
  33. { name: '小版本 (minor)', value: 'minor' },
  34. { name: '大版本 (major)', value: 'major' },
  35. ],
  36. },
  37. ])
  38. // 2) 选择日志生成模式(默认增量)
  39. const { changelogMode } = await inquirer.prompt([
  40. {
  41. type: 'list',
  42. name: 'changelogMode',
  43. message: '请选择 changelog 生成模式:',
  44. default: 'incremental',
  45. choices: [
  46. { name: '增量生成(只追加本次更新的内容)', value: 'incremental' },
  47. { name: '全量生成(会覆盖整个文件)', value: 'full' },
  48. ],
  49. },
  50. ])
  51. // 3) 先只更新 package.json 版本,不提交、不打 tag(确保 changelog 标题用到新版本)
  52. run(`npm version ${versionType} --no-git-tag-version`)
  53. const version = getVersion()
  54. // 4) 生成 changelog(增量/全量)
  55. console.log('📝 正在生成 changelog...')
  56. // 确保文件存在,避免第一次运行时 in-place 报错
  57. if (!fs.existsSync('CHANGELOG.md')) fs.writeFileSync('CHANGELOG.md', '')
  58. if (changelogMode === 'full') {
  59. run('npx conventional-changelog -p angular -i CHANGELOG.md -s -r 0')
  60. } else {
  61. run('npx conventional-changelog -p angular -i CHANGELOG.md -s')
  62. }
  63. // 5) 一次性提交:把 package.json + CHANGELOG.md 一起提交,并打 tag(保证日志与版本同步)
  64. run('git add package.json package-lock.json 2> NUL || :')
  65. run('git add CHANGELOG.md')
  66. run(`git commit -m "chore(release): v${version}"`)
  67. run(`git tag v${version}`)
  68. // 6) 推送代码 & tag
  69. run('git push')
  70. run('git push --tags')
  71. // 7) 提示
  72. console.log('\x1b[36m=========================\x1b[0m')
  73. console.log('\x1b[32m🎉 发布成功!\x1b[0m')
  74. console.log(`\x1b[33m📦 版本号:v${version}\x1b[0m`)
  75. console.log('\x1b[35m⚙️ 部署:\x1b[0m')
  76. console.log('\x1b[34m * 测试环境:npm run deploy:test\x1b[0m')
  77. console.log('\x1b[34m * 开发环境:npm run build:dev\x1b[0m')
  78. console.log('\x1b[34m * 生产环境:npm run build\x1b[0m')
  79. console.log('\x1b[36m=========================\x1b[0m')
  80. }
  81. main()