Auto Changelog with GitLab
上一篇博文 Integrate Renovate with GitLab 中介绍了为私有代码仓库与私有源提供依赖自动检测更新并发起 Merge Request 的方式。Renovate 可以自动通过 Release Notes 获取到版本之间的更新日志,并在 MR 中展示,这为执行合并的评审人提供了极大的便利。
接下来需要解决另一个问题:如何为分散在各处的私有依赖自动生成更新日志?
工具
首先需要说明,自动生成 Changelog 的前提条件是使用 约定式提交 ,这样各类程序才能从 git 仓库的提交记录中提取出有价值的信息并加以整理归类。
可供选择的程序有很多,可以按需选择。这里选用的是 lob/generate-changelog 。
时机
一个合适的生成 Changelog 的时机是创建新 Tag 的时候。如果是一个 npm package,那么执行 npm version xxx
命令的时候就会自动得到一个 Tag,将其推送到远端即可。
也可以使用预定义的脚本:
"release:major": "npm version major && git push origin && git push origin --tags", |
CI
如何驱使 GitLab 来完成 Release Note 的创建,有很多方式。
1. 使用 .gitlab-ci.yml
从 GitLab 13.2 开始,runner 可以使用以下镜像直接操作 Release:
release_job: |
这是最简单的方式。但是由于我司的 GitLab 版本过低,不支持此操作。因此需要另外想办法。
2. bash script
GitLab CI 可以执行一个 bash script,因此可以利用 GitLab 提供的 API,结合一个 Access Token 向 GitLab 发起请求,最终得到 Changelog。
这种方式应该是大多数老版本 GitLab 所使用的。但是它存在一些我认为无法接受的问题:
- 每个项目都需要有此脚本(不过这一点实际上可以通过
npx
绕过); - 每个项目的
.gitlab-ci.yml
都需要修改,这点是无法避免的(实际上方式 1 也存在此问题); - 每个项目都需要配置 Secret Token( Access Token 不可能直接暴露在代码中)。
因此,我觉得这个办法不够优雅。
3. webhook
为了解决以上问题,我决定继续改造之前的博文 Gitlab CE Code-Review Bot 中介绍的评审机器人,让它可以
- 识别 Tag 事件;
- 自动拉取仓库代码;
- 自动生成 Changelog;
- 调用 GitLab API 完成 Release Note 的创建。
首先在入口处加多一个事件监听:
module.exports = async (ctx) => { |
GitLab 并没有区分 Tag 创建与删除的事件,因此需要通过代码判断:
const { after, ref, project_id, project: { git_http_url } } = ctx.request.body |
使用 simple-git 来拉取 Git 仓库,注意这里需要使用 oauth2:Access Token
来完成授权:
const simpleGit = require('simple-git') |
生成 Changelog:
const Changelog = require('generate-changelog') |
最后,使用 GitLab API 将得到的 Changelog 更新上去即可:
/** |
最后的最后,删除之前拉取下来的仓库,这个任务就算完成了。
这么做最大的好处是:仓库启用与否,只需要在 Webhook 处多勾选一个 Tag push
Event 即可,无需任何其他操作。
但是它也有一个不好的地方:如果原仓库特别大的话,拉取可能会非常耗时。不过考虑到 GitLab 和 Bot 一般都会处在同一个内网环境下,这点基本可以忽略。