Skip to content

ci(wechat-notify): add Sourcery summary extraction with Qwen fallback#892

Merged
keeees merged 1 commit intorelease/v0.3.0from
fix/simple-fix
Apr 14, 2026
Merged

ci(wechat-notify): add Sourcery summary extraction with Qwen fallback#892
keeees merged 1 commit intorelease/v0.3.0from
fix/simple-fix

Conversation

@keeees
Copy link
Copy Markdown
Collaborator

@keeees keeees commented Apr 14, 2026

  • Extract Sourcery AI summary from PR body as primary source
  • Add fallback to Qwen AI summarization when Sourcery summary unavailable
  • Refactor notification payload to conditionally use Sourcery or Qwen summary
  • Update step conditions to skip Qwen processing when Sourcery summary found
  • Improve code formatting and indentation consistency in Python scripts
  • Reduce redundant file I/O by writing directly to GITHUB_OUTPUT

- Extract Sourcery AI summary from PR body as primary source
- Add fallback to Qwen AI summarization when Sourcery summary unavailable
- Refactor notification payload to conditionally use Sourcery or Qwen summary
- Update step conditions to skip Qwen processing when Sourcery summary found
- Improve code formatting and indentation consistency in Python scripts
- Reduce redundant file I/O by writing directly to GITHUB_OUTPUT
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Apr 14, 2026

Reviewer's Guide

此 PR 更新了 WeChat 发布通知工作流:优先从 PR 正文中提取由 Sourcery 生成的总结,只有在未找到 Sourcery 总结时才回退到基于 Qwen 的 AI 总结,同时简化输出处理并改善 Python 代码格式。

WeChat 通知工作流中优先使用 Sourcery 总结的时序图

sequenceDiagram
    participant Dev
    participant GitHubPR as GitHub_PR
    participant Workflow as GH_Actions_Workflow
    participant Sourcery as Sourcery_Summary
    participant Qwen as Qwen_API
    participant WeChat as WeChat_Webhook

    Dev->>GitHubPR: Create_or_update_PR
    GitHubPR->>Workflow: Trigger_release_notify_wechat

    Workflow->>GitHubPR: Check_PR_state
    alt PR_valid
        Workflow->>GitHubPR: Read_PR_body
        Workflow->>Workflow: Extract_Sourcery_Summary
        alt Sourcery_summary_found
            Workflow->>WeChat: Send_notification_with_Sourcery_summary
        else No_Sourcery_summary
            Workflow->>GitHubPR: Fetch_commits_via_commits_url
            GitHubPR-->>Workflow: Commit_messages
            Workflow->>Qwen: Request_AI_summary_with_commits
            Qwen-->>Workflow: Qwen_summary
            Workflow->>WeChat: Send_notification_with_Qwen_summary
        end
    else PR_invalid
        Workflow->>WeChat: Skip_notification
    end
Loading

File-Level Changes

Change Details Files
Add Sourcery summary extraction from PR body and expose it as workflow outputs.
  • 新增“Extract Sourcery Summary”作业步骤,从 GitHub 事件中读取 PR_BODY
  • 使用内联 Python 脚本,通过正则匹配 PR 正文中的 ## Summary by Sourcery 小节
  • 将提取出的总结以及一个表示是否找到的布尔标志写入 GITHUB_OUTPUT,以供后续步骤使用
  • 把完整的文本总结写入本地 sourcery_summary.txt 文件,便于调试或未来使用
.github/workflows/release-notify-wechat.yml
Make Qwen AI summarization a conditional fallback only when no Sourcery summary is available.
  • 为“Get Commits”步骤添加条件,仅在未找到 Sourcery 总结时执行
  • 将 Qwen 总结步骤重命名为“AI Summary (Qwen Fallback)”,并通过 sourcery.outputs.found == 'false' 进行条件控制
  • 保留现有逻辑:获取最近的提交信息并发送到 Qwen API 进行总结
