首页
/ Strapi 提交信息规范全解:基于 commitlint 与 Husky 的 Conventional Commits 实践

Strapi 提交信息规范全解:基于 commitlint 与 Husky 的 Conventional Commits 实践

2026-09-06 18:14:55作者:鲍丁臣Ursa

Strapi 仓库采用一套由 commitlint 强制执行、Husky 本地钩子与 GitHub Actions 双重保障的 Git 提交信息规范。本文以仓库中的技能文档 .ai/skills/git-conventions/SKILL.md 为主体,结合 CONTRIBUTING.md 的 Git Conventions 章节与 .commitlintrc.ts 的实际配置,系统讲解 Strapi 中 type(scope): subject 提交格式的完整规则、合法类型清单、subject 撰写要点与类型决策指南,帮助开发者(以及自动化 Agent)写出既能通过 CI 校验、又能直接用于生成 changelog 的高质量提交信息。

一、规范定位:为什么 Strapi 要强制提交信息格式

CONTRIBUTING.md 在 Git Conventions 章节明确说明了这套约定的目的:

The goal of this convention is to help us generate changelogs that can be communicated to our users.

即提交信息的结构化程度直接决定了 changelog 能否自动、准确地产出。SKILL.md 将 CONTRIBUTING.md 的 "Git Conventions" 章节与 .commitlintrc.ts 共同指定为规范的权威来源(source of truth),这也是本文展开的两条主线:文档层面的撰写规则,以及工具层面的强制执行配置。

二、提交信息格式

SKILL.md 给出的完整格式为:

type[(scope)]: subject

body

各组成部分的规则如下:

  • type 与 subject 必须使用小写
  • subject 结尾不能带句号
  • subject 要描述性地说出提交"是什么",而不是代码"怎么实现"的(具体见后文 Subject 规则);
  • scope 是推荐而非强制的——commitlint 并不校验 scope,但强烈建议带上包名或功能区域,便于在 changelog 中定位与过滤变更。SKILL.md 给出的示例包括 fix(core/core): ...feat(content-manager): ...chore(deps): ...,并列出了一组真实可用的 scope 名称:admincontent-managerdatabasegraphqluploadi18ndepscommitlint
  • body 行宽不被校验——配置中显式关闭了 body-max-line-length 规则;
  • 合并提交被豁免:形如 Merge branch '<x>' into <y> 的提交信息会被 commitlint 直接忽略。

源码层面的执行机制

从仓库配置看,这些规则并非停留在文档里,而是有完整的落地链路:

  1. commitlint 配置.commitlintrc.ts 继承 @commitlint/config-conventional,通过 type-enum 规则以 Error 级别(always)限定合法 type 集合,并显式禁用 body-max-line-length。其 ignores 字段用一个正则 /^Merge branch '.*' into [a-zA-Z0-9\/\-_]+$/ 实现了"GitHub 合并提交豁免",与 SKILL.md 的描述逐字对应;
  2. 本地钩子.husky/commit-msg 在每次 git commit 时执行 yarn exec commitlint --edit "$1",即在本地提交阶段就完成校验,非法提交在推送到远端之前就会被拦截;
  3. CI 兜底.github/workflows/commitlint.yml 在每次 pull_request 事件上运行 npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose,即对 PR 中相对基线分支新增的全部提交逐条校验。这保证了即便本地钩子被绕过(git commit --no-verify),CI 仍能拦截不合规范的提交;
  4. 工具版本package.json 中锁定 @commitlint/cli 19.2.0、@commitlint/config-conventional 19.1.0,并同时引入了 @commitlint/prompt-cli 19.2.0——后者支撑了 AGENTS.md 中提到的交互式提交命令 yarn commit,它会在提交时引导你选择 type 等字段,从输入端减少手写格式错误。

三、合法的提交类型

.commitlintrc.tstype-enum 的完整清单为 chorecidocsenhancementfeatfixreleaserevertsecuritytestfuture 共 11 种。SKILL.md 对每种类型的适用场景给出了说明:

