Skip to content

Commit

Permalink
build: Refactor scripts to support multi-module log generation
Browse files Browse the repository at this point in the history
  • Loading branch information
Marinerer committed Sep 30, 2024
1 parent c20fd4c commit 0d23f8c
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 23 deletions.
42 changes: 29 additions & 13 deletions Help.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,37 @@ pnpm test core main
pnpm test -- -p core,main --coverage
```



# Release

## 版本发布

1. `pnpm changeset`
2. `pnpm changeset:version`
- 然后执行 `pnpm changelog` 打印版本日志
3. 更改`change log`后, `git add & commit`
4. `git push` 后触发 github release,自动发布
```bash
# 1. 创建变更集
pnpm changeset


# 2. 更新版本、编辑变更日志、读取和删除变更集的命令
# 注: 该步骤放在本地手动操作
pnpm changeset:version


# 3. 生成日志记录
pnpm changelog core cli
# 查看日志记录
pnpm changelog


# 4. 提交 commit
git add .
git commit -m 'Version Packages'


# 5. 提交远程仓库并发布 (触发 github-action 自动发布)
git push
```

## 语义化版本

严格遵循 [semver](https://semver.org/) 规范。

```
Expand All @@ -31,24 +48,23 @@ pnpm test -- -p core,main --coverage
- `Major` - 主版本号:当你做了不兼容的 API 修改
- `Minor` - 次版本号:当你做了向下兼容的功能性新增
- `Patch` - 修订号:当你做了向下兼容的问题修正
先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。
先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

> **Tag**
>
> - `alpha` - alpha 版本, 内部测试版,一般不向外部发布;
> - `beta` - beta 版本, 测试版,该版本会一直加入新的功能;
> - `rc` - rc 版本 (Release Candidate) 发行候选版本。不再加新功能,着重于除错。
> - `rc` - rc 版本 (Release Candidate) 发行候选版本。不再加新功能,着重于除错。
>
> 优先层级:
> 例如:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0。

## refs
- [pnpm构建monorepo工程](https://github.com/astonishqft/pnpm-monorepo-demo)

- [pnpm 构建 monorepo 工程](https://github.com/astonishqft/pnpm-monorepo-demo)
- [webpack5 的多页脚手架](https://github.com/kailong321200875/webpack-multi-page-cli)
- [pnpm-workspaces-example & changeset](https://github.com/DavidWells/pnpm-workspaces-example/)


# Todo


# Help
28 changes: 25 additions & 3 deletions scripts/changelog.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
const simpleGit = require('simple-git')
const { promisify } = require('util')
const log = require('diy-log')
const minimist = require('minimist')
const { readPackageJson, readPackageFile, writePackageFile, updateChangelog } = require('./utils')

const rawArgs = process.argv.slice(2)
const args = minimist(rawArgs)
const git = simpleGit()

// 获取从特定 commit ID 开始的所有最新记录
Expand Down Expand Up @@ -62,10 +66,20 @@ function formatCommits(commits, filter = (commit) => commit) {
})
}

// 生成日志记录
async function generateLogs(name, logs) {
const pkg = await readPackageJson(name)
const content = await readPackageFile(name)
const result = updateChangelog(content, pkg.version, logs[name])
await writePackageFile(name, result)

return result
}

;(async () => {
const moduleRegex = /^[a-z]{1,10}\(\w+\).*/i
try {
// const commits = await getCommitsSince('4ac1e7a')
// const commits = await getCommitsSince('d9acb96')
const commits = await getCommitsSinceLatestTag()
const formattedCommits = formatCommits(commits, (commit) => {
return moduleRegex.test(commit.message)
Expand All @@ -81,14 +95,22 @@ function formatCommits(commits, filter = (commit) => commit) {
)
return acc
}, {})

console.log(
'Commit messages:',
formatCommits(commits).map((commit) => commit.message)
)

Object.entries(formattedCommits).forEach(([key, value]) => {
log.tag.warn('\n' + value.join('\n'), key)
})
} catch (error) {
console.error('error:', error.message)

if (args._.length) {
for (const name of args._) {
await generateLogs(name, formattedCommits)
}
}
} catch (err) {
console.error('error:', err.message)
}
})()
37 changes: 37 additions & 0 deletions scripts/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* 模块及对应路径
*/
const packagesMap = {
core: 'packages/core',
cli: 'packages/cli',
main: 'packages/main',
utils: 'packages/utils',
renew: 'plugins/renew',
}

/**
* 版本 emoji 标识
*/
const semverSymbol = {
Major: '🎉',
Minor: '🚀',
Patch: '🌟',
}

/**
* 显示的日志类型
* // (revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip)
*/
const messagesType = ['feat', 'fix', 'perf', 'refactor', 'docs']

/**
* changeset 默认变更日志 (待替换)
*/
const defaultChangeLog = `- update.`

module.exports = {
packagesMap,
semverSymbol,
messagesType,
defaultChangeLog,
}
8 changes: 1 addition & 7 deletions scripts/test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
const minimist = require('minimist')
const rawArgs = process.argv.slice(2)
const args = minimist(rawArgs)
const packagesMap = {
core: 'packages/core',
cli: 'packages/cli',
main: 'packages/main',
utils: 'packages/utils',
renew: 'plugins/renew',
}
const { packagesMap } = require('./config')

let regex
if (args.p) {
Expand Down
105 changes: 105 additions & 0 deletions scripts/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const fs = require('fs')
const path = require('path')
const { packagesMap, semverSymbol, messagesType, defaultChangeLog } = require('./config')

/**
* 读取模块文件内容
*
* @param {string} name 模块名
* @param {string} filename 文件名
* @returns {Promise}
*/
function readPackageFile(name, filename) {
return new Promise((resolve, reject) => {
const filePath = path.resolve(__dirname, '../', packagesMap[name], filename || 'CHANGELOG.md')
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
reject(err)
}
resolve(data)
})
})
}

