ci(wechat-notify): add Sourcery summary extraction with Qwen fallback#892
ci(wechat-notify): add Sourcery summary extraction with Qwen fallback#892keeees merged 1 commit intorelease/v0.3.0from
Conversation
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
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
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your Experience访问你的 dashboard 可以:
Getting HelpOriginal review guide in EnglishReviewer's GuideThis 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 workflowsequenceDiagram
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
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
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>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据这些反馈改进后续的评审。
Original comment in English
Hey - I've found 1 issue, and left some high level feedback:
- In the
Extract Sourcery Summarystep you still writesourcery_summary.txtbut never consume it later, so you can drop that file I/O entirely and only write toGITHUB_OUTPUTto 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>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| - name: AI Summary (Qwen Fallback) | ||
| if: steps.check.outputs.ok == 'true' && steps.sourcery.outputs.found == 'false' | ||
| id: qwen |
There was a problem hiding this comment.
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 失败。
具体来说:
- 将
data = ...下面所有与 Qwen 相关的代码整体缩进到try:块中。 - 确保进入
except分支时,同样会把 step 的输出 summary 设置为兜底字符串(例如写入summary=AI 摘要生成失败到GITHUB_OUTPUT文件),这样下游的步骤仍然能收到一个有效(虽然降级)的摘要。 - 不要在
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:
- Indent all the remaining Qwen-related code below
data = ...under thetry:block. - Ensure that when the
exceptis hit, you also set the step's output summary to the fallback string (e.g. writesummary=AI 摘要生成失败to theGITHUB_OUTPUTfile), so downstream steps receive a valid (though degraded) summary. - Do not re-raise the exception in the
exceptblock; simply log it and let the script exit normally so the step succeeds with exit code 0.