这篇脚本通过 GitHub Actions 实现了 CI/CD(持续集成/持续部署)。
通俗地说,你是在 GitHub 的服务器上雇佣了一个“虚拟机器人”。每当你把代码推送到 main 分支时,这个机器人就会醒来,在一台全新的、干净的 Linux 电脑上,把你手动原本要做的所有事情(改版本号、提交、发布)快速执行一遍。
下面我将从流程拆解和底层原理两个维度为你详细剖析。
一、 流程拆解:机器人具体干了什么?
这个脚本是按顺序执行的,我们可以把它看作一条流水线:
1. 触发机制 (Trigger)
on:
push:
branches:
- main
- 动作:你在本地执行了
git push。 - 原理:GitHub 接收到
push事件,检查分支匹配main,于是分配一台 Linux 虚拟机(Runner)开始工作。
2. 赋予权限 (Permissions)
permissions:
contents: write # 允许修改仓库代码
id-token: write # 允许生成身份令牌
- 原理:默认情况下,机器人只有“读”代码的权限。因为我们需要它修改版本号并写回仓库(
git push),所以必须给contents: write权限。id-token是为了 npm 的来源证明(Provenance)。
3. 准备环境 (Setup)
- Checkout: 下载你的代码。注意这里用了
token: ${{ secrets.GITHUB_TOKEN }},这是机器人自带的一把“万能钥匙”,让它有权代表你操作仓库。 - Setup Node: 安装 Node.js v18 环境。
- Git Config: 告诉 git “我是谁”。机器人需要配置用户名(GitHub Action)和邮箱,否则无法生成 commit。
4. 核心魔法:自动升级版本 (npm version)
run: |
npm version patch -m "chore(release): bump version to %s [skip ci]"
这是最关键的一步,底层发生了连锁反应:
- 修改文件:它读取
package.json,把 version 从1.3.5改成1.3.6。 - Git Commit:它自动执行
git add package.json和git commit。 - Git Tag:它自动打了一个
v1.3.6的标签。 - 生成提交信息:提交信息里包含了
[skip ci](这一点至关重要,后面细说)。
5. 写回仓库 (Sync Back)
run: git push
- 动作:机器人把刚才生成的 Commit(包含新版本号)和 Tag 推送回你的 GitHub 仓库。
- 结果:你的 GitHub 仓库现在的代码版本变成了
1.3.6。
6. 发布到 npm (Publish)
run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- 原理:机器人拿着你存好的
NPM_TOKEN(相当于你的 npm 账号密码),向 npm 官方服务器发起请求,上传文件。 - --provenance:这是一个安全功能,它告诉 npm:“这个包是由 GitHub 仓库的自动化脚本构建的,不是某个黑客在地下室偷偷上传的”,这会给你的 npm 包页面增加一个绿色的“来源可信”徽章。
二、 底层原理与关键技术点
1. 身份认证:它是怎么登录的?
整个过程涉及两个系统的认证:
- 对 GitHub 的认证:使用
GITHUB_TOKEN。这是一个临时的、自动生成的令牌。它让脚本有权把修改后的package.json推送回仓库。 - 对 npm 的认证:使用
NPM_TOKEN。这是你手动从 npm 生成并填入 GitHub Secrets 的。环境变量NODE_AUTH_TOKEN被.npmrc文件读取,从而完成登录。
2. 防止“无限死循环” ([skip ci])
这是一个非常巧妙的机制。
-
风险:
- 你 Push 代码 -> 触发 Action。
- Action 改版本号并 Push 回去 -> GitHub 认为又有新代码来了。
- 再次触发 Action -> 改版本号 -> Push...
- 死循环,版本号瞬间爆炸。
-
原理:
GitHub 系统在检查触发条件时,会扫描 Commit Message。如果你在npm version的 message 里写了[skip ci](或者[ci skip]),GitHub 就会知道:“哦,这次提交是机器人自己干的,不用再触发流水线了。”
这就是打断无限循环的熔断器。
3. 为什么用 npm ci 而不是 npm install?
脚本里写的是 npm ci。
- npm install:可能会修改
package-lock.json,比较慢,适合人写代码时用。 - npm ci (Clean Install):严格按照
package-lock.json安装依赖,速度快,不修改文件。这是 CI/CD 环境的标准做法,保证了“你在本地测的是什么,发布的就是什么”。
三、 总结
这个脚本构建了一个闭环:
- 你:负责写业务代码。
- GitHub Action:负责脏活累活(改版本、打标签、发包)。
- npm:负责分发。
你实际上是把**“发布经理”**这个职位,外包给了这一段 50 行的代码。这就是 DevOps(开发运维一体化)的魅力。