.github/workflows/release-notify-wechat.yml
Refactor summary output handling to write directly to GITHUB_OUTPUT and avoid redundant files.
  • 更新 Qwen 总结步骤,直接把总结写到 GITHUB_OUTPUT,而不再借助中间文件 ai_summary.txt
  • 移除在 Shell 层重新读取并 echo AI 总结到 GITHUB_OUTPUT 的冗余操作
  • 确保 Sourcery 和 Qwen 两个步骤都使用相同的多行语法输出 summary
.github/workflows/release-notify-wechat.yml
Update WeChat notification payload to conditionally use Sourcery or Qwen summary with appropriate labeling.
  • 在 Notify WeChat 步骤的环境变量中传入 SOURCERY_FOUNDSOURCERY_SUMMARYQWEN_SUMMARY
  • 在通知步骤中加入 Python 逻辑,根据 SOURCERY_FOUND 决定使用 Sourcery 总结还是 Qwen 总结
  • 调整 Markdown 文本,当有 Sourcery 总结时显示“Summary by Sourcery”,否则使用通用的 AI 变更总结标签
.github/workflows/release-notify-wechat.yml
Improve inline Python script formatting and indentation for readability and consistency.
  • 重新缩进 Python 代码块,使 Sourcery 和 Qwen 步骤都统一使用 4 空格缩进
  • 整理字典字面量和 urllib.request.Request 的构造方式,让结构更清晰
  • 移除与 AI 总结处理相关的不必要的 print 和临时文件使用
.github/workflows/release-notify-wechat.yml

Tips and commands

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

This PR updates the WeChat release notification workflow to first extract a Sourcery-generated summary from the PR body and only fall back to Qwen-based AI summarization when no Sourcery summary is found, while simplifying output handling and improving Python formatting.

Sequence diagram for Sourcery-first summary selection in WeChat notify workflow

sequenceDiagram
    participant Dev
    participant GitHubPR as GitHub_PR
    participant Workflow as GH_Actions_Workflow
    participant Sourcery as Sourcery_Summary
    participant Qwen as Qwen_API
    participant WeChat as WeChat_Webhook

    Dev->>GitHubPR: Create_or_update_PR
    GitHubPR->>Workflow: Trigger_release_notify_wechat

    Workflow->>GitHubPR: Check_PR_state
    alt PR_valid
        Workflow->>GitHubPR: Read_PR_body
        Workflow->>Workflow: Extract_Sourcery_Summary
        alt Sourcery_summary_found
            Workflow->>WeChat: Send_notification_with_Sourcery_summary
        else No_Sourcery_summary
            Workflow->>GitHubPR: Fetch_commits_via_commits_url
            GitHubPR-->>Workflow: Commit_messages
            Workflow->>Qwen: Request_AI_summary_with_commits
            Qwen-->>Workflow: Qwen_summary
            Workflow->>WeChat: Send_notification_with_Qwen_summary
        end
    else PR_invalid
        Workflow->>WeChat: Skip_notification
    end
Loading

File-Level Changes

Change Details Files
Add Sourcery summary extraction from PR body and expose it as workflow outputs.
  • Introduce a new Extract Sourcery Summary job step that reads PR_BODY from the GitHub event
  • Use a Python inline script to regex-match the '## Summary by Sourcery' section from the PR body
  • Write the extracted summary and a boolean found flag to GITHUB_OUTPUT for downstream steps to consume
  • Persist the full textual summary into a local sourcery_summary.txt file for debugging or future use
.github/workflows/release-notify-wechat.yml
Make Qwen AI summarization a conditional fallback only when no Sourcery summary is available.
  • Guard the Get Commits step with a condition that Sourcery summary was not found
  • Rename the Qwen summarization step to AI Summary (Qwen Fallback) and gate it on sourcery.outputs.found == 'false'
  • Keep the existing logic to fetch recent commit messages and send them to the Qwen API for summarization
.github/workflows/release-notify-wechat.yml
Refactor summary output handling to write directly to GITHUB_OUTPUT and avoid redundant files.
  • Update the Qwen summary step to write the summary directly to GITHUB_OUTPUT instead of via an intermediate ai_summary.txt file
  • Remove shell-level re-reading and echoing of the AI summary into GITHUB_OUTPUT
  • Ensure both Sourcery and Qwen steps emit a summary output with the same multiline syntax
