使用Github Action自动化发布npm包
GitHub Actions 提供了一种强大的自动化构建和发布流程的方式,通过组合github action的方式形成了workflow,来实现CI/CD。我们完全可以将 npm 包的发布流程集成到 GitHub workflow中,做到自动化发包,这可以可以提高效率并减少人为错误。以下是如何使用 GitHub Actions 实现自动化发布的详细指南。
0. 原理解释
github actions是一个github推出的CI/CD工具,可以模拟平台(比如linux等)自动化执行一些操作。
npm可以通过token实现免登陆发布包,并且Github Secrets能很好的保护token不被泄露(后面会说简单说一下为什么),这样就避免了在登陆信息在CI/CD时泄露
这是我编写的权限验证的一个包,支持vue,react以及函数式调用,同时使用github workflow实现的自动npm化发包。欢迎大家参考,同时提出优化意见:
validate-permission/.github/workflows at main · 2ue/validate-permission · GitHub
1. 准备工作
在开始之前,请确保:
- 你有一个 GitHub 账户,并且已经创建了一个仓库。
- 你的项目中包含一个
package.json
文件。 - 你有一个 npm 账户,并且已经获取了 npm token。
- 你即将发布的包的包名没有被占用。
获取Access Token
首先登陆npm官网,然后点击Access Tokens:
然后进入access Tokens生成页面:
两者任选一个点击进入,两者都可以作为token在github actions中使用,只是Classic Token设置更简单,Granular Access Token设置更多,控制更精细化
点击Classic Token后:一定勾选publish,后面才能正常从github actions推送
点击:Granular Access Token,红框勾选的三个必填:
- Token name:不必多说,token名字,起一个你喜欢的
- Expiration:有效期,默认三十天,可以改得更长,过期后需要重新生成
- Permissions:权限,即生成的token能做什么样的操作,同样需要选择 read && write,不然github actions执行是无法推送
- 其余的选项可以根据需要适当勾选
填写完成后,滑到底部点击Generate token按钮
2. 如何免登陆发布npm包
创建.npmrc文件
前面你已经生成了一个npm的具有publish或者write权限的access token。
那么你只需在项目根目录下创建 .npmrc
文件,写入以下内容这个文件将包含 npm registry 的授权信息。但要注意,因为access token具有你的npm账户读写权利,所有不应该将.npmrc文件提交到远程仓库,需要将该文件加入到.gitignore中
1 | //registry.npmjs.org/:_authToken=你刚刚申请的token |
或者直接在项目根目录命令行执行,将会自动生成:
1 | echo "//registry.npmjs.org/:_authToken=你刚刚申请的token" > .npmrc |
然后,将 .npmrc
文件添加到你的版本控制系统中。
发布
将你准备发布的文件,编译好。假设你已经准备好了,那么就愉快的执行:
1 | npm logout |
或者登陆npm官网,查看刚刚发布的包
发布失败
如果你没有成功,出现如下报错:
1 | npm ERR! need auth You need to authorize this machine using `npm adduser` [https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow](https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow) |
有三个可能原因:
- .npmrc配置问题:确保你的.npmrc文件路径,命名和内容正确
- .npmrc:确保你的access token正确,或者具有publish或write权限
- 本地没有使用npm官方源:由于某些不可描述原因,你将本地npm的源设置为其他源,没有设置为
https://registry.npmjs.org
,比如腾讯源,阿里云云等,此时需要切换过来才能正确
至此使用npm access token发布npm包的流程已经跑通了。
相信大家已经发现了,上面这种方式有一个问题:.npmrc只能放到本地,意味着每次换一个电脑写代码都要重新去复制access token,生成.npmrc,那有没有一种方式可以比较安全的管理它呢,答案肯定是有的:答案就在Github。
我们不但可以利用GitHub Secrets管理npm的access token,而且还可利用github actions能力实现自动化workflow,来自动化发包到npm。
3. 配置 GitHub Secrets
在 GitHub 仓库中添加 npm token:
- 进入 GitHub 仓库的 “Settings” > “Secrets”。
- 点击 “New repository secret”。
- 输入
NPM_TOKEN
作为名称,并粘贴你的 npm token 作为值。 - 保存秘密。
请注意,这里我们可以选择Secrets和Variables,他们都在我们编写的workflow中被读取到,其实都是变量,但是两者有区别:
变量类型 | 存储方式 | 界面是否可见 | 修改内容 | 修改变量名 | workflow是否可见 |
---|---|---|---|---|---|
Secrets | 加密 | 不可见 | 只能更新且更新时不能看到之前内容 | 无法修改 | 以***显示 |
Variables | 明文 | 明文且可见 | 可自由更改且可以看到之前内容 | 可以修改 | 明文可见 |
从上面的比较可以看出为什么github Secrets能够有效的保护npm access token,当然万事不是绝对,如果非要追求百分百安全,那就使用最原始的方式吧,毕竟放在你本地的文件也可能因为中木马泄露出去。 |
4. 编写 GitHub Actions Workflow
至此我们就可以利用github actions来编写一个workflow。让我们捋一下思路:
- 什么时候执行:在代码推送到某分支,或者打tag的时候,这里我们选择当代码推送时
- 执行流程
- 拉取代码
- 设置时区:如果需要
- 设置node环境
- 安装pnpm,yarn等工具:如果需要
- 安装代码依赖,并打包
- 写入token到.npmrc
- 执行npm 发布
当然如果所有的操作都需要我们自己去实现,就比较复杂,好在有第三方action可以快速的让我们实现这些能力:
- run:可以执行脚本命令,让我们可以执行类似npm i这样的命令
- actions/checkout@v4:实现代码拉取
- actions/setup-node@v4:实现node环境,可以指定node版本
那么我们就用这些能力创建一个workflow吧
在项目根目录下创建 .github/workflows/npm-publish.yml
文件,并添加以下内容:
1 | # workflow名字 |
此 workflow 会在推送到 main
分支时触发。
5. 推送更改到 GitHub
将你的更改推送到 GitHub 仓库:
1 | git add . |
6. 测试 Workflow
一旦你推送了更改,GitHub Actions workflow 将会运行。你可以在 GitHub 仓库的 “Actions” 选项卡中查看 workflow 的状态。
7. 发布新版本
当你准备发布新版本时,更新 package.json
中的版本号,然后提交并推送这些更改到 main
分支。GitHub Actions 将自动处理剩余的发布流程。
8.优化
这个workflow脚本还有很多优化的空间,比如:
优化触发时机
如果我们推送代码就执行发包操作,在有些情况下可能不符合我们要求,所有我们可以更改触发条件:
正常情况我们想的是创建了一个v1.0.0这样的tag分支才触发,并且是修改了关键源码才触发
- 设置当推送了tag分支并且需要tag符合某种格式才触发流水
1 | name: Npm publish |
- 设置修改了某些文件才执行发包
1 | - uses: dorny/paths-filter@v3 |
dorny/paths-filter@v3
是github actions
市场的一个包,可以用来检查哪些文件有变动,如果有变动则输出一个变量update,为true时表示有变动,可以用steps.changes.outputs.update来读取这个变量
自动化生成版本号
每次改动需要发布npm包时,都需要修改package.json的版本号,无疑有点麻烦,那我们可以使用npm version
<update_type>
是语义化版本类型之一,如major
、minor
或patch
。- 例如,运行
npm version patch
将会更新版本号为当前版本号的下一个补丁版本
甚至你可以通过github workflow的内置变量拿到tag名字,根据tag特征做到修改哪一个版本号
自动化生成tag和release
如果你的commit比较规范,比如使用了@changesets/cli等,那么可以利用github actions市场的三方包来自动化为你的发布生成changelog,tag,release等信息,比如semantic-release-action等
当然根据个人需求不同,可能还可以做更多的优化,这里就不一一述说了,毕竟本篇文章仅仅是一个穿针引线。
问题总结
问题 1:权限问题
如果你的 npm token 没有足够的权限发布包,你可能会遇到权限错误。[参考](#获取Access Token)
解决方案:确保你的 npm token 有发布包的权限。通常,这意味着你需要在 npm 网站上生成一个具有适当权限的 token。
问题 2:网络问题
如果你的 CI/CD 服务器无法访问 npm registry,发布可能会失败。一般在github上不会出现该问题,可能在本地使用了代理或者切换了npm源会出现这个问题。参考
解决方案:检查你的 CI/CD 服务器的网络设置,确保它可以无障碍地访问 https://registry.npmjs.org/
。
问题 3:Workflow 配置错误
如果你的 workflow 配置有误,它可能不会按预期触发。
解决方案:仔细检查 workflow 文件的语法和配置,特别是触发条件和 secret 的使用。
问题 4:.npmrc问题
如果你的 .npmrc
文件没有被正确地添加到项目根目录或内容不正确,那么可能导致发布失败。参考
解决方案:确保 .npmrc
文件被正确添加到你的版本控制系统,并且格式正确无误。
通过以上步骤和解决方案,你可以确保 npm 包的自动化发布流程顺畅运行。
参考
Using private packages in a CI/CD workflow | npm Docs
Working with the npm registry - GitHub Docs
Variables - GitHub Docs