Skip to content

Commit 98c11a0

Browse files
committed
feat(scripts): 🚀 新增 resetChangelog 工具函数的实现
实现项目整体 changelog 重建
1 parent a542435 commit 98c11a0

File tree

2 files changed

+65
-7
lines changed

2 files changed

+65
-7
lines changed

scripts/changelog/index.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
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'
211

312
/* eslint-disable unused-imports/no-unused-vars */
413
const commitTypes = [
@@ -46,3 +55,52 @@ export function generateChangelog(commits: ParsedCommit[], title = 'Changelog'):
4655

4756
return changelog.join('\n')
4857
}
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+
}

scripts/git-utils/tags.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { x } from 'tinyexec'
22

33
const execOptions = { throwOnError: true }
44

5-
interface Tag {
5+
export interface Tag {
66
/* 标签 */
77
tag: string
88
/* 提交id */
@@ -199,7 +199,7 @@ export class GitTagParser {
199199
return new Date(result.stdout.trim())
200200
}
201201

202-
async getPreviousTag(tag: string, same = false): Promise<Tag | undefined> {
202+
async getPreviousTag(tag: string, same = false, pre = false): Promise<Tag | undefined> {
203203
const currentTagIndex = this.tags.indexOf(tag)
204204
let prevTag: string | undefined
205205
if (same === true) {
@@ -223,7 +223,7 @@ export class GitTagParser {
223223
}
224224

225225
if (prevTag) {
226-
return this.getTagInfo(prevTag)
226+
return this.getTagInfo(prevTag, pre, same)
227227
}
228228

229229
return undefined
@@ -234,7 +234,7 @@ export class GitTagParser {
234234
* @param tag
235235
* @param pre 默认 false,避免递归
236236
*/
237-
async getTagInfo(tag: string, pre = false): Promise<Tag> {
237+
async getTagInfo(tag: string, pre = false, same = false): Promise<Tag> {
238238
const result = await x('git', ['show', tag, '-q', '--pretty=format:"%id=%H&author=%an&date=%ad&sha=%h%"'], execOptions)
239239
const data = result.stdout.trim()
240240
const temp = data?.slice(data.indexOf('%') + 1, data.lastIndexOf('%')) || ''
@@ -251,7 +251,7 @@ export class GitTagParser {
251251
}
252252

253253
// 获取上一个标签
254-
pre && (tagResult.pre = await this.getPreviousTag(tag))
254+
pre && (tagResult.pre = await this.getPreviousTag(tag, same, pre))
255255

256256
return tagResult
257257
}
@@ -293,7 +293,7 @@ export class GitTagParser {
293293
}
294294

295295
// 提取标签中的 scope、project 和 version
296-
private extractScopeProjectVersion(tag: string): { scope: string, project: string, version: string } {
296+
extractScopeProjectVersion(tag: string): { scope: string, project: string, version: string } {
297297
let scope = ''
298298
let project = ''
299299
let version = ''

0 commit comments

Comments
 (0)