.github/workflows/release-notify-wechat.yml
Update WeChat notification payload to conditionally use Sourcery or Qwen summary with appropriate labeling.
  • Pass SOURCERY_FOUND, SOURCERY_SUMMARY, and QWEN_SUMMARY into the Notify WeChat step environment
  • Add Python logic in the notification step to choose between Sourcery and Qwen summaries based on SOURCERY_FOUND
  • Adjust the markdown body to show 'Summary by Sourcery' when available, otherwise default to the generic AI change summary label
.github/workflows/release-notify-wechat.yml
Improve inline Python script formatting and indentation for readability and consistency.
  • Re-indent Python blocks to use consistent 4-space indentation in both Sourcery and Qwen steps
  • Tidy up dict literals and urllib.request.Request construction for clearer structure
  • Remove unnecessary print and temporary file usage related to AI summary handling
.github/workflows/release-notify-wechat.yml

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
Contributor

@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 - 我发现了 1 个问题,并给了一些整体性的反馈:

  • Extract Sourcery Summary 这一步中,你仍然会写入 sourcery_summary.txt,但后面从未再读取它,所以可以完全去掉这部分文件 I/O,只写入 GITHUB_OUTPUT,这样也更符合你减少冗余磁盘写入的目标。
  • 用来提取 Sourcery 总结的正则(r"## Summary by Sourcery\s*\n(.*?)(?=\n## |\Z)")目前比较严格;建议放宽一些(例如:大小写不敏感、允许标题中有可选空格或额外词语、以及兼容 \r\n),这样当 Sourcery 小节标题的格式有轻微变化时也能继续正常工作。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the `Extract Sourcery Summary` step you still write `sourcery_summary.txt` but never consume it later, so you can drop that file I/O entirely and only write to `GITHUB_OUTPUT` to match your goal of reducing redundant disk writes.
- The regex used to extract the Sourcery summary (`r"## Summary by Sourcery\s*\n(.*?)(?=\n## |\Z)"`) is quite strict; consider making it a bit more tolerant (e.g., case-insensitive, allowing optional spaces or additional words in the heading, and handling `\r\n`) so it keeps working if the Sourcery section title varies slightly in format.

## Individual Comments

### Comment 1
<location path=".github/workflows/release-notify-wechat.yml" line_range="81-83" />
<code_context>
-      - name: AI Summary (Qwen)
-        if: steps.check.outputs.ok == 'true'
-        id: ai
+      - name: AI Summary (Qwen Fallback)
+        if: steps.check.outputs.ok == 'true' && steps.sourcery.outputs.found == 'false'
+        id: qwen
         env:
           DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Consider guarding against failures in the Qwen API call to avoid the whole job failing on transient issues.

Any exception in this snippet (network error, non-JSON response, changed schema, etc.) will currently fail the step and the whole job. Since this is just a notification fallback, consider catching all exceptions, setting a safe default summary (e.g. `"AI 摘要生成失败"`), and still exiting with code 0 so the release notification continues.

Suggested implementation:

```
        run: |
          import json, os, sys, urllib.request

          try:
              with open("commits.txt", "r") as f:
                  commits = f.read().strip()

              prompt = "请用中文总结以下代码提交,输出3-5条要点,面向测试人员。直接输出编号列表,不要输出标题或前言:\n" + commits
              payload = {"model": "qwen-plus", "input": {"prompt": prompt}}
              data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
          except Exception as e:
              # Fallback: do not fail the job if AI summary generation fails
              fallback_summary = "AI 摘要生成失败"
              print(fallback_summary)
              print(f"[Qwen fallback] Failed to prepare AI summary request: {e}", file=sys.stderr)

```

The rest of the Qwen API interaction (creating the HTTP request, calling `urlopen`, parsing the JSON response, and writing the summary to `${GITHUB_OUTPUT}` or step outputs) should also be moved inside the same `try:` block so that any failure there is caught by the `except` and does not fail the job.

