|
1 | | -import type { ParsedCommit } from '../git-utils/tags' |
| 1 | +import type { ParsedCommit, Tag } from '../git-utils/tags' |
| 2 | +import path from 'node:path' |
| 3 | +import process from 'node:process' |
| 4 | +import chalk from 'chalk' |
| 5 | +import { x } from 'tinyexec' |
| 6 | +import { gitCommit } from '../git-utils/commit' |
| 7 | +import { GitTagParser } from '../git-utils/tags' |
| 8 | +import { detectMonorepo } from '../monorepo/detect' |
| 9 | +import { findPackages } from '../monorepo/packages' |
| 10 | +import { createFile } from '../utils/file' |
2 | 11 |
|
3 | 12 | /* eslint-disable unused-imports/no-unused-vars */ |
4 | 13 | const commitTypes = [ |
@@ -46,3 +55,52 @@ export function generateChangelog(commits: ParsedCommit[], title = 'Changelog'): |
46 | 55 |
|
47 | 56 | return changelog.join('\n') |
48 | 57 | } |
| 58 | + |
| 59 | +function getAllTags(tag: Tag): Tag[] { |
| 60 | + const tags: Tag[] = [tag] // 初始化一个包含当前标签的数组 |
| 61 | + // 如果有 `pre` 标签,递归调用 |
| 62 | + if (tag.pre) { |
| 63 | + tags.push(...getAllTags(tag.pre)) // 合并结果 |
| 64 | + } |
| 65 | + return tags |
| 66 | +} |
| 67 | + |
| 68 | +/** |
| 69 | + * 重建整个项目的 changelog |
| 70 | + */ |
| 71 | +export async function resetChangelog() { |
| 72 | + const parser = new GitTagParser() |
| 73 | + await parser.fetchTags() |
| 74 | + |
| 75 | + console.log(chalk.blue('Checking monorepo structure...')) |
| 76 | + const monorepo = await detectMonorepo() |
| 77 | + if (!monorepo) { |
| 78 | + console.log(chalk.red('Not a pnpm monorepo project')) |
| 79 | + return process.exit(1) |
| 80 | + } |
| 81 | + |
| 82 | + const allPackages = await findPackages(monorepo) |
| 83 | + const publishable = allPackages.filter(p => !p.private) |
| 84 | + |
| 85 | + for (const pkg of publishable) { |
| 86 | + const currTag = `${pkg.name}@${pkg.version}` |
| 87 | + const prevTag = await parser.getPreviousTag(currTag, true, true) |
| 88 | + if (prevTag) { |
| 89 | + const tagsInfo = getAllTags(prevTag).reverse() |
| 90 | + const tags = [...tagsInfo.map(item => item.tag), currTag] |
| 91 | + |
| 92 | + const changelogs: string[] = [] |
| 93 | + for (let index = 0; index < tags.length; index++) { |
| 94 | + const currentTag = tags[index]! |
| 95 | + const prevTag = tags[index - 1] |
| 96 | + const commits = await parser.getCommitsBetweenTags(currentTag, prevTag, true) |
| 97 | + changelogs.push(generateChangelog(commits, currentTag)) |
| 98 | + } |
| 99 | + // TODO: 可以选择拆分更新日志至细分文件 |
| 100 | + const changelogPath = createFile(path.join(pkg.path, 'changelog.md'), changelogs.reverse().join('\n'), true) |
| 101 | + await x('npx', ['eslint', '--fix', changelogPath]) |
| 102 | + const commitMsg = `chore(changelog): ${pkg.name}@{${parser.extractScopeProjectVersion(tagsInfo[0]!.tag).version}..${pkg.version}}` |
| 103 | + await gitCommit([changelogPath], commitMsg) |
| 104 | + } |
| 105 | + } |
| 106 | +} |
0 commit comments