手动维护npm包容易出现一些问题:忘记编译、多提交一些无关文件、网络不通等。自动化发布能够极大地简化这个过程。
最近刚调整过一次自动化流程,可以自动发布版本,及根据Commit消息生成Changelog。实现如下图所示的效果:
下面介绍下具体的配置过程。
前置要求
在开始之前,需要准备如下的材料:
- npm token,用于发布。获取方式参见:https://docs.npmjs.com/creating-and-viewing-authentication-tokens
步骤列表
- 设置约定式提交 Conventional Commits生成Changelog
- 设置Github Actions自动发布版本
- 设置自动生成Github Release及Changelog
设置约定式提交Conventional Commits生成Changelog
约定式提交 Conventional Commits 是一种Commit消息规范,它要求开发者按照规范编写Git Commit消息,并可根据Git Commit消息自动生成Changelog。
本文中Changelog的生成也是根据此规范自动处理的。
在npm工程中,要设置Conventional Commits,需要做如下几个方面的处理
设置npm version命令自动生成Changelog
可以在package.json
的scripts中添加一个version命令,内容如下:
1 "scripts": { 2 "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md" 3 },
同时,安装下相应的依赖conventional-changelog-cli,全局安装或在项目中安装均可。我用的是全局安装
1npm i -g conventional-changelog-cli
这样配置以后,在执行npm version patch|minor|major
时,会相应地自动更新Changelog文件。
设置Git hook
上面的conventional-changelog设置好了机制,另外还需要提交的时候遵守约定式提交 Conventional Commits规范才能实现自动生成Changelog的功能。
为了避免写出不规范的Commit消息,可考虑添加Git hook,在提交代码时检查Commit消息是否合法。
首先安装husky用来管理git hook:
1npm i -D husky
再添加husky的配置文件.huskyrc
,添加提交消息的git hook
1{ 2 "hooks": { 3 "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 4 } 5}
这里我们使用了commitlint进行commit消息的规范校验。
一般来说,使用Angular团队推荐的Conventional Commits规范格式即可,有需要的可适当自定义。
我使用的commitlint配置文件(commitlint.config.js)如下:
1module.exports = { 2 extends: ['@commitlint/config-conventional'] 3}
相应地,还需要安装commitlint
的命令行工具及规范包,推荐还是全局安装即可:
1npm install -g @commitlint/cli @commitlint/config-conventional
如上步骤配置完之后,就有了一套可用的changelog生成机制了。
Git commit之后,试试npm version patch
,看看是不是发布了新版本,并自动添加了CHANGELOG.md文件?
设置Github Actions自动发布版本
上一节讲的还都是一些本地操作,本地使用npm version patch|minor|major
发布版本时自动生成Changelog。下面要讲的就是怎么跟Github结合,以及如何使用Github Actions发布版本。
设置postversion script
在package.json中添加postversion脚本,可在npm version patch|minor|major
之后,自动将代码和tag推送到Github上。
设置方式为:
1 "scripts": { 2 "postversion": "git push --follow-tags", 3 },
如果不添加这种脚本,自己每次手动push也行。
设置项目的Github Secrets
自动化发布过程中,涉及到npm身份的校验。我们是用的NPM_TOKEN来解决这个问题。(NPM_TOKEN的生成见https://docs.npmjs.com/creating-and-viewing-authentication-tokens)
但是NPM_TOKEN是不能直接写在代码中的,安全性太低,需要保存在Github Secrets中,再在Actions中再使用。
关于Secrets的创建,可以参阅Github上的指南:https://help.github.com/cn/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets。
- 在 GitHub 上,导航到仓库的主页面。
- 在仓库名称下,单击 Settings(设置)。
- 在左侧边栏中,单击 Secrets(密码)。
- 在 "Name"(名称)输入框中输入密码的名称。
- 输入密码的值。
- 单击 Add secret(添加密码)。
设置自动发布
在上面的步骤中,我们使用npm version patch|minor|major
等创建了Tag,并使用postversion
中的脚本自动将其推送到了Github仓库。
现在我们可以通过检测新tag,自动执行工作流来进行npm publish
的操作。Github上可用的CI/CD服务很多,这里我选择的是其自带的Github Actions。
要使用Github Actions,只需要在相应的仓库中,创建一个 .github/workflows/
目录,并在其中加入一些.yml
后缀的配置文件即可。
我们先添加一个用于npm publish
的配置文件.github/workflows/publish.yml
,文件名是随意定义的。
1on: 2 push: 3 tags: 4 - 'v*' # 这段的意思是仅在出现名为 v 字符开头的tag时,触发此任务,如v1.2.1 5name: Publish 6jobs: 7 # test: # test任务可选,视情况决定是否添加 8 # runs-on: ubuntu-latest 9 # steps: 10 # - uses: actions/checkout@v2 11 # - uses: actions/setup-node@v1 12 # with: 13 # node-version: 10 14 # - run: npm i 15 # - run: npm test 16 17 publish: 18 # needs: test 19 runs-on: ubuntu-latest 20 steps: 21 - uses: actions/checkout@v2 22 - uses: actions/setup-node@v1 23 with: 24 node-version: 10 25 registry-url: https://registry.npmjs.org/ 26 - run: npm i 27 - run: npm publish # 如果发布之前需要构建,可添加prepublishOnly的生命周期脚本 28 env: 29 NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} # 上面在Github Secrets中设置的密钥
如果发布之前需要执行构建 ,可在 - run: npm publish
之前加一段类似于- run: npm run build
之类的指令,或者在package.json
中添加prepublishOnly
的脚本:
1{ 2 "scripts": { 3 "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md", 4 "postversion": "git push --follow-tags", 5 "prepublishOnly": "npm run build" 6 } 7}
按上面的方式设置之后,每次执行npm version patch|minor|major
之后,会自动地在Github Actions中创建一个名为publish
的任务,可在Git仓库的 actions 路径下找到它。
现在应已经能正常地执行npm仓库的发布了。
设置自动生成Github Release
上面已经有了自动化的npm版本发布,且也已经自动地在CHANGELOG.md文件中生成了changelog。不过它现在还实现不了
这样的效果。
需要调用下Github Release方面的API,生成对应的Release才可以。
因为我们已经在CHANGELOG.md中自动填充上了changelog,所以此处不再需要conventional commits的解析了。我选择的是用一个解析changelog.md生成Github Release的工具:github-release-from-changelog。
下面我们再修改下 .github/workflows/publish.yml
,添加上对Github Release的支持。
1on: 2 push: 3 tags: 4 - 'v*' 5name: Publish 6jobs: 7 # test: 8 # runs-on: ubuntu-latest 9 # steps: 10 # - uses: actions/checkout@v2 11 # - uses: actions/setup-node@v1 12 # with: 13 # node-version: 10 14 # - run: npm i 15 # - run: npm test 16 17 publish: 18 # needs: test 19 runs-on: ubuntu-latest 20 steps: 21 - uses: actions/checkout@v2 22 - uses: actions/setup-node@v1 23 with: 24 node-version: 10 25 registry-url: https://registry.npmjs.org/ 26 - run: npm i 27 - run: npm publish 28 env: 29 NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 30 31 github-release: 32 needs: publish 33 runs-on: ubuntu-latest 34 steps: 35 - uses: actions/checkout@v2 36 - uses: actions/setup-node@v1 37 with: 38 node-version: 10 39 registry-url: https://registry.npmjs.org/ 40 - run: npm i -g github-release-from-changelog 41 - run: github-release-from-changelog 42 env: 43 GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
上面的github-release
任务即是本次新增的Github Release任务,它的主要内容就是安装和执行github-release-from-changelog。
过程中会用到名为GITHUB_TOKEN
的密钥,用于访问Github相关的API,不过这个私钥是Github Actions默认提供的,不需要额外设置。
上面的步骤完成之后,整个事情就大功告成了!
总结
总结下上面进行的改动,有如下几点:
-
获取NPM_TOKEN,用于发布。获取方式参见:https://docs.npmjs.com/creating-and-viewing-authentication-tokens
-
将上面获取到的NPM_TOKEN添加到Github Secrets中,设置变量名为NPM_TOKEN。设置方式参见:https://help.github.com/cn/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets。
-
全局安装一些工具包,或安装在项目的devDependencies中
1npm i -g @commitlint/cli @commitlint/config-conventional conventional-changelog-cli 2 3# 或 npm i -D @commitlint/cli @commitlint/config-conventional conventional-changelog-cli
-
在项目中devDependencies中安装如下包:
1npm i -D husky
-
在
package.json
中添加如下的scripts:1{ 2 "scripts": { 3 "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md", 4 "postversion": "git push --follow-tags", 5 "prepublishOnly": "npm run build" 6 } 7}
其中build命令为工程自己配置,不需要的话可以删除
prepublishOnly
脚本。 -
在项目中添加如下的配置文件:
-
.huskyrc
用于设置 git hooks1{ 2 "hooks": { 3 "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 4 } 5}
-
commitlint.config.js
用于设置Git Commit消息规范1module.exports = { 2 extends: ['@commitlint/config-conventional'] 3}
-
.github/workflows/publish.yml
用于设置Github Actions1on: 2 push: 3 tags: 4 - 'v*' 5name: Publish 6jobs: 7 # test: 8 # runs-on: ubuntu-latest 9 # steps: 10 # - uses: actions/checkout@v2 11 # - uses: actions/setup-node@v1 12 # with: 13 # node-version: 10 14 # - run: npm i 15 # - run: npm test 16 17 publish: 18 # needs: test 19 runs-on: ubuntu-latest 20 steps: 21 - uses: actions/checkout@v2 22 - uses: actions/setup-node@v1 23 with: 24 node-version: 10 25 registry-url: https://registry.npmjs.org/ 26 - run: npm i 27 - run: npm publish 28 env: 29 NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 30 31 github-release: 32 needs: publish 33 runs-on: ubuntu-latest 34 steps: 35 - uses: actions/checkout@v2 36 - uses: actions/setup-node@v1 37 with: 38 node-version: 10 39 registry-url: https://registry.npmjs.org/ 40 - run: npm i -g github-release-from-changelog 41 - run: github-release-from-changelog 42 env: 43 GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
-