release.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* eslint-disable @typescript-eslint/ban-ts-comment */
  2. // @ts-check
  3. import fs from 'node:fs'
  4. import path from 'node:path'
  5. import { fileURLToPath } from 'node:url'
  6. import { createRequire } from 'node:module'
  7. import { execSync } from 'node:child_process'
  8. import enquirer from 'enquirer'
  9. import semver from 'semver'
  10. import minimist from 'minimist'
  11. import chalk from 'chalk'
  12. const step = msg => console.log(chalk.cyan(msg))
  13. // 获取当前目录
  14. const __dirname = path.dirname(fileURLToPath(import.meta.url))
  15. const { prompt } = enquirer
  16. const require = createRequire(import.meta.url)
  17. // 获取当前版本
  18. const currentVersion = require('../package.json').version
  19. const args = minimist(process.argv.slice(2))
  20. const preId = args.preid || semver.prerelease(currentVersion)?.[0]
  21. // 如果已经定义的版本号直接跳过
  22. let targetVersion = args._[0]
  23. // 如果未定义版本号,则生成推测版本号选项
  24. if (!targetVersion) {
  25. const versionIncrements = [
  26. 'patch',
  27. 'minor',
  28. 'major',
  29. ...(preId ? ['prepatch', 'preminor', 'premajor', 'prerelease'] : [])
  30. ]
  31. const inc = i => semver.inc(currentVersion, i, preId)
  32. // @ts-ignore
  33. const { release } = await prompt({
  34. type: 'select',
  35. name: 'release',
  36. message: '请选择 release type',
  37. choices: versionIncrements.map(i => `${i} (${inc(i)})`).concat(['custom'])
  38. })
  39. // 目标版本号
  40. if (release === 'custom') {
  41. const result = await prompt({
  42. type: 'input',
  43. name: 'version',
  44. message: '请自定义你的想要 release 的版本号',
  45. initial: currentVersion
  46. })
  47. // @ts-ignore
  48. targetVersion = result.version
  49. } else {
  50. targetVersion = release.match(/\((.*)\)/)[1]
  51. }
  52. }
  53. // 再次确认版本号是否正确
  54. // @ts-ignore
  55. const { yes: confirmRelease } = await prompt({
  56. type: 'confirm',
  57. name: 'yes',
  58. message: `你确认 release 版本号 v${targetVersion} 吗?`
  59. })
  60. if (confirmRelease) {
  61. await updateVersions(targetVersion)
  62. // 仅正式版本号生成 changelog
  63. if (/^\d+(\.\d+)*$/.test(targetVersion)) {
  64. await generateChangelog()
  65. } else {
  66. await pushCommit()
  67. }
  68. } else {
  69. console.warn(
  70. `${chalk.bgYellow.white(' WARN ')} ${chalk.yellow(
  71. `你已经取消了 v${targetVersion} 版本的 release`
  72. )}`
  73. )
  74. }
  75. function updateVersions(version) {
  76. step('\nUpdate Versions...')
  77. // 更新根目录
  78. updatePackage(path.resolve(__dirname, '..'), version)
  79. }
  80. // 更新 package.json 的 version 字段
  81. function updatePackage(pkgRoot, version) {
  82. const pkgPath = path.resolve(pkgRoot, 'package.json')
  83. const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
  84. pkg.version = version
  85. fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
  86. step(`\nUpdate Versions Success ${pkg.name} ${version}`)
  87. }
  88. // 生成更新日志
  89. async function generateChangelog() {
  90. step('\nGenerating Changelog...')
  91. await execSync('yarn changelog')
  92. // @ts-ignore
  93. const { yes: changelogOk } = await prompt({
  94. type: 'confirm',
  95. name: 'yes',
  96. message: `Changelog 已经生成完毕,请你检查是否 OK?`
  97. })
  98. if (changelogOk) {
  99. step('\nGenerating Changelog Success')
  100. await pushCommit()
  101. } else {
  102. console.warn(
  103. `${chalk.bgYellow.white(' WARN ')} ${chalk.yellow(
  104. `你已经取消了 v${targetVersion} 版本的代码推送`
  105. )}`
  106. )
  107. }
  108. }
  109. // 推送 release 的版本号
  110. function pushCommit() {
  111. step('\nPush Commit...')
  112. const releaseMsg = `release(version): v${targetVersion}`
  113. try {
  114. execSync('git add .')
  115. execSync(`git commit -m '${releaseMsg}'`)
  116. execSync('git push')
  117. console.log(
  118. `${chalk.bgGreen.white(' SUCCESS ')} ${chalk.green(
  119. `你成功推送了 v${targetVersion} 版本的 release 到远程仓库`
  120. )}`
  121. )
  122. } catch (error) {
  123. if (String(error).includes('No staged files found')) {
  124. console.error(
  125. `${chalk.bgRed.white(' ERROR ')} ${chalk.red(
  126. `版本号重复且 SDK 内容没有变更!`
  127. )}`
  128. )
  129. } else {
  130. console.error(
  131. `${chalk.bgRed.white(' ERROR ')} ${chalk.red(
  132. `推送 release 的版本号时发生错误: ${error.message}`
  133. )}`
  134. )
  135. }
  136. }
  137. }