Type 适用场景
feat 新功能
fix 缺陷修复
enhancement 对已有功能的改进(性能、重构、UX 打磨等)
chore 内部清理、工具链、无行为变化的重构、依赖升级
docs 纯文档变更
test 新增或更新测试
ci CI/CD 流水线变更
security 安全修复或加固(常见形式为 security(deps): ...
revert 回滚此前的提交
release 发布提交(预留给发布工具使用)
future 处于 future flag 之后的工作

一个关键陷阱:perfrefactor 等类型会被拒绝

SKILL.md 特别指出,不在上述清单中的 perfrefactorstylebuildimprovementwip 这些 Conventional Commits 社区常见类型在 Strapi 中会被 commitlint 直接拒绝。这一点容易让熟悉社区规范的开发者踩坑。

文档同时给出了替代路径:refactorperf 作为 type 前缀被拒绝,但这不意味着对应的工作无法提交——按 SKILL.md 的说法,应将这类工作路由到:

  • enhancement:当重构/性能优化改善了产品或功能本身时;
  • chore:当它只是内部整理、不产生任何产品变化时。

四、Subject 撰写规则

CONTRIBUTING.md 的核心要求是:subject 概括提交是关于什么(what),而不是代码在做什么(how)。SKILL.md 在此基础上进一步要求:

  • 优先使用 scope,即 type(scope): subject,例如 fix(core/core): xxx,scope 指向被改动的包或功能区域,保持提交历史可过滤;
  • 各类型的 subject 应回答的问题分别是:
    • feat(scope): <这个功能是什么>
    • fix(scope): <这个问题是什么>——描述 bug 本身,而不是描述修复手段
    • chore(scope): <这个 PR 是关于什么的>
    • docs(scope): <记录了什么>

其中对 fix 的约束最为严格。CONTRIBUTING.md 与 SKILL.md 都附带同一条警示:

⚠️ For a fix commit, the subject must describe the bug being fixed, not the solution.

CONTRIBUTING.md 给出的正反例对照:

  • 正确:fix: unable to publish documents due to missing permissions(描述用户遇到的故障现象)
  • 错误:fix: add permission check(描述代码层面的解决动作)

CONTRIBUTING.md 中还有一组覆盖各类型的完整示例,可作日常撰写参照:

  • feat: introduce document service
  • fix: unable to publish documents due to missing permissions
  • chore: refactor data-fetching in EditView to use react-query
  • docs: document service API reference

AGENTS.md 的 Quality Gates 一节给出的带 scope 示例与之互相印证:

feat(content-manager): add bulk delete action
fix(database): preserve relation order during publish
chore(admin): migrate data-fetching to react-query

五、类型决策指南

当一次改动"看起来"可以归入多个类型时,SKILL.md 的 Decision Guide 给出了一组按序判断的决策路径:

  1. 面向用户的新能力?→ feat
  2. 已有功能出现了故障?→ fix(subject 描述 bug 本身)
  3. 已有功能、代码、UX 或性能获得了有意义的改进(包括改善运维行为的内部替换)?→ enhancement
  4. 不改变产品的仓库日常维护——依赖、工具链、构建配置、示例清理、仅 lint/format 的改动?→ chore(依赖升级使用 chore(deps): ...
  5. 纯文档?→ docs
  6. 纯测试?→ test
  7. 仅改动 CI/workflow 文件?→ ci
  8. 安全公告或加固?→ security
  9. 工作在 future flag 之后?→ future

这套顺序隐含了优先级:先判断是否改变产品行为(feat/fix/enhancement),再退化为仓库内部维护(chore/docs/test/ci/security),releasefuture 属于特殊保留场景。

六、实操要点速查

结合仓库中的工具链配置,日常提交 Strapi 时可以直接按以下流程操作:

  • 本地校验:提交时由 Husky commit-msg 钩子 自动运行 commitlint --edit,无需手动执行校验命令;
  • 交互式提交:使用 yarn commit 触发 @commitlint/prompt-cli 的交互提示(由 package.json 中引入的 @commitlint/prompt-cli 提供),可逐项选择 type 并自动生成合规前缀;
  • PR 阶段commitlint CI 工作流 会对 PR 引入的所有提交做 --from base --to head 的批量校验,注意这意味着整个分支历史上新增的每一个提交都要合规,而不仅仅是最后一次 squash 后的信息;
  • 例外情况:仅 Merge branch '...' into ... 形式的 GitHub 合并提交被豁免,其余任何自由格式(包括 WIP、临时占位提交)都会失败;
  • 依赖变更:如果改动了任意 package.jsonAGENTS.md 还要求运行 yarn version:check 确认版本号与变更类型匹配。

七、小结

Strapi 的提交信息规范是一个"文档 + 配置 + 钩子 + CI"四位一体的体系:CONTRIBUTING.md 定义撰写原则,.commitlintrc.ts 把原则固化为可执行规则,.husky/commit-msgcommitlint.yml 分别在本地和云端执行校验,而 AGENTS.md 面向自动化 Agent 复述了同一套约束。理解这套体系的两个重点在于:其一,Strapi 的合法 type 集合是社区 Conventional Commits 的变体——enhancementsecurityfuturerelease 是 Strapi 特有的,而 refactorperf 等社区常用类型在此被明确拒绝;其二,fix 类提交的 subject 必须描述故障现象而非解决手段,这条规则虽无法被 commitlint 机器校验,却是整个规范中唯一被反复强调的撰写性约束。

登录后查看全文
热门项目推荐
相关项目推荐