其他
用 changesets 完成 npm 包从写…
当需要发布一个基于 changesets 的 npm 包(写 changeset、修 CI、合并 Version Packages PR、验证 npm 发布)或排查发布未成功时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 38/100 ×0.15
适用场景
用 changesets 完成 npm 特定
解决思路
- 把整个发布理解为一个工作流、两次连续运行:先推送含待处理 `.changeset/*.md` 的提交到默认分支,CI 用 `changeset version` 生成并更新 `changeset-release/<default-branch>` 分支上的 Version Packages PR,合并该 PR 后同一工作流再次运行并执行 `changeset publish` 发布到 npm、推送 git tag 并创建 GitHub release。
- 本地工作止于“推送 changeset 文件”,版本号和发布都由 CI 负责,绝不在本地做版本化。
- 先读 `uses:` 行确认 `changesets/action` 版本:`@v1` 用 `publish:`,`@v2` 用 `publish-script:`,再诊断“已 version 但未 publish”的运行。
- Step 1 创建 changeset:检查待处理 changeset 及其包覆盖范围,复用覆盖本次发布的那些,仅为未覆盖的变更新增;仅在无关的待发布内容导致发布范围不明确时才询问。
- 默认使用 `patch`,只有用户明确指示才用 `minor` 或 `major`。
- 直接写 changeset 文件(交互式提示需要 TTY),摘要从 `git log --oneline -10` 推断,作为面向用户的 changelog 文本。
- 用 `npx changeset status` 校验文件,包名拼错会在此失败而不是在 CI 中失败。
- Step 2 修复 lint、类型、测试、格式:从 `package.json` scripts(`check`、`lint`、`typecheck`、`test`、`format`、`fix`)发现命令;非 npm 仓库检查 `Makefile`、`Cargo.toml`、`pyproject.toml`、`go.mod`。
- 依次运行 lint、typecheck、test、format;任何代码改动后都从第一个 gate 重新开始(类型修复常破坏 lint,lint 自动修复常破坏测试)。
- 在支持的情况下把自动修复限定到改动文件,然后检查 `git status`:宽泛的 `fix`/`format` 脚本会重排改动之外的文件(MDX 常被波及);只撤销本次运行引入的修复改动,保留同一文件中已有的编辑。
- 每个 gate 的修复循环上限为 5 次,每轮报告剩余错误数,然后停止并报告。
- Step 3 提交并推送 changeset:按显式路径暂存 changeset 文件和范围内的修复,提交前用 `git status --porcelain` 扫一遍 hook 产物(根目录 `schema.gql` 是已知的一种)。
- 提交(`chore: add <type> changeset for <package>`)并推送;推送的提交必须仍包含 `.changeset/*.md`。
- Step 4a 在推送的 SHA 上启动提交监视,每次状态变化输出一行,当该提交的所有运行(CI 和 release 工作流)完成时输出一行 `TERMINAL:`;首次轮询空闲是正常的。
- CI 失败时从 `gh run view <id> --log-failed` 分类:flaky 或基础设施问题用 `gh run rerun <id> --failed`(最多 3 次);真实失败则修复、提交、推送并在新 SHA 上重新监视。
- Step 4b 找到 head 为 `changeset-release/<default-branch>` 的开放 PR;若不存在则运行 PR 等待监视(上限 10 分钟)。
- 仅在三个条件全部满足时合并:head 分支是 `changeset-release/<default-branch>`(标题通常为 "Version Packages",但 `pr-title` 可改名),`gh pr checks <n> --json name,bucket` 每个检查都是 `bucket: pass`,`gh pr view <n> --json mergeable` 为 `MERGEABLE`(为 `UNKNOWN` 时等待并重新查询)。
- 宣布("Merging Version Packages PR #N: <package>@<version>")后执行 `gh pr merge <n> --squash --delete-branch`,或仓库允许的合并方式;任何前置条件失败都停止并报告,绝不合并。
- Step 5 取合并 SHA(`gh pr view <n> --json mergeCommit --jq .mergeCommit.oid`)并在其上运行提交监视;失败时读日志、对照发布失败表、报告并停止,发布失败绝不盲目重试。
- 发布成功后用 `npm view <package>@<version> version` 打印合并的版本,并用 `npm view <package> dist-tags` 确认 `latest` 指向它(pre 模式除外),停止剩余监视并报告这两个输出作为完成证据。
- 失败恢复:gate 5 次迭代后仍失败则停止并报告 gate、剩余错误数、最后错误输出;"Changeset Status" 失败若是缺少 changeset 则回到 Step 1,若是被本地 `changeset version` 消耗则回滚 bump 和 `CHANGELOG.md` 编辑并重新添加 changeset 文件;Version Packages PR 10 分钟后缺失则 `gh run view` 查看 release 运行并确认默认分支上有待处理 changeset 且 `.github/workflows/` 中有 `changesets/action` 步骤。
- 安全分级:绿色(直接执行)为读取 CI/PR 状态、`npm view`、待处理 changeset、`package.json` scripts、git 历史与状态;黄色(一行公告后执行)为写 changeset 文件、运行 lint/type/test/format 修复器、`git add/commit/push`、启动监视、在确认身份且所有检查通过后合并 Version Packages PR;红色(需明确确认)为 force-push、改写历史、修改仓库设置、任何破坏性 git 操作。
- 绝不本地运行 `npx changeset version`(会消耗 `.changeset/*.md`,导致推送的提交没有待处理 changeset、"Changeset Status" 失败、不打开 Version Packages PR;恢复方式是回滚 bump 而非重跑 CI)。
- 绝不直接运行 `npm publish`(绕过 changesets、跳过 changelog 和 tag,并让 Version Packages PR 描述已发布的版本从而报 "You cannot publish over the previously published versions")。
- 绝不手改 `CHANGELOG.md` 或 `package.json` 的 `version`,CI 会在 Version Packages PR 中生成两者,本地编辑会让 bot PR 变成 `CONFLICTING`。
- 注意 `changesets/action@v2` 重命名了所有输入(`publish`→`publish-script`、`version`→`version-script`、`title`→`pr-title`、`commit`→`commit-message`、`branch`→`pr-base-branch`),旧名只给警告,因此 `@v2` 工作流仍用 `publish:` 会打开 Version PR 然后绿色完成却不发布。
- 注意 `setup-node` 的 `node-version: 22` 自带 npm 10.9.x,而 trusted publishing 需要 npm 11.5.1 或更高,因此即使设置了 `id-token: write`,`changeset publish` 也会 `ENEEDAUTH` 失败;改用 Node 24 或在发布前 `npm install -g npm@latest`。
- 注意使用 classic token 的 `NPM_TOKEN` secret 会 `ENEEDAUTH` 失败(npm 已于 2025 年 12 月 9 日撤销所有 classic token),应迁移到 trusted publishing 而非新造 token;有写权限的 granular token 90 天内过期。
- 注意 npm 保存 trusted publisher 时不校验,工作流文件名与 `.github/workflows/<file>.yml` 在大小写或扩展名上不一致只会在发布时以 `ENEEDAUTH` 暴露。
- 注意新的个人仓库会阻止 Actions 打开 PR,release 运行会以 "GitHub Actions is not permitted to create or approve pull requests" 失败且不出现 Version PR;修复方式是 Settings、Actions、General、"Allow GitHub Actions to create and approve pull requests"(组织级设置可覆盖),属红色层级,报告而不要未经要求修改设置。
- 注意 `gh pr list --json headBranch` 和 `gh pr checks --json conclusion` 是无效字段会报错,应使用 `headRefName` 和 `bucket`。
- 注意 Monitor 工具默认 `timeout_ms` 为 300000(5 分钟),超过它的 CI 运行会以看似静默的超时终止监视;CI 监视传 `timeout_ms: 3600000`。
- 每 30 秒或更慢轮询一次,更快的循环会耗尽 GitHub API 速率限制(`gh api rate_limit --jq .resources.core.remaining`)并让发布流程中途停滞。
- 不要用 `git add -A`(会把 pre-commit hook 产物和修复器改动提交进 release commit),按显式路径暂存。
- 没有明确指示时不要用 `major`,它向所有消费者表示破坏性变更,默认用 `patch`。
适用边界 · 注意事项
- 不是基于 changesets 的 npm 包发布流程(如新包脚手架用 `scaffold-cli`,功能 PR 用 `pr-creator`,功能 PR 的评审/冲突/CI 监视用 `pr-babysitter`)。
- 缺少 Git checkout、GitHub CLI 认证、Node.js 或 changesets 发布工作流的环境。
- 需要 force-push、改写历史、修改仓库设置等红色层级操作而未获明确确认时。