choose-semverness.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /* eslint-disable no-continue */
  2. import { createWriteStream, mkdirSync, readFileSync } from 'node:fs'
  3. import { spawnSync } from 'node:child_process'
  4. import prompts from 'prompts'
  5. import { TARGET_BRANCH } from './config.js'
  6. const ROOT = new URL('../../', import.meta.url)
  7. const PACKAGES_FOLDER = new URL('./packages/', ROOT)
  8. function getRobodogDependencies () {
  9. const { dependencies } = JSON.parse(readFileSync(new URL('./@uppy/robodog/package.json', PACKAGES_FOLDER)))
  10. return Object.keys(dependencies)
  11. }
  12. function maxSemverness (a, b) {
  13. if (a === 'major' || b === 'major') return 'major'
  14. if (a === 'premajor' || b === 'premajor') return 'premajor'
  15. if (a === 'minor' || b === 'minor') return 'minor'
  16. if (a === 'preminor' || b === 'preminor') return 'preminor'
  17. if (a === 'prepatch' || b === 'prepatch') return 'prepatch'
  18. if (a === 'prepatch' || b === 'prerelease') return 'prerelease'
  19. return 'patch'
  20. }
  21. export default async function pickSemverness (
  22. spawnOptions,
  23. LAST_RELEASE_COMMIT,
  24. STABLE_BRANCH_MERGE_BASE_RANGE,
  25. releaseFileUrl,
  26. packagesList,
  27. ) {
  28. mkdirSync(new URL('.', releaseFileUrl), { recursive: true })
  29. const releaseFile = createWriteStream(releaseFileUrl)
  30. releaseFile.write('releases:\n')
  31. let uppySemverness
  32. let robodogSemverness
  33. const robodogDeps = getRobodogDependencies()
  34. for await (const workspaceInfo of packagesList) {
  35. const { location, name } = JSON.parse(workspaceInfo)
  36. if (!name.startsWith('@uppy/')) continue
  37. if (name === '@uppy/robodog') continue
  38. const { stdout } = spawnSync(
  39. 'git',
  40. [
  41. '--no-pager',
  42. 'log',
  43. '--format=- %s',
  44. `${LAST_RELEASE_COMMIT}..`,
  45. '--',
  46. location,
  47. ],
  48. spawnOptions,
  49. )
  50. if (stdout.length === 0) {
  51. const { stdout } = spawnSync(
  52. 'git',
  53. [
  54. '--no-pager',
  55. 'log',
  56. '--format=- %s',
  57. STABLE_BRANCH_MERGE_BASE_RANGE,
  58. '--',
  59. location,
  60. ],
  61. spawnOptions,
  62. )
  63. if (stdout.length === 0) {
  64. console.log(`No commits since last release for ${name}, skipping.`)
  65. } else {
  66. console.log(`Some commits have landed on the stable branch since last release for ${name}.`)
  67. releaseFile.write(` ${JSON.stringify(name)}: prerelease\n`)
  68. uppySemverness = maxSemverness(uppySemverness, 'prerelease')
  69. if (robodogDeps.includes(name)) {
  70. robodogSemverness = maxSemverness(robodogSemverness, 'prerelease')
  71. }
  72. }
  73. continue
  74. }
  75. console.log('\n')
  76. console.log('-'.repeat(20))
  77. console.log(name)
  78. console.log(
  79. `\nHere are the commits that landed on ${name} since previous release:\n${stdout}\n`,
  80. )
  81. console.log(
  82. `Check the web UI at https://github.com/transloadit/uppy/tree/${TARGET_BRANCH}/${encodeURI(
  83. location,
  84. )}.`,
  85. )
  86. const response = await prompts({
  87. type: 'select',
  88. name: 'value',
  89. message: `What should be the semverness of next ${name} release?`,
  90. choices: [
  91. { title: 'Pre-release', value: 'prerelease' },
  92. { title: 'Skip this package', value: '' },
  93. { title: 'Patch', value: 'patch' },
  94. { title: 'Minor', value: 'minor' },
  95. { title: 'Major', value: 'major' },
  96. ],
  97. initial: 0,
  98. })
  99. if (!response.value) {
  100. console.log('Skipping.')
  101. continue
  102. }
  103. releaseFile.write(` ${JSON.stringify(name)}: ${response.value}\n`)
  104. uppySemverness = maxSemverness(uppySemverness, response.value)
  105. if (robodogDeps.includes(name)) {
  106. robodogSemverness = maxSemverness(robodogSemverness, response.value)
  107. }
  108. }
  109. if (uppySemverness == null) throw new Error('No package to release, aborting.')
  110. {
  111. // Robodog
  112. const location = 'packages/@uppy/robodog'
  113. const { stdout } = spawnSync(
  114. 'git',
  115. [
  116. '--no-pager',
  117. 'log',
  118. '--format=- %s',
  119. `${LAST_RELEASE_COMMIT}..`,
  120. '--',
  121. location,
  122. ],
  123. spawnOptions,
  124. )
  125. if (stdout.length === 0) {
  126. if (robodogSemverness == null) {
  127. console.log(`No commits since last release for @uppy/robodog, skipping.`)
  128. } else {
  129. console.log(`No commits since last release for @uppy/robodog, releasing as ${robodogSemverness}.`)
  130. releaseFile.write(` "@uppy/robodog": ${robodogSemverness}\n`)
  131. }
  132. } else {
  133. console.log(
  134. `Here are the commits that landed on @uppy/robodog since previous release:\n\n${stdout}\n`,
  135. )
  136. console.log(
  137. `Check the web UI at https://github.com/transloadit/uppy/tree/${TARGET_BRANCH}/${encodeURI(
  138. location,
  139. )}.`,
  140. )
  141. const response = await prompts({
  142. type: 'select',
  143. name: 'value',
  144. message: `What should be the semverness of next @uppy/robodog release?`,
  145. choices: [
  146. { title: 'Pre-release', value: 'prerelease' },
  147. { title: 'Skip this package', value: '', disabled: robodogSemverness != null },
  148. { title: 'Patch', value: 'patch', disabled: robodogSemverness === 'minor' || robodogSemverness === 'major' },
  149. { title: 'Minor', value: 'minor', disabled: robodogSemverness === 'major' },
  150. { title: 'Major', value: 'major' },
  151. ],
  152. initial: 0,
  153. })
  154. releaseFile.write(` "@uppy/robodog": ${response.value}\n`)
  155. }
  156. }
  157. releaseFile.write(` "uppy": ${uppySemverness}\n`)
  158. releaseFile.close()
  159. }