Concretely:
1. Indent all the remaining Qwen-related code below `data = ...` under the `try:` block.
2. Ensure that when the `except` is hit, you also set the step's output summary to the fallback string (e.g. write `summary=AI 摘要生成失败` to the `GITHUB_OUTPUT` file), so downstream steps receive a valid (though degraded) summary.
3. Do not re-raise the exception in the `except` block; simply log it and let the script exit normally so the step succeeds with exit code 0.
</issue_to_address>

Sourcery 对开源项目是免费的 —— 如果你喜欢我们的评审,请考虑帮忙分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据这些反馈改进后续的评审。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • In the Extract Sourcery Summary step you still write sourcery_summary.txt but never consume it later, so you can drop that file I/O entirely and only write to GITHUB_OUTPUT to match your goal of reducing redundant disk writes.
  • The regex used to extract the Sourcery summary (r"## Summary by Sourcery\s*\n(.*?)(?=\n## |\Z)") is quite strict; consider making it a bit more tolerant (e.g., case-insensitive, allowing optional spaces or additional words in the heading, and handling \r\n) so it keeps working if the Sourcery section title varies slightly in format.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the `Extract Sourcery Summary` step you still write `sourcery_summary.txt` but never consume it later, so you can drop that file I/O entirely and only write to `GITHUB_OUTPUT` to match your goal of reducing redundant disk writes.
- The regex used to extract the Sourcery summary (`r"## Summary by Sourcery\s*\n(.*?)(?=\n## |\Z)"`) is quite strict; consider making it a bit more tolerant (e.g., case-insensitive, allowing optional spaces or additional words in the heading, and handling `\r\n`) so it keeps working if the Sourcery section title varies slightly in format.

## Individual Comments

### Comment 1
<location path=".github/workflows/release-notify-wechat.yml" line_range="81-83" />
<code_context>
-      - name: AI Summary (Qwen)
-        if: steps.check.outputs.ok == 'true'
-        id: ai
+      - name: AI Summary (Qwen Fallback)
+        if: steps.check.outputs.ok == 'true' && steps.sourcery.outputs.found == 'false'
+        id: qwen
         env:
           DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Consider guarding against failures in the Qwen API call to avoid the whole job failing on transient issues.

Any exception in this snippet (network error, non-JSON response, changed schema, etc.) will currently fail the step and the whole job. Since this is just a notification fallback, consider catching all exceptions, setting a safe default summary (e.g. `"AI 摘要生成失败"`), and still exiting with code 0 so the release notification continues.

Suggested implementation:

```
        run: |
          import json, os, sys, urllib.request

          try:
              with open("commits.txt", "r") as f:
                  commits = f.read().strip()

              prompt = "请用中文总结以下代码提交,输出3-5条要点,面向测试人员。直接输出编号列表,不要输出标题或前言:\n" + commits
              payload = {"model": "qwen-plus", "input": {"prompt": prompt}}
              data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
          except Exception as e:
              # Fallback: do not fail the job if AI summary generation fails
              fallback_summary = "AI 摘要生成失败"
              print(fallback_summary)
              print(f"[Qwen fallback] Failed to prepare AI summary request: {e}", file=sys.stderr)

```

The rest of the Qwen API interaction (creating the HTTP request, calling `urlopen`, parsing the JSON response, and writing the summary to `${GITHUB_OUTPUT}` or step outputs) should also be moved inside the same `try:` block so that any failure there is caught by the `except` and does not fail the job.

Concretely:
1. Indent all the remaining Qwen-related code below `data = ...` under the `try:` block.
2. Ensure that when the `except` is hit, you also set the step's output summary to the fallback string (e.g. write `summary=AI 摘要生成失败` to the `GITHUB_OUTPUT` file), so downstream steps receive a valid (though degraded) summary.
3. Do not re-raise the exception in the `except` block; simply log it and let the script exit normally so the step succeeds with exit code 0.
</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 on lines +81 to +83
- name: AI Summary (Qwen Fallback)
if: steps.check.outputs.ok == 'true' && steps.sourcery.outputs.found == 'false'
id: qwen
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion (bug_risk): 建议对 Qwen API 调用增加失败保护,以避免因为临时性问题导致整个 Job 失败。

