前言
上一篇对Git提交进行了规范化,本篇实现自动生成CHANGELOG。
11、自动生成CHANGELOG
安装 conventional-changelog-cli 插件
// package.json
"conventional-changelog-cli": "^3.0.0",
在 package.json 文件添加脚本
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 -n ./changelog-option.cjs"
-p angular,表示changelog标准为angular,现在有angular, atom, codemirror, ember, eslint, express, jquery 等项目的标准可供选择
-i CHANGELOG.md,表示指定输出的文件名称
-s 输出到infile,这样就不需要指定与outfile相同的文件
-r 从最新的版本的生成,默认值为1。如果为0,则将重新生成整个更新日志并覆盖输出文件
-n ./changelog-option.js 表示指定自定义配置文件
在根目录新建 changelog-option.cjs文件 和 templates/commit.hbs 文件
// changelog-option.cjs
const readFileSync = require('fs').readFileSync
const join = require('path').join
module.exports = {
gitRawCommitsOpts: {
format: '%B%n-hash-%n%H%n-gitTags-%n%d%n-committerDate-%n%ci%n-authorName-%n%an%n-authorEmail-%n%ae',
},
writerOpts: {
commitPartial: readFileSync(
join(__dirname, 'templates/commit.hbs'),
'utf-8'
),
// mainTemplate: readFileSync(join(__dirname, 'templates/template.hbs'),'utf-8'),
// headerPartial: readFileSync(join(__dirname, 'templates/header.hbs'),'utf-8'),
// footerPartial: readFileSync(join(__dirname, 'templates/footer.hbs'),'utf-8'),
...getWriterOpts(),
},
}
function getWriterOpts() {
return {
transform: (commit, context) => {
let discard = true
const issues = []
commit.notes.forEach((note) => {
note.title = 'BREAKING CHANGES'
discard = false
})
if (commit.type === 'feat') {
commit.type = '✨ Features | 新功能'
} else if (commit.type === 'fix') {
commit.type = '🐛 Bug Fixes | Bug 修复'
} else if (commit.type === 'perf') {
commit.type = '⚡ Performance Improvements | 性能优化'
} else if (commit.type === 'revert' || commit.revert) {
commit.type = '⏪ Reverts | 回退'
} else if (commit.type === 'improvement') {
commit.type = '💩 Improvement | 优化改进'
} else if (commit.type === 'style') {
commit.type = '💄 Styles | 风格'
} else if (discard) {
return
} else if (commit.type === 'docs') {
commit.type = '📝 Documentation | 文档'
} else if (commit.type === 'refactor') {
commit.type = '♻ Code Refactoring | 代码重构'
} else if (commit.type === 'test') {
commit.type = '✅ Tests | 测试'
} else if (commit.type === 'build') {
commit.type = '👷 Build System | 构建'
} else if (commit.type === 'ci') {
commit.type = '🔧 Continuous Integration | CI 配置'
} else if (commit.type === 'chore') {
commit.type = '🎫 Chores | 其他更新'
}
if (commit.scope === '*') {
commit.scope = ''
}
if (typeof commit.hash === 'string') {
commit.hash = commit.hash.substring(0, 7)
}
if (typeof commit.subject === 'string') {
let url = context.repository
? `${context.host}/${context.owner}/${context.repository}`
: context.repoUrl
if (url) {
url = `${url}/issues/`
// Issue URLs.
commit.subject = commit.subject.replace(
/#([0-9]+)/g,
(_, issue) => {
issues.push(issue)
return `[#${issue}](${url}${issue})`
}
)
}
if (context.host) {
// User URLs.
commit.subject = commit.subject.replace(
/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g,
(_, username) => {
if (username.includes('/')) {
return `@${username}`
}
return `[@${username}](${context.host}/${username})`
}
)
}
}
// remove references that already appear in the subject
commit.references = commit.references.filter((reference) => {
if (issues.indexOf(reference.issue) === -1) {
return true
}
return false
})
return commit
},
groupBy: 'type',
commitGroupsSort: 'title',
commitsSort: ['scope', 'subject'],
noteGroupsSort: 'title',
}
}
// templates/commit.hbs
- {{header}}
{{~!-- commit link --}} {{#if @root.linkReferences~}}
([#{{hash}}](
{{~#if @root.repository}}
{{~#if @root.host}}
{{~@root.host}}/
{{~/if}}
{{~#if @root.owner}}
{{~@root.owner}}/
{{~/if}}
{{~@root.repository}}
{{~else}}
{{~@root.repoUrl}}
{{~/if}}/
{{~@root.commit}}/{{hash}}) by @{{authorName}})
{{~else}}
{{~hash}}
{{~/if}}
{{~!-- commit references --}}
{{~#if references~}}
, closes
{{~#each references}} {{#if @root.linkReferences~}}
[
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}#{{this.issue}}](
{{~#if @root.repository}}
{{~#if @root.host}}
{{~@root.host}}/
{{~/if}}
{{~#if this.repository}}
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}
{{~else}}
{{~#if @root.owner}}
{{~@root.owner}}/
{{~/if}}
{{~@root.repository}}
{{~/if}}
{{~else}}
{{~@root.repoUrl}}
{{~/if}}/
{{~@root.issue}}/{{this.issue}})
{{~else}}
{{~#if this.owner}}
{{~this.owner}}/
{{~/if}}
{{~this.repository}}#{{this.issue}}
{{~/if}}{{/each}}
{{~/if}}
生成效果。
配置环境变量
顺便把环境变量加一下,删除原有的env.d.ts文件,新建.env,.env.development,.env.production三个文件。
// .env
# 端口号
VITE_PORT = 8080
# 标题
VITE_GLOB_APP_TITLE = Common Template
# 简称
VITE_GLOB_APP_SHORT_NAME = common_template
内容暂时都使用这一份即可。
结语
自动生成CHANGELOG就结束了,后面考虑要不要加release-it。未完待续…