Skip to content

refactor(ci):项目提交名重新升为“约定式提交规范” (Conventional Commits)#288

Merged
sunyink merged 3 commits into
mainfrom
refactor(Ci)/hookcommit&changelog
May 23, 2026
Merged

refactor(ci):项目提交名重新升为“约定式提交规范” (Conventional Commits)#288
sunyink merged 3 commits into
mainfrom
refactor(Ci)/hookcommit&changelog

Conversation

@sunyink
Copy link
Copy Markdown
Owner

@sunyink sunyink commented May 21, 2026

Summary by Sourcery

在变更日志生成器中为 Conventional Commit 类型引入分级分组和渲染机制,改善结构并提升对误写提交 scope 情况的处理。

Enhancements:

  • 将变更日志中的提交分组重构为第一级(功能/质量)和第二级(工程)类别,并提供本地化的章节标题。
  • 增加从符合 Conventional Commit 风格的标题中解析提交类型和 scope 的功能,包括在类型和 scope 位置颠倒时进行自动纠正。
  • 更新变更日志渲染逻辑,以便对稳定版本和预发布标签生成不同布局,并在稳定版本中折叠次要(第二级)变更。
Original summary in English

Summary by Sourcery

Introduce tiered grouping and rendering for Conventional Commit types in the changelog generator, improving structure and handling of mis-typed commit scopes.

Enhancements:

  • Refactor changelog commit grouping into Tier 1 (features/quality) and Tier 2 (engineering) categories with localized section titles.
  • Add parsing of commit type and scope from Conventional Commit-style subjects, including automatic correction when type and scope appear reversed.
  • Update changelog rendering to produce different layouts for stable vs prerelease tags and to fold secondary (Tier 2) changes in stable releases.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (2)
  • scripts/changelog_generator.py is excluded by none and included by none
  • scripts/hooks/prepare-commit-msg is excluded by none and included by none

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2e33a22f-2b0d-479c-a744-7b21786a6ecb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor(Ci)/hookcommit&changelog

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 21, 2026