当前这段代码中出现的任何异常(网络错误、非 JSON 响应、返回结构变化等)都会让该 step 失败,进而让整个 Job 失败。由于这里只是通知用的兜底方案,建议捕获所有异常,设置一个安全的默认摘要(例如:"AI 摘要生成失败"),并且仍然以退出码 0 结束,从而让发布通知流程继续执行。

建议实现方式:

        run: |
          import json, os, sys, urllib.request

          try:
              with open("commits.txt", "r") as f:
                  commits = f.read().strip()

              prompt = "请用中文总结以下代码提交,输出3-5条要点,面向测试人员。直接输出编号列表,不要输出标题或前言:\n" + commits
              payload = {"model": "qwen-plus", "input": {"prompt": prompt}}
              data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
          except Exception as e:
              # Fallback: do not fail the job if AI summary generation fails
              fallback_summary = "AI 摘要生成失败"
              print(fallback_summary)
              print(f"[Qwen fallback] Failed to prepare AI summary request: {e}", file=sys.stderr)

剩余的 Qwen API 交互逻辑(创建 HTTP 请求、调用 urlopen、解析 JSON 响应、并把摘要写入 ${GITHUB_OUTPUT} 或 step 输出)也应该一起放到同一个 try: 代码块中,这样那里的任何失败都能被 except 捕获,而不会让 Job 失败。

具体来说:

  1. data = ... 下面所有与 Qwen 相关的代码整体缩进到 try: 块中。
  2. 确保进入 except 分支时,同样会把 step 的输出 summary 设置为兜底字符串(例如写入 summary=AI 摘要生成失败GITHUB_OUTPUT 文件),这样下游的步骤仍然能收到一个有效(虽然降级)的摘要。
  3. 不要在 except 里重新抛出异常;只需记录日志,让脚本正常结束,从而让该 step 以退出码 0 成功完成。
Original comment in English

suggestion (bug_risk): Consider guarding against failures in the Qwen API call to avoid the whole job failing on transient issues.

Any exception in this snippet (network error, non-JSON response, changed schema, etc.) will currently fail the step and the whole job. Since this is just a notification fallback, consider catching all exceptions, setting a safe default summary (e.g. "AI 摘要生成失败"), and still exiting with code 0 so the release notification continues.

Suggested implementation:

        run: |
          import json, os, sys, urllib.request

          try:
              with open("commits.txt", "r") as f:
                  commits = f.read().strip()

              prompt = "请用中文总结以下代码提交,输出3-5条要点,面向测试人员。直接输出编号列表,不要输出标题或前言:\n" + commits
              payload = {"model": "qwen-plus", "input": {"prompt": prompt}}
              data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
          except Exception as e:
              # Fallback: do not fail the job if AI summary generation fails
              fallback_summary = "AI 摘要生成失败"
              print(fallback_summary)
              print(f"[Qwen fallback] Failed to prepare AI summary request: {e}", file=sys.stderr)

The rest of the Qwen API interaction (creating the HTTP request, calling urlopen, parsing the JSON response, and writing the summary to ${GITHUB_OUTPUT} or step outputs) should also be moved inside the same try: block so that any failure there is caught by the except and does not fail the job.

Concretely:

  1. Indent all the remaining Qwen-related code below data = ... under the try: block.
  2. Ensure that when the except is hit, you also set the step's output summary to the fallback string (e.g. write summary=AI 摘要生成失败 to the GITHUB_OUTPUT file), so downstream steps receive a valid (though degraded) summary.
  3. Do not re-raise the exception in the except block; simply log it and let the script exit normally so the step succeeds with exit code 0.

@keeees keeees merged commit d9cb2b5 into release/v0.3.0 Apr 14, 2026
1 check passed
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