/**
* 写入模块文件内容
*
* @param {string} name 模块名
* @param {string} filename 文件名
* @returns {Promise}
*/
function writePackageFile(name, data, filename) {
return new Promise((resolve, reject) => {
fs.writeFile(
path.resolve(__dirname, '../', packagesMap[name], filename || 'CHANGELOG.md'),
data,
(err) => {
if (err) {
reject(err)
}
resolve()
}
)
})
}

/**
* 日志排序
*
* @param {Array.<string>} logs 日志列表
* @returns {Array.<string>}
*/
function sortLogsByType(logs) {
const msgRegex = new RegExp(`- (${messagesType.join('|')}):[\\s\\S]+`)
return logs
.reduce((acc, cur) => {
const type = cur.match(msgRegex)?.[1]
const index = messagesType.indexOf(type)
if (index > -1) {
acc[index].push(cur)
}
return acc
}, messagesType.map(() => []).concat([[]]))
.reduce((acc, cur) => acc.concat(cur), [])
}

/**
* 更新日志内容
*
* @param {string} content 日志内容
* @param {string} version 版本号
* @param {Array.<string>} logs 日志列表
* @returns {Promise}
*/
function updateChangelog(content, version, logs) {
const [v1, v2, v3] = version.split('.')
const regex = new RegExp(`## ${v1}\\.${v2}\\.${v3}[\\s]*### (Patch|Minor|Major) Changes\\n`)
logStr = sortLogsByType(logs).join('\n')

return content
.replace(regex, (match, p1) => {
// console.log('replace : ', match, p1)
return match.replace('Changes', 'Changes ' + semverSymbol[p1])
// return match + ' ' + semverSymbol[p1]
})
.replace(defaultChangeLog, logStr)
}

/**
* 读取JSON文件内容
*
* @param {string} name 模块名
* @param {string} filename 文件名
* @returns {Promise}
*/
function readPackageJson(name, filename) {
return readPackageFile(name, filename || 'package.json').then((data) => JSON.parse(data))
}

module.exports = {
readPackageFile,
writePackageFile,
readPackageJson,
updateChangelog,
sortLogsByType,
}

0 comments on commit 0d23f8c

Please sign in to comment.