审阅者指南(Reviewer's Guide)

重构变更日志(changelog)生成器,使其使用分级的、兼容 Conventional Commits 的分组系统,并改进类型/作用域解析与工程类次级变更的按需渲染,从而让 CI 提交信息与 Conventional Commits 规范保持一致。

分级 Conventional Commits 变更日志生成流程图

flowchart TD
    A[Commits list
subject messages
ci uses Conventional Commits] --> B[group_commits_by_type]
    B --> C{tier1,tier2,other
structure}
    C --> D[_render_tier tier1
TIER1_TITLES]
    C --> E[_render_tier tier2
TIER2_TITLES]
    C --> F[other commits
appended to tier2]
    F --> E

    G[_get_tag_type current_tag] --> H{tag_type}
    D --> I[Changelog markdown]
    E --> I

    H -->|stable| J[Render tier2
inside details
Engineering section]
    H -->|beta alpha ci| K[Render tier2
expanded
Engineering section]

    J --> I
    K --> I
Loading

文件级变更(File-Level Changes)

变更 详情 文件
在变更日志生成器中引入分级的提交类型分组,并加入 Conventional Commits 解析以及类型/作用域自动纠正。
  • 定义第 1 级(Tier 1)和第 2 级(Tier 2)提交类型集合,并为每种类型配置可读性较好的标题
  • 新增解析器,通过正则表达式从 Conventional Commit 的 subject 中提取提交类型和可选的作用域,并统一转换为小写
  • 重构分组逻辑,根据解析出的类型/作用域,将提交归入 tier1、tier2 和 other 桶中
  • 检测可能的类型/作用域反转(例如 Tier2 类型却带有 Tier1 作用域),在打印控制台警告的同时自动重新归类
scripts/changelog_generator.py
重构变更日志渲染逻辑以使用新的分级结构,并根据发布类型调整 Markdown 布局和标题。
  • 用内部的 _render_tier 辅助函数替换原先扁平的 group_titles 循环,从 tier 字典和标题映射中渲染按类型分组的章节
  • 在渲染每个分组时过滤掉合并提交,并将 “other” 提交合并到最终的 Tier 2 子分组中
  • 通过 _get_tag_type 引入 tag_type 检测,在渲染 Tier 2 内容时区分稳定版与预发布标签
  • 将 Tier 1 分组渲染在“功能与质量更新”部分下,并在稳定版本中使用 HTML
    Details 标签按需折叠或展开“工程与生态基建”下的 Tier 2 分组
scripts/changelog_generator.py
调整提交信息准备(prepare)钩子,使其与 Conventional Commits 命名保持一致(具体细节未在 diff 中完全展示)。
  • 更新 prepare-commit-msg 钩子脚本,以强制或辅助使用符合 Conventional Commits 风格的提交信息(具体逻辑需在完整文件中确认)
scripts/hooks/prepare-commit-msg

提示与命令(Tips and commands)

与 Sourcery 交互(Interacting with Sourcery)

  • 触发新的审阅: 在 Pull Request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 从审阅评论生成 GitHub Issue: 在审阅评论下回复,要求 Sourcery 从该评论创建一个 issue。你也可以在审阅评论下回复 @sourcery-ai issue 来创建对应的 issue。
  • 生成 Pull Request 标题: 在 Pull Request 标题的任意位置写上 @sourcery-ai,即可随时生成标题。也可以在 Pull Request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 Pull Request 摘要: 在 Pull Request 描述正文中任意位置写上 @sourcery-ai summary,即可在相应位置生成 PR 摘要。也可以在 Pull Request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审阅者指南: 在 Pull Request 中评论 @sourcery-ai guide,即可随时(重新)生成审阅者指南。
  • 一次性解决所有 Sourcery 评论: 在 Pull Request 中评论 @sourcery-ai resolve,将所有 Sourcery 评论标记为已解决。如果你已经处理完所有评论且不希望继续看到它们,这会很有用。
  • 关闭所有 Sourcery 审阅: 在 Pull Request 中评论 @sourcery-ai dismiss,以关闭所有现有的 Sourcery 审阅。若你希望从一次全新的审阅开始,这尤其有用——别忘了之后再评论 @sourcery-ai review 触发新的审阅!

自定义你的使用体验(Customizing Your Experience)

打开你的 dashboard 以:

  • 启用或关闭某些审阅功能,例如 Sourcery 生成的 Pull Request 摘要、审阅者指南等。
  • 更改审阅语言。
  • 添加、删除或编辑自定义审阅说明。
  • 调整其他审阅设置。

获取帮助(Getting Help)

Original review guide in English

Reviewer's Guide

Refactors the changelog generator to use a tiered, Conventional Commits–aware grouping system with improved type/scope parsing and conditional rendering of secondary (engineering) changes, aligning CI commit messages with the Conventional Commits spec.

Flow diagram for tiered Conventional Commits changelog generation

flowchart TD
    A[Commits list
subject messages
ci uses Conventional Commits] --> B[group_commits_by_type]
    B --> C{tier1,tier2,other
structure}
    C --> D[_render_tier tier1
TIER1_TITLES]
    C --> E[_render_tier tier2
TIER2_TITLES]
    C --> F[other commits
appended to tier2]
    F --> E

    G[_get_tag_type current_tag] --> H{tag_type}
    D --> I[Changelog markdown]
    E --> I

    H -->|stable| J[Render tier2
inside details
Engineering section]
    H -->|beta alpha ci| K[Render tier2
expanded
Engineering section]

    J --> I
    K --> I
Loading

File-Level Changes

Change Details Files
Introduce tiered commit-type grouping with Conventional Commits parsing and type/scope auto-correction in the changelog generator.
  • Define Tier 1 and Tier 2 commit-type sets and human-readable titles for each type
  • Add a parser that extracts commit type and optional scope from Conventional Commit subjects using regex and normalizes them to lowercase
  • Refactor grouping logic to populate tier1, tier2, and other buckets based on parsed type/scope
  • Detect likely type/scope inversions (Tier2 type with Tier1 scope) and automatically reclassify them while printing a console warning
scripts/changelog_generator.py
Refactor changelog rendering to use the new tiered structure and adjust markdown layout and headings based on release type.
  • Replace flat group_titles loop with an internal _render_tier helper that renders per-type sections from tier dictionaries and title maps
  • Filter out merge commits when rendering each section and consolidate 'other' commits into a final Tier 2 subgroup
  • Introduce tag_type detection via _get_tag_type to differentiate stable vs pre-release tags when rendering Tier 2 content
  • Render Tier 1 groups under a '功能与质量更新' section and conditionally collapse or expand Tier 2 groups under '工程与生态基建' using HTML
    Details for stable releases
scripts/changelog_generator.py
Adjust commit message preparation hook to align with Conventional Commits naming (details not fully shown in diff).
  • Update the prepare-commit-msg hook script to enforce or assist with Conventional Commits style commit messages (exact logic to be confirmed in the full file)
scripts/hooks/prepare-commit-msg

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了两个问题,并留下了一些高层次的反馈:

  • group_commits_by_type 函数在每次运行时都会为疑似 type/scope 反转打印警告,这在 CI 中可能比较嘈杂;建议将其通过现有的日志机制输出,或者用调试标志(debug flag)进行控制。
  • 对以 Merge:' 开头的 subject 的过滤逻辑在 _render_tierother 分支中有重复;可以考虑提取一个小的辅助函数(例如 is_merge_commit),或者对 commits 进行一次预过滤,从而把这条规则集中维护在单一位置。
供 AI Agent 使用的提示(Prompt)
Please address the comments from this code review:

## Overall Comments
- The `group_commits_by_type` function prints a warning for suspected type/scope inversion on every run, which can be noisy in CI; consider routing this through the existing logging mechanism or guarding it behind a debug flag.
- The filtering of `Merge:'` subjects is duplicated in `_render_tier` and the `other` block; consider extracting a small helper (e.g. `is_merge_commit`) or pre-filtering `commits` once to keep this rule maintained in a single place.

## Individual Comments

### Comment 1
<location path="scripts/changelog_generator.py" line_range="77-78" />
<code_context>
+            continue
+
+        # 反转检测:type 是地方词、scope 是行为词 → 自动提升到 Tier 1
+        if type_str in TIER2_TYPES and scope in TIER1_TYPES:
+            print(f"⚠️ 疑似 type/scope 反转: '{subject[:60]}' → 自动提升到 Tier 1,建议改为 {scope}({type_str}):")
+            groups['tier1'][scope].append(commit)
+        elif type_str in TIER1_TYPES:
</code_context>
<issue_to_address>
**suggestion:** Unconditional printing for suspected type/scope reversal may be noisy and hard to control.

This `print` runs on every suspected type/scope reversal and always writes to stdout, which can pollute CI logs or break callers that expect only markdown output.

Please either:
- send this message to stderr,
- guard it with a verbosity/debug flag, or
- collect these warnings and emit them in a controlled way (e.g., a final summary or separate log).

Suggested implementation:

```python
        # 反转检测:type 是地方词、scope 是行为词 → 自动提升到 Tier 1
        if type_str in TIER2_TYPES and scope in TIER1_TYPES:
            print(
                f"⚠️ 疑似 type/scope 反转: '{subject[:60]}' → 自动提升到 Tier 1,建议改为 {scope}({type_str}):",
                file=sys.stderr,
            )
            groups['tier1'][scope].append(commit)
        elif type_str in TIER1_TYPES:

```

To support `file=sys.stderr`, ensure that at the top of `scripts/changelog_generator.py` you have:
- `import sys`

If there is an existing import block, add `import sys` there in a style consistent with the rest of the file.
</issue_to_address>

### Comment 2
<location path="scripts/changelog_generator.py" line_range="331-335" />
<code_context>
+    grouped = group_commits_by_type(commits)
+    tag_type = _get_tag_type(current_tag)
+
+    def _render_tier(tier_dict, tier_titles):
+        """渲染单个 Tier 内各分组,返回 markdown 字符串"""
+        out = ''
+        for type_key, title in tier_titles.items():
+            type_commits = [
+                c for c in tier_dict.get(type_key, [])
                 if not c['subject'].startswith("Merge:'")
</code_context>
<issue_to_address>
**suggestion:** The merge-commit filter is duplicated and could be centralized to avoid divergence.

That condition is now hardcoded both in `_render_tier` and in the `other_commits` handling. If the merge pattern changes, both spots must be updated. Consider extracting a helper like `is_merge_commit(subject)` and reusing it to keep the logic consistent and maintainable.

Suggested implementation:

```python
    tag_type = _get_tag_type(current_tag)

    def _is_merge_commit(commit):
        subject = commit.get("subject", "")
        return subject.startswith("Merge:'")

    def _render_tier(tier_dict, tier_titles):
        """渲染单个 Tier 内各分组,返回 markdown 字符串"""
        out = ''

```

```python
            type_commits = [
                c for c in tier_dict.get(type_key, [])
                if not _is_merge_commit(c)
            ]

```

There is another mention of “merge-commit filter” in the `other_commits` handling that is not shown in the snippet. To fully implement the suggestion, you should:
1. Locate any other merge-commit filters, e.g. conditions like `if not c['subject'].startswith("Merge:'")` or similar.
2. Replace those conditions with calls to `_is_merge_commit` (e.g. `if not _is_merge_commit(c)`), so all merge-detection logic is centralized in the new helper.
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得这些评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈不断改进评审质量。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • The group_commits_by_type function prints a warning for suspected type/scope inversion on every run, which can be noisy in CI; consider routing this through the existing logging mechanism or guarding it behind a debug flag.
  • The filtering of Merge:' subjects is duplicated in _render_tier and the other block; consider extracting a small helper (e.g. is_merge_commit) or pre-filtering commits once to keep this rule maintained in a single place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `group_commits_by_type` function prints a warning for suspected type/scope inversion on every run, which can be noisy in CI; consider routing this through the existing logging mechanism or guarding it behind a debug flag.
- The filtering of `Merge:'` subjects is duplicated in `_render_tier` and the `other` block; consider extracting a small helper (e.g. `is_merge_commit`) or pre-filtering `commits` once to keep this rule maintained in a single place.

## Individual Comments

### Comment 1
<location path="scripts/changelog_generator.py" line_range="77-78" />
<code_context>
+            continue
+
+        # 反转检测:type 是地方词、scope 是行为词 → 自动提升到 Tier 1
+        if type_str in TIER2_TYPES and scope in TIER1_TYPES:
+            print(f"⚠️ 疑似 type/scope 反转: '{subject[:60]}' → 自动提升到 Tier 1,建议改为 {scope}({type_str}):")
+            groups['tier1'][scope].append(commit)
+        elif type_str in TIER1_TYPES:
</code_context>
<issue_to_address>
**suggestion:** Unconditional printing for suspected type/scope reversal may be noisy and hard to control.

This `print` runs on every suspected type/scope reversal and always writes to stdout, which can pollute CI logs or break callers that expect only markdown output.

Please either:
- send this message to stderr,
- guard it with a verbosity/debug flag, or
- collect these warnings and emit them in a controlled way (e.g., a final summary or separate log).

Suggested implementation:

```python
        # 反转检测:type 是地方词、scope 是行为词 → 自动提升到 Tier 1
        if type_str in TIER2_TYPES and scope in TIER1_TYPES:
            print(
                f"⚠️ 疑似 type/scope 反转: '{subject[:60]}' → 自动提升到 Tier 1,建议改为 {scope}({type_str}):",
                file=sys.stderr,
            )
            groups['tier1'][scope].append(commit)
        elif type_str in TIER1_TYPES:

```

To support `file=sys.stderr`, ensure that at the top of `scripts/changelog_generator.py` you have:
- `import sys`

If there is an existing import block, add `import sys` there in a style consistent with the rest of the file.
</issue_to_address>

### Comment 2
<location path="scripts/changelog_generator.py" line_range="331-335" />
<code_context>
+    grouped = group_commits_by_type(commits)
+    tag_type = _get_tag_type(current_tag)
+
+    def _render_tier(tier_dict, tier_titles):
+        """渲染单个 Tier 内各分组,返回 markdown 字符串"""
+        out = ''
+        for type_key, title in tier_titles.items():
+            type_commits = [
+                c for c in tier_dict.get(type_key, [])
                 if not c['subject'].startswith("Merge:'")
</code_context>
<issue_to_address>
**suggestion:** The merge-commit filter is duplicated and could be centralized to avoid divergence.

That condition is now hardcoded both in `_render_tier` and in the `other_commits` handling. If the merge pattern changes, both spots must be updated. Consider extracting a helper like `is_merge_commit(subject)` and reusing it to keep the logic consistent and maintainable.

Suggested implementation:

```python
    tag_type = _get_tag_type(current_tag)

    def _is_merge_commit(commit):
        subject = commit.get("subject", "")
        return subject.startswith("Merge:'")

    def _render_tier(tier_dict, tier_titles):
        """渲染单个 Tier 内各分组,返回 markdown 字符串"""
        out = ''

```

```python
            type_commits = [
                c for c in tier_dict.get(type_key, [])
                if not _is_merge_commit(c)
            ]

```

There is another mention of “merge-commit filter” in the `other_commits` handling that is not shown in the snippet. To fully implement the suggestion, you should:
1. Locate any other merge-commit filters, e.g. conditions like `if not c['subject'].startswith("Merge:'")` or similar.
2. Replace those conditions with calls to `_is_merge_commit` (e.g. `if not _is_merge_commit(c)`), so all merge-detection logic is centralized in the new helper.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread scripts/changelog_generator.py Outdated
Comment thread scripts/changelog_generator.py Outdated
@sunyink sunyink merged commit 60b5fb2 into main May 23, 2026
23 of 24 checks passed
@sunyink sunyink deleted the refactor(Ci)/hookcommit&changelog branch May 23, 2026 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant