自动生成 changelog.md,做一名有追求的工程师

前面写过四篇文章,各自讲述了Git Hooks 与 Huskycommitlint + Husky 规范 git commit 日志根据 commit message 自动生成 changelog如何自定义 conventional-changelog,这篇文章是将这些知识整合起来,应用到为自动生成 changelog


commitlint + Husky 规范 git commit 日志

规范 commit 日志的好处

  • 团队形成一致的代码提交风格,更好的提高工作效率
  • 规范的 commit message 有助于团队其它人员 review, 还可以有效的输出 CHANGELOG, 对项目十分重要
  • 成为一名有追求的工程师

安装 & 配置 commitlint


安装 commitlint cliconfig-conventional

npm install --save-dev @commitlint/{config-conventional,cli}

# For Windows:

npm install --save-dev @commitlint/config-conventional @commitlint/cli

创建 commitlint.config.js 配置 commitlint

echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js

安装 & 配置 husky

安装 husky

npm install husky --save-dev

启用 Git hooks

npx husky install

添加 commit-msg hook

运行以下命令创建 commit-msg hook

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'


# 有时上面的命令在某些命令解释器中不起作用

# 你可以尝试下面的命令在commit-msg文件中写入 npx --no -- commitlint --edit $1

npx husky add .husky/commit-msg \"npx --no -- commitlint --edit '$1'\"

# or

npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"

提交 commit,发现 commitlint 已经生效,不符合 commitlint 规范的 git commit 的将被停止

Tip

如果你遇到如下报错,删除node_modules并执行 npm install 重新安装即可

.husky/_/husky.sh: No such file or directory

commitlint 规范

提交格式

git commit -m <type>(scope?): <subject>

Examples
git commit -m 'chore: run tests on travis ci'

git commit -m 'fix(server): send cors headers'

git commit -m 'feat(blog): add comment section'

注意,英文冒号 + 空格


常用的 type 类别

type:用于表明我们这次提交的改动类型,是新增了功能?还是修改了测试代码?又或者是更新了文档?总结以下 11 种类型:

  • build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
  • ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
  • docs:文档更新
  • feat:新增功能
  • fix:bug 修复
  • perf:性能优化
  • refactor:重构代码(既没有新增功能,也没有修复 bug)
  • revert:回滚某个更早之前的提交
  • style:不影响程序逻辑的代码修改(修改空白字符,补全缺失的分号等)
  • test:新增测试用例或是更新现有测试
  • chore:不属于以上类型的其他类型(日常事务)

更多的 type 说明 你可以参阅这里 commitlint type-enum

scope:作用域,可选。用于标识此次提交主要涉及到代码中哪些模块。支持多作用域(可使用分隔符:“/”、“” 和 “,”

subject:一句话描述此次提交的主要内容,做到言简意赅。


自定义 commitlint 规范

https://commitlint.js.org/#/reference-rules

在这里插入图片描述

我们可以通过修改 commitlint.config.js 来自定义我们的提交规范,如:

rule配置说明:rulename和配置数组组成,如:'name: [0, 'always', 72]',数组中第一位为level,可选0,1,2,0为disable,1为warning,2为error;第二位为是否启用,可选always|never,第三位该rule的值。具体配置例子如下:

// commitlint.config.js
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'test', 'upd', 'feat', 'fix', 'refactor', 'docs', 'chore', 'style', 'revert',
    ]],
    'type-case': [0],
    'type-empty': [0],
    'scope-empty': [0],
    'scope-case': [0],
    'subject-full-stop': [0, 'never'],
    'subject-case': [0, 'never'],
    'header-max-length': [0, 'always', 72],
  },
};

根据 commit message 自动生成 changelog

安装依赖

npm install conventional-changelog conventional-changelog-cli conventional-changelog-custom-config compare-func --save-dev

或者

yarn add conventional-changelog conventional-changelog-cli conventional-changelog-custom-config compare-func --save-dev

自定义 changelog

在根目录创建的 changelog-option.js 文件

const compareFunc = require('compare-func')

module.exports = {
  writerOpts: {
    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 (discard) {
        return
      } else if (commit.type === 'docs') {
        commit.type = '📝 Documentation | 文档'
      } else if (commit.type === 'style') {
        commit.type = '💄 Styles | 风格'
      } 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',
    notesSort: compareFunc
  }
}

添加脚本

修改 package.json 中 scripts 字段

{
  "scripts": {
     "version": "conventional-changelog -p custom-config -i CHANGELOG.md -s -n ./changelog-option.js && git add CHANGELOG.md",
	 "postversion": "git push --tags",
	 "changelog": "conventional-changelog -p custom-config -i CHANGELOG.md -s -n ./changelog-option.js && git add CHANGELOG.md"
  }
}

在这指定配置文件位置,我们放在了根目录,也可以指定其他地方

配置项说明:

  • -p custom-config 指定风格*
  • -i CHANGELOG.md 指定输出的文件名称
  • -s 输出到infile,这样就不需要指定与outfile相同的文件
  • -r 从最新的版本生成多少个版本如果为0,则整个更改日志将被重新生成,输出文件将被覆盖。默认值:1
  • -n ./changelog-option.js 指定自定义配置

自动生成 CHANGELOG.md 文件

执行 npm version 的时候会自动生成


手动生成 CHANGELOG.md 文件

直接运行下面的命令即可

npm run changelog

在这里插入图片描述

如果typefeatfixperfrevert,则该 commit 将肯定出现在 Change log 之中。其他情况(docschorestylerefactortest)由你决定(通 commitlint.config.js 配置)。


如何使用


第一步,提交 commit

按照上面的 git commit 提交格式提交代码


第二步,用命令升级版本号

注意,版本的log使用 npm version <newversion> 才会生成新的log,手动修改 package.json version 不会有新的版本log

我们使用如下命令来升级项目版本号

命令作用执行结果version
npm version patch升级修订号首次执行2.0.0-0 -> 2.0.0
再次执行2.0.0 -> 2.0.1
npm version minor升级次版本号2.0.1 -> 2.1.0
npm version major升级主版本号2.1.0 -> 3.0.0

注意

npm version <newversion> 后会自动生成 git tag,在git push 时还要 git push --tags。因为changelog读取的就是git tag




参阅

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__畫戟__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值