开发流程
Conventional Commits + release-please 自动化发版规范,提交即版本
本仓库的版本号、CHANGELOG、npm 发布完全自动化。你只需要做一件事:按规范写 commit message。
剩下的(算 semver、开 Release PR、推 tag、publish npm、开 GitHub Release)由 release-please 在你 push 到 main 后自动完成。
完整流程
开发者本地 GitHub PR main 合并后 自动发布
────── ────── ────── ──────
改代码 CI 跑 type-check/test release-please action release-please
↓ reviewer 看代码 自动开/更新 自动跑
git add 合并 PR "chore(release): vX.Y.Z" npm publish
↓ ↓
git commit -m "feat:" GitHub Release
↓ Tag 推送
git push origin
1. Conventional Commits 规范
1.1 格式
<type>(<scope>): <description>
<body>
<footer>
1.2 type 与 semver 映射
| type | 例子 | 触发什么版本 |
|---|---|---|
feat |
feat: 添加 file sink |
minor (X.Y.Z) |
feat! |
feat!: 升级 Elysia 主版本 |
major (X.Y.Z) |
fix |
fix: logger 在 async context 下崩溃 |
patch (X.Y.Z) |
fix! |
fix!: 修改 httpError 签名 |
major |
perf |
perf: 缓存 pino transport 引用 |
patch |
refactor |
refactor(logger): 抽取 format helper |
不触发版本(隐藏) |
docs |
docs: 更新 usage 例子 |
不触发版本 |
test |
test: 加 ws 集成测试 |
不触发版本 |
build |
build: 升级 tsup 到 8.5 |
不触发版本 |
ci |
ci: 修 windows runner 缓存 |
不触发版本 |
chore |
chore: 清理 dead code |
不触发版本 |
1.3 scope
可选,描述影响范围。推荐用 elogs 的子目录名(便于 CHANGELOG 分组):
feat(otel): ...fix(translator): ...refactor(logger): ...docs(docs): ...(docs site)chore(release): ...(release-please 自己的 commit)
1.4 真实 commit 例子
# patch: 普通 bug 修复
git commit -m "fix(context): 修复 useLogger 在非请求作用域下访问 store 报错"
# minor: 新功能
git commit -m "feat(otel): 支持自定义 span attribute 注入"
# major: 升级 Elysia 主版本(必须用 ! 或 BREAKING CHANGE 标记)
git commit -m "feat!: 升级到 Elysia 3.x 主版本"
# major: 通过 footer 标记
git commit -m "refactor(plugin): 重命名 createElogs → createLogger
BREAKING CHANGE: \`createElogs\` 函数被移除,请改用 \`createLogger\`
"
# 不进 CHANGELOG 的杂项
git commit -m "chore: 删 leftover 调试 log"
git commit -m "refactor(utils): 抽取 pad2 helper(无 API 变化)"
2. 升级 Elysia 主版本(强约定)
@eastgold15/elogs 的 major 必须 = elysia 的 major。 这样用户看一眼版本号就知道依赖兼容性。
2.1 操作流程
当你需要把 peerDependencies.elysia 升到下一个 major 时:
- 改代码 +
peerDependencies.elysia同步升 - 写带
!的 commit 触发 major bump:
git commit -m "feat!: 升级到 Elysia 3.x
- peerDependencies.elysia: >=2.0.0-exp.62 → ^3.0.0
- 适配 Elysia 3 的新 API"
- push → release-please 自动算
3.0.0→ 开chore(release): v3.0.0PR - reviewer 必须在合并前确认 elogs major == elysia major
2.2 为什么不用 CI 校验脚本
理论上可以写个 step 读 node_modules/elysia/package.json#version 与 package.json#version 对比,major 不一致就 fail。但:
- elogs 还没稳定,流程会随需求变
- 人工 review 足够,自动化反而增加维护成本
- 起步阶段先用文档约定,痛了再加脚本
3. 合并 Release PR 的检查清单
Release PR(chore(release): vX.Y.Z)合并前,reviewer 必须确认:
- CHANGELOG.md 描述准确(无 typo、scope 正确)
-
package.json#version与预期 semver 一致- 改动里只有
fix:/perf:→ patch - 有
feat:但无!→ minor - 有
feat!:/fix!:/BREAKING CHANGE:→ major
- 改动里只有
- major 与 Elysia 主版本一致(若本次涉及 Elysia 升级)
- 没有遗漏的
feat!:应当走 major 而走了 minor(看 commits 列表)
4. 本地试运行(可选)
在 push 之前,你可以本地算一下 release-please 会推什么版本:
# 需要 GitHub token(GITHUB_TOKEN),因为 release-please 会调 GitHub API 看 commit 历史
npx -y release-please manifest-pr \
--config-file .github/release-please-config.json \
--manifest-file .github/.release-please-manifest.json \
--token=$GITHUB_TOKEN
或在仓库根跑:
bun run release
5. 常见误区
5.1 ❌ 不要写 update: / add: / change:
只接受 conventional commits 标准的 type(feat / fix / perf / refactor / docs / test / build / ci / chore)。其他 type release-please 不会识别,可能算错版本。
5.2 ❌ 不要把多个不相关的变更塞进一个 commit
# 错
git commit -m "feat: 加 file sink + 修 translator bug + 删无用代码"
# 对:拆三个 commit
git commit -m "feat(output): 加 file sink"
git commit -m "fix(translator): 修 Drizzle translator 空指针"
git commit -m "chore: 删 leftover 调试 log"
5.3 ❌ 不要在 main 上直接 push 改 version
release-please 会自动算 version,你手改 package.json#version 会被它的下一次 commit 覆盖回去。
5.4 ❌ 不要在 PR description 里写变更说明
变更说明放 commit message 里,不是 PR description。release-please 读 commit,不看 PR。
5.5 ✅ squash merge 也 OK
GitHub 的 “Squash and merge” 会把多个 commit 合成一个,只要合成后的 message 符合 conventional commits 规范,release-please 就能正确算版本。
6. 提 PR 时的 PR title 规范
PR title 也要遵循 conventional commits(虽然 release-please 看的是 merge commit,但保持一致更好 review):
feat(otel): 支持自定义 span attribute
fix(translator): 修空指针
docs: 更新 usage 例子
7. 调试发版问题
如果 release-please 没自动开 PR,检查:
- commit message 格式:
git log --oneline -10看最近的 commit 是不是符合规范 - workflow 权限:
.github/workflows/release-please.yml里的permissions块要包含contents: write+pull-requests: write - 配置文件:
.github/release-please-config.json的package字段要等于packages/elogs/package.json#name(@eastgold15/elogs) - manifest 锁定:
.github/.release-please-manifest.json里的.: "2.0.0"是起点 - GitHub Actions 日志:
gh run list --workflow=release-please.yml看最近一次跑的情况
8. 进阶
8.1 多个 feat 同时合并到 main
release-please 会把所有 feat 合并算成一次 minor。例 2 个 feat,明天又合并 1 个 fix → release-please 开 1 个 PR 算 X.Y+1.Z(minor),下一个 release 算 X.Y+1.Z+1(patch)。
8.2 一个 PR 包含 feat + fix
release-please 看最高优先级的:feat! > feat > fix > perf。一个 PR 同时含 feat: 和 fix:,release-please 会算 minor。
8.3 想撤回已发版
npm 版本号发布后不能复用 — 2.0.0 发了就不能再发 2.0.0。要修复只能发 2.0.1 或 2.1.0。如果一定要“撤销”,需要 npm unpublish(有 72 小时窗口限制,且 npm 公司政策越来越严格)。