发布指南
本指南说明 dependfix 的 npm 发布流程、版本策略与发布自动化配置。
发布包清单
当前 Monorepo 对外发布两个 npm 包:
| 包 | 说明 | npm 地址 |
|---|---|---|
dependfix | CLI 应用入口(含 dependfix bin 命令) | https://www.npmjs.com/package/dependfix |
@dependfix/core | 核心领域模型库 | https://www.npmjs.com/package/@dependfix/core |
版本策略
- 0.x 即预览版:当前处于开发阶段,
0.1.0及后续0.x版本直接作为latest发布,不加beta等预发布后缀。理由:0.x在 semver 中本身就是"初始开发、API 不稳定"语义,已充分表达预览状态;- npm 默认不安装带预发布后缀的版本(需显式
dependfix@beta),会给预览测试设置障碍; - changesets 的 pre 模式会增加每轮发布的维护成本。
- 稳定信号来自
1.0.0:API 稳定后发布1.0.0,届时再启用@v1滚动 tag(GitHub Action 引用)。 - 版本号由 Changesets 管理(
.changeset/),包版本升级语义(patch / minor / major)在提交时通过 changeset 声明;CHANGELOG 由pnpm changelog基于 conventional commits 生成(见"CHANGELOG 策略")。
发布架构
| 阶段 | 触发方式 | 认证方式 | 发布命令 |
|---|---|---|---|
首次发布 0.1.0 | 手动(一次性) | npm 账号登录(npm login) | pnpm publish(本地) |
后续版本 0.1.1+(0.x 阶段) | workflow_dispatch 手动触发 | OIDC Trusted Publishing(无 NPM_TOKEN) | pnpm changeset publish(CI) |
1.0.0+(正式版,规划) | 手动 + schedule 定时自动发布(可选 push) | OIDC Trusted Publishing | pnpm changeset publish(CI) |
0.x 阶段仅手动发布:
release.yml未启用on.push/on.schedule自动触发(每次推送触发 release 不符合 0.x 预览期的发布节奏)。定时自动发布配置已按 momei 模式内嵌(每周六 UTC+0 12:00 = UTC+8 20:00),1.0.0 正式版发布后取消schedule注释即可启用,自动发布逻辑(版本提升 + 日志生成 + 提交推送)无需额外配置。发布底层始终是
pnpm publish(changeset publish在 pnpm 项目内部调用它),它会自动把workspace:*依赖替换为实际版本号,保证发布产物可被消费者正常安装。不要改用裸npm publish:npm 不会替换workspace:*,会把字面量发布到 registry。
前置配置(一次性)
1. npmjs.com 配置 Trusted Publisher
为每个包分别配置(每个包只能配置一个 Trusted Publisher):
- 打开
https://www.npmjs.com/package/<包名>/access(注意是包级设置页,不是账号设置页); - 在 Trusted Publisher 区域点击添加;
- 选择 GitHub Actions 并填写:
- Organization or user:
dependfix - Repository:
dependfix - Workflow filename:
release.yml - Allowed actions:
npm publish
- Organization or user:
- 两个包(
dependfix与@dependfix/core)都要配置。
⚠️ 包必须已存在于 npm 上才能配置 Trusted Publisher(npm/cli#8544)。因此
@dependfix/core的首次发布必须先手动完成(见下),之后才能配置并启用 OIDC。
2. package.json 元数据
repository.url 建议与 GitHub 仓库保持一致(dependfix/dependfix,大小写敏感):OIDC 的匹配依据是 npmjs.com 上配置的 Trusted Publisher,provenance 依据 GitHub Actions 环境,两者虽不读取该字段,但保持正确有利于 npm 包页展示与发包工具校验:
{
"homepage": "https://github.com/dependfix/dependfix#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/dependfix/dependfix.git"
},
"bugs": {
"url": "https://github.com/dependfix/dependfix/issues"
}
}3. CI 环境要求
- pnpm 版本:发布走
pnpm publish的 OIDC 路径。pnpm 11.0.3 存在 OIDC 回归(pnpm/pnpm#11566,已修复),CI 使用pnpm/action-setup@v4默认解析的最新 pnpm(11.x 后期 / 12.x)即可; - npm 版本:
changeset publish内部会用npm info探测 registry,release.yml 中通过npm install -g npm@latest保持较新; release.yml已配置permissions: id-token: write。
首次发布(0.1.0,手动,一次性)
前置条件:
pnpm publish默认执行 gitChecks(当前分支为master、工作区干净、与 remote 同步),不满足会中止发布。先确认:
git branch --show-current # 期望 master
git status --porcelain # 期望无输出(工作区干净)
git fetch && git log HEAD..@{u} # 期望无输出(无落后提交)正式发布:
# 1. 质量门全绿
pnpm lint
pnpm typecheck
pnpm test
pnpm build
# 2. 检查包内容(确认 dist / bin / README / LICENSE 都在)
pnpm --filter @dependfix/core pack --pack-destination "$env:TEMP" # Windows PowerShell
pnpm --filter dependfix pack --pack-destination "$env:TEMP" # Windows PowerShell
# bash/zsh 使用:pnpm --filter @dependfix/core pack --pack-destination /tmp
# 3. 本地试跑构建产物
node packages/cli/dist/bin.mjs --help
# 4. npm 登录(一次性,pnpm publish 复用 npm 凭据)
npm login
# 5. 发布(顺序重要:先被依赖方 @dependfix/core,再 dependfix)
# 必须使用 pnpm publish:它会替换 workspace:* 为实际版本
pnpm --filter @dependfix/core publish
pnpm --filter dependfix publish
# 6. 打 tag(供 GitHub Release 关联与 Action 引用)
git tag v0.1.0
git push origin v0.1.0
# 7. 验证
npm view dependfix version # 期望 0.1.0,dist-tags.latest
npm view @dependfix/core version # 期望 0.1.0
npm view dependfix dependencies # 期望 @dependfix/core 为具体版本(非 workspace:*)
npm i -g dependfix && dependfix --version # 或临时目录 npx dependfix --help
# 8.(可选)GitHub Release(预览版标记 pre-release)
gh release create v0.1.0 --generate-notes --prerelease
# 9. 在 npmjs.com 为两个包配置 Trusted Publisher(见"前置配置")后续版本(0.1.1+)
常规流程
# 1. 代码变更时创建 changeset(选择受影响包 + 版本类型 + 变更描述)
pnpm changeset
# 2. 版本提升(消费 .changeset/*.md,更新 package.json 版本)
# changelog 已禁用("changelog": false),此步骤无需 GITHUB_TOKEN
pnpm changeset version
# 3. 生成 CHANGELOG(基于 conventional commits 重新生成三份日志,见"CHANGELOG 策略")
pnpm changelog
# 4. 审查并提交(含包级 CHANGELOG.md 与 package.json 版本变更)
git add -A && git commit -m "chore(release): 版本提升至 x.y.z"
# 5. push 到 master(提交本身不触发发布;0.x 阶段发布由手动 workflow_dispatch 触发)
git push origin master
# 6. 手动触发发布:GitHub Actions → Release → Run workflow(workflow_dispatch)定时自动发布(1.0.0+ 启用)
release.yml 已内嵌 schedule 定时发布(每周六 UTC+0 12:00 = UTC+8 20:00,参照 momei),1.0.0 正式版发布后取消 schedule 注释即启用。定时触发时 CI 自动完成:
changeset version(消费待发布 changeset,无则无操作)+pnpm changelog(生成日志)+ 提交并推送 master;- 随后执行与手动发布相同的完整流程:质量门 → changelog 校验 →
changeset publish(OIDC)→ push tags。
手动发布(workflow_dispatch)时跳过自动版本提升步骤(版本已在本地提升并提交)。
CI 发布行为
release.yml(workflow_dispatch 手动触发;1.0.0 后增加 schedule 定时触发)依次执行:
- (仅
schedule触发)Auto version & changelog:自动版本提升 + CHANGELOG 生成 + 提交推送; - lint → typecheck → test → build(质量门,任一失败即中止);
Verify changelog is up to date:校验三份 CHANGELOG 已包含当前版本段(防止漏跑pnpm changelog直接发布;普通提交版本未变时自动通过);pnpm changeset publish:- 只发布有 changeset 记录的包,无变更时安全退出(
No unpublished projects to publish); - 在 pnpm 项目内部调用
pnpm publish:自动替换workspace:*为实际版本,发布顺序由 changesets 编排(@dependfix/core先于dependfix); - 通过 OIDC trusted publishing 认证(
id-token: write+ npmjs.com 的 Trusted Publisher 配置),无需NPM_TOKEN; - 发布成功后本地创建
<pkg>@<version>格式的 git tag(如dependfix@0.1.1);
- 只发布有 changeset 记录的包,无变更时安全退出(
Push release tags:将 changeset publish 创建的本地 tag 推送到 GitHub(git push origin --tags,通过GITHUB_TOKEN认证)。
tag 策略与包版本不同步
- 发布不需要手动打
v*tag:changeset publish只发布有变更的包,包版本不同步(例如只 bump 了dependfix,@dependfix/core未变)时未变更的包会被自动跳过,不存在"一个 tag 表达不了多版本"的问题; changeset publish成功后会为每个发布的包创建<pkg>@<version>格式的 git tag(changesets / lerna 生态惯例),由 CI 的Push release tags步骤推送到 GitHub,供 GitHub Release 关联与后续精确回溯;- 注意:若发布成功但后续步骤失败导致重跑,已发布的包会被跳过、tag 不会重建(可从 Git 历史手动补打);
- 首次发布的
v0.1.0tag 仅用于 GitHub Release 展示与 Action 引用;文档中的uses: dependfix/dependfix@v1滚动 tag 待1.0.0稳定版发布后再启用。
CHANGELOG 策略
- changesets 不负责生成 changelog(
.changeset/config.json中"changelog": false),仅负责版本提升与发布; - CHANGELOG 由
pnpm changelog生成(scripts/changelog.mjs),基于 conventional commit 消息 +conventional-changelog-cmyr-config(与 momei / semantic-release-cmyr-config 生态同一套格式):- 根级
CHANGELOG.md:全仓库的 feat/fix/refactor 类 commit(chore/ci/docs 等类型由 preset 过滤,不进入日志;全局改动如 CI / 文档 / workspace 配置自然不展示),版本段以dependfix@tag 序列划分(dependfix 为主交付物,core 单独发布的变更会随下一次 dependfix 发布段出现); - 包级
CHANGELOG.md(packages/cli、packages/core):按git log -- <path>精确过滤——只有实际改动该包路径的 commit 才会进入对应日志(一个 commit 同时改两个包时会同时出现在两包日志中,这是真实影响面的体现); - 分组语言由根
package.json的changelog.language: "zh"控制(中文 emoji 分组:✨ 新功能 / 🐛 Bug 修复 / 📦 代码重构 等);
- 根级
- 全局改动归属约定:根目录文件(
docs/、.github/、pnpm-workspace.yaml等)不匹配任何包的 path,不会出现在包级日志;若某全局改动确实影响包行为(如 overrides 改依赖解析),应在 commit 中落在包路径内或拆分提交,否则只记录在根级日志; - 生成是幂等的:脚本每次全量重新生成(
releaseCount: 0),不依赖历史 changelog 内容; - 生成时机与边界行为:在
changeset version之后、publish 之前运行(此时新版本尚无 tag,当前版本段输出全部新增 commit);若在版本等于最新 tag 时运行(如 core-only 发布后、或发布后立即重跑),顶层段会复用该版本号并生成自引用 compare 链接,属正常现象,下一版本发布段会自动归位; - 版本标题与 tag:根级与包级日志的版本段均按
dependfix@/@dependfix/core@tag 序列划分(changeset publish 自动创建);无 tag 的首版(0.1.0)从仓库最早 commit 生成; - 依赖变更提示差异:changesets 原会在依赖包变更时向依赖方日志写入
Updated dependencies行,本方案不自动生成(npm 安装时会自动带上新依赖版本,不影响使用); - 依赖版本:必须使用
conventional-changelog@^7(8.x 模板引擎与 cmyr-config 3.x 不兼容)。
已知限制与排查
| 现象 | 原因与处理 |
|---|---|
| 包首次发布时 OIDC 报错 | npm 的 Trusted Publisher 要求包已存在才能配置(npm/cli#8544)。初始版本必须手动发布(pnpm publish + npm login),之后版本可走 OIDC |
| 手动触发发布后所有包都被跳过 | 没有未发布的 changeset(changeset version 未执行或已发布过);这是正常行为,不是错误 |
| 定时发布中途失败(质量门/发布挂) | master 可能处于"版本已提升未发布"状态:人工 workflow_dispatch 重试发布即可,或等待下一定时周期自愈(changeset 未消费则幂等重跑) |
npm publish 发布产物中带 workspace:* | 使用了裸 npm publish。npm 不替换 workspace 协议,必须使用 pnpm publish(changeset publish 内部即走此路径) |
| OIDC 发布报 E404 / E401(pnpm 11.0.3) | pnpm 11.0.3 存在 OIDC 回归(pnpm/pnpm#11566,已修复)。升级 pnpm(或改用 pnpm/action-setup 默认最新版) |
| OIDC 发布报 E401 / Unable to authenticate | 检查:Trusted Publisher 的 workflow 文件名是否与 release.yml 完全一致(大小写敏感);id-token: write 权限是否在发布 job 上;是否使用 GitHub-hosted runner |
pnpm changelog 输出英文分组 | 根 package.json 缺少 changelog.language: "zh"(cmyr-config 从 cwd 的 package.json 读取语言) |
pnpm changelog 报模板错误 | conventional-changelog 被解析为 8.x。必须使用 conventional-changelog@^7(8.x 模板引擎与 cmyr-config 3.x 不兼容) |
| CI 报 "CHANGELOG 缺少版本段" | 版本已提升但漏跑了 pnpm changelog(发布前必须生成并提交日志) |
关于 provenance
- npm 官方在 trusted publishing(OIDC)下会为
npm publish自动生成 provenance 声明;pnpm publish的 provenance 需要显式--provenance标志(changesets 2.31.1 不透传该参数); - 0.1.0 预览阶段不强制要求 provenance(不阻塞发布);后续如需要,可评估升级 changesets 或在发布前补充 provenance 步骤。