changeset 是什么?
changeset 是专注于管理版本号和变更日志的工具, 尤其擅长处理多包仓库(monorepo)的版本/更新日志管理
changeset 和 semantic-release 的区别
- monorepos 支持
- Changesets: 是专门为 monorepo 设计的,它能够更好地管理仓库内的多个包及其相互之间的依赖关系
- Semantic-Release: 更加专注单仓库的版本控制,而在处理 monorepo 方面则不是特别好用
- 更新信息存储方式
- Changesets: 会将变更信息写入
.changeset
目录的 markdown 文件, 且可以手动修改它 - Semantic-Release: 从 git 的文件中读取并解析变更信息, 也就是说提交 git 后不能手动修改它
- Changesets: 会将变更信息写入
- CI 环境逻辑
- Changesets: 会根据 changeset 变更信息文件中创建一个
pull-request
, 然后由维护者去决定是否要合并 - Semantic-Release: 直接根据 git 提交记录更新
package.json
version
字段 & 创建新的 git commit 记录
- Changesets: 会根据 changeset 变更信息文件中创建一个
主要功能
- 检查变更状态
- 生成变更信息文件 -> 简化手动变更版本的流程(monorepo 项目,手动修改的话,容易出错) -> 生成 CHANGELOG
- 集成 github Actions -> 自动创建 PR
Changesets 的基本工作流程
1. 安装
sh
# for monorepo
pnpm install -wD @changesets/cli
# for single repo
pnpm install -D @changesets/cli
2. 初始化
sh
pnpm changeset init
3. 创建一个变更记录信息
会在当前目录创建 .changeset
目录, 如果是monorepo, 会在所有子包中添加 CHANGELOG.md
sh
pnpm changeset add
4. 执行变更版本
执行后需要选择需要更新的版本类型, 自动更新 major.minor.patch
数值
sh
pnpm changeset version
5. 发布到 npm
执行后发布到 npmjs.com
, 当然也可以通过 .npmrc
配置发布到 npm 私服
sh
yarn changeset publish
Changesets 配置
jsonc
{
// 加上这个可以在写配置获得代码提示
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
// 如何生成 changelog 信息, 设置为 false 可以禁用这功能
"changelog": "@changesets/cli/changelog",
// 修改版本后, 是否提交文件
"commit": true,
// 多个包进行版本同步升级
"fixed": [],
// 多个包使用同一个版本, 功能类似 fixed 但是不同
"linked": [],
// 是否发布 package 中有 "private":true 的包
// 允许的值为:
// - restricted: 发布私有包
// - public: 仅发布为公开的包,任何人都可以下载(推荐建议使用)
// 注意: 如果使用 changeset publish 命令来发布到 verdaccio 私服, 需要将这个
// 值设置为 public, 否则 {"name": "tools"} 这样的包名会发布失败, 错误信息如下:
// error an error occurred while publishing tools: EUNSCOPED Can't restrict access to unscoped packages.
// 如果非要设置为: restricted, 需要将包名修改为 "@xxx/tools"
"access": "public",
// git 分支名(最好不要修改)
"baseBranch": "main",
// 是否需要更新子包依赖的包, 比如: packageA 依赖于 packageB
// 此时 packageB 版本更新后, packageA 也自动更新版本
"updateInternalDependencies": "patch",
// 忽略哪些不需要 changeset 管理的包, 比如一些公共配置
"ignore": [],
}
集成 Github Actions 自动创建 PR
- 安装 changeset bot
- 配置 github actions secrets, 可参考 semantic-release 的配置方式
- 配置
.github/workflows/changesets-create-pr.yaml
txt
.
├── README.md
├── apps
│ └── web
│ ├── CHANGELOG.md
│ ├── index.html
│ ├── package.json # name: @for-study/web
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.vue # 这个依赖 packages/tools/src/index.js 模块
│ │ └── main.js
│ └── vite.config.js
├── package.json # name: @for-study/root
├── packages
│ └── tools
│ ├── CHANGELOG.md
│ ├── package.json # name: @for-study/tools
│ └── src
│ └── index.js
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
8 directories, 15 files
yaml
name: Changesets
on:
push:
branches:
- main
# 这些路径对应的文件变化之后才会触发这个 workflow
paths:
- ".changeset/**/*.md"
- "packages/**/package.json"
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
changesets:
name: Changesets
runs-on: ubuntu-latest
# 权限设置
permissions:
contents: write
packages: write
pull-requests: write
steps:
# 1. 下载代码
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
# 2. 安装 pnpm
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.10.0
run_install: false
# 3. 安装 nodejs 22
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: "pnpm"
# 4. 使用 pnpm 安装 依赖
- name: Install dependencies
run: pnpm install
# 5. 使用 changesets/action 消费版本变更信息文件
- name: Create PR and publish
id: changesets
uses: changesets/action@v1
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
with:
# 创建 pr 时的提交信息和 pr 的 title
commit: "chore(changeset): update versions"
title: "chore(changeset): update versions"
# publish: 默认会执行 pnpm changeset publish --tag
# 当我改为 pnpm changeset tag 之后就不会发布到 npmjs.com
publish: pnpm changeset tag
# 是否将代码发布到 github release, 默认值为 true
# 但是必须要 publish 步骤执行成功后才会执行发布到 github release 这个步骤
# 假如使用默认的 publish 步骤会失败(因为没有配置 NPM_TOKEN)
createGithubReleases: true
创建PR后自动发布到私有 npm 服务
为什么需要将内容发布到私服
- 在 npmjs.com 上, 创建组织是收费的功能
- 有的代码可能是公司内部用的, 而不是开源的
发布到私有仓库需要满足哪些条件?
- 首先, 必须要有一个公网可以访问的 verdaccio 私服, 搭建教程, 假设服务为
https://yournpmjs.com
- 在本地登录私有服务
npm login --registry https://yournpmjs.com
- 获得本地
~/.npmrc
的authToken
内容 设置到 github actions 的 secrets 中
- 在本地登录私有服务
- 将 registry 和 authToken 登录信息(NPMRC)都设置到
github action secrets
中 - 设置
package.json
的publishConfig
的registry
字段 - 修改
.github/workflows/changesets-create-pr.yaml
内容如下:
yaml
name: Changesets
on:
push:
branches:
- main
paths:
- ".changeset/**/*.md"
- "packages/**/package.json"
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
changesets:
name: Changesets
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.10.0
run_install: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
# 动态生成 npmrc 配置文件
- name: Generate npmrc config
run: echo "${{ secrets.NPMRC }}" > .npmrc
# ls -al 是用来查看 .npmrc 文件是否正常生成
# npm whoami 可以用来验证 .npmrc 是否配置正确
- name: Validate npmrc config
run: |
echo ">>> files" && ls -al
echo ">>> whoami" && npm whoami
- name: Create PR or publish release
id: changesets
uses: changesets/action@v1
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
with:
commit: "chore(changeset): update versions"
title: "chore(changeset): update versions"
# 删除动态前面步骤生成 .npmrc 文件
- name: Clean up npmrc config
run: |
echo "Cleaning up..."
rm -rf .npmrc
ls -al
yaml
"publishConfig": {
"registry": "https://yournpmjs.com"
},
txt
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsX2dyb3VwcyI6WyJhZG1pbiJdLCJuYW1lIjoiYWRtaW4iLCJncm91cHMiOlsiYWRtaW4iLCIkYWxsIiwiJGF1dGhlbnRpY2F0ZWQiLCJAYWxsIiwiQGF1dGhlbnRpY2F0ZWQiLCJhbGwiXSwiaWF0IjoxNzQ2MDM0NjcxLCJuYmYiOjE3NDYwMzQ2NzIsImV4cCI6MTc0ODYyNjY3MX0.7-Wuwd064uyl_spIBsMX4IMussoeP5SVhXOG1IxySck
txt
registry=https://yournpmjs.com
//yournpmjs.com/:_authToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZWFsX2dyb3VwcyI6WyJhZG1pbiJdLCJuYW1lIjoiYWRtaW4iLCJncm91cHMiOlsiYWRtaW4iLCIkYWxsIiwiJGF1dGhlbnRpY2F0ZWQiLCJAYWxsIiwiQGF1dGhlbnRpY2F0ZWQiLCJhbGwiXSwiaWF0IjoxNzQ2MDM0NjcxLCJuYmYiOjE3NDYwMzQ2NzIsImV4cCI6MTc0ODYyNjY3MX0.7-Wuwd064uyl_spIBsMX4IMussoeP5SVhXOG1IxySck
容易出错点:
- npmrc 内容中的
registry
必须和 package.json 中的publishConfig.registry
字段保持一致, 否则报错 - npmrc 总是无法通过验证, 可以在本地新建一个
.npmrc
然后使用npm whoami
来验证是否能够狗正确获取到登录的用户名