Qwen PR Review Workflow 结构与改进记录
编写日期:2026年 6月 25日
目的
本文档记录了将基于 qwen-code 的 PR Review workflow 引入并定制以适配当前仓库的过程。
本次工作的核心不仅是让 workflow 成功结束,还要使 Qwen 生成的审查结果实际以 GitHub PR 评论的形式留下。
背景
本仓库同时使用 CodeRabbit、Sourcery、Qodo 等外部审查机器人。但我们仍单独引入 qwen-code workflow,通过 OpenRouter 路径运行,并尝试在每个 PR 中留下基于 Qwen 的审查。
最初因为费用问题暂停了 AI PR 审查 API 流程。随后在 OpenRouter 免费层可以使用 openai/gpt-oss-120b:free,因此在 README 中修改为重新尝试该路径的方向。
原始 workflow 结构
目标文件:
.github/workflows/qwen-code-pr-review.yml原始工作流名称:
🧐 Qwen Pull Request Review主要触发器:
on:
pull_request_target:
types: ['opened']
pull_request_review_comment:
types: ['created']
pull_request_review:
types: ['submitted']
workflow_dispatch:
inputs:
pr_number:
required: true
type: 'number'job 条件是设定在以下情况下执行。
workflow_dispatch手动执行pull_request_target的opened事件且 PR 作者为OWNER、MEMBER、COLLABORATOR时- PR review 评论中包含
@qwen /review时 - PR review 正文中包含
@qwen /review时
workflow 的主要步骤如下。
- 检出 PR 代码
- 收集 PR 标题、正文、变更文件、diff 信息
- 执行
QwenLM/qwen-code-action - 在 prompt 中让 Qwen 生成审查并指示使用
gh pr comment添加评论
观察到的问题
在 PR #5 中实际观察到 workflow。
PR:
https://github.com/yyeongjin/idea_world/pull/5PR 已正常创建,以下机器人作出了响应。
- CodeRabbit
- Sourcery
- Qodo
Qwen 工作流也在 pull_request_target 事件中执行了。
观察到的运行:
workflow: 🧐 Qwen Pull Request Review
event: pull_request_target
conclusion: success但是在实际的 PR 中没有留下 Qwen 的审查评论。
查看 workflow 日志可以看到,Qwen 在编写审查内容后并未执行实际的工具调用,而是以文本形式输出了如下 JSON 样式的指令。
{"tool":"write_file", ...}
{"tool":"run_shell_command", ...}即 workflow 本身是 success,但用户期望的结果 “PR 评论撰写” 并未完成。
原因整理
问题在于将评论撰写的任务交给了 Qwen。
原始 prompt 指示 Qwen 直接执行以下操作。
1. write_file("review.md", "<your detailed review feedback here>")
2. gh pr comment $PR_NUMBER --body-file review.md --repo $REPOSITORY但是在实际执行中,Qwen 并没有将此任务作为工具调用来执行,而是仅以文本形式输出了需要做的工作。
因此,如果模型没有正确调用工具,即使 workflow 成功,PR 也不会留下任何评论。
额外确认的结构问题
workflow 的 job 条件中包含了 issue_comment 事件。
(github.event_name == 'issue_comment' && ... contains(github.event.comment.body, '@qwen /review') ...)但是 on: 触发器没有 issue_comment。
即使在 PR 对话中留下 @qwen /review 评论,workflow 也根本不会启动。
此外,pull_request_target 触发器仅在 opened 时响应。
pull_request_target:
types: ['opened']所以在 PR 分支有新提交被 push 的 synchronize 事件中,并未自动重新执行。
改进方向
不再让模型负责 GitHub 评论的编写,而是让 GitHub Actions 步骤负责评论的编写。
改进后职责划分如下。
Qwen
-> 只生成评论 Markdown 文本
GitHub Actions
-> 将 Qwen 输出值保存到文件
-> 使用 gh pr comment 在 PR 上发表评论这样做的话,即使 Qwen 将工具调用输出为文本,也至少可以在 workflow 步骤中接收 qwen_result 并留下评论。
变更内容
1. trigger 加强
原始:
pull_request_target:
types: ['opened']更改:
pull_request_target:
types: ['opened', 'reopened', 'synchronize']
issue_comment:
types: ['created']意图:
- 当 PR 新建时执行
- 当 PR 重新打开时执行
- 当 PR 分支有新提交时执行
- 当在 PR 对话中留下
@qwen /review时执行
额外观察:
仅加强 on: 触发器并不足够。实际上,当向 PR 分支推送新提交时,pull_request_target 运行已生成,但作业条件仍仅允许 github.event.action == 'opened',导致运行以 skipped 结束。
因此,作业条件也需要像下面这样进行修改。
(github.event.action == 'opened' ||
github.event.action == 'reopened' ||
github.event.action == 'synchronize')2. 为 Qwen 步骤分配 id
更改:
- name: 'Run Qwen PR Review'
id: 'qwen_review'意图:
为了在后续步骤中读取下一个输出。
steps.qwen_review.outputs.qwen_result3. prompt 责任更改
原来的 prompt 直接指示 Qwen 编写文件和 PR 评论。
更改后,prompt 指示 Qwen 仅将审阅的 Markdown 文本作为最终回复返回。
Return the review markdown text as your final answer.
Do not call write_file.
Do not call gh pr comment.
Do not output JSON tool-call instructions.
A later GitHub Actions step will post your final answer as a PR comment.意图:
- 减少 Qwen 输出工具调用 JSON 的问题。
- 将评论编写的责任从模型转移到工作流步骤。
4. 添加将 Qwen 输出值发布为 PR 评论的步骤
添加的步骤:
- name: 'Post Qwen PR Review'
if: |-
${{ always() && steps.qwen_review.outputs.summary != '' }}
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
PR_NUMBER: '${{ steps.get_pr.outputs.pr_number || steps.get_pr_comment.outputs.pr_number }}'
REPOSITORY: '${{ github.repository }}'
QWEN_RESULT: '${{ steps.qwen_review.outputs.summary }}'
run: |-
{
echo "## Qwen PR Review"
echo
printf '%s\n' "$QWEN_RESULT"
} > qwen-review.md
gh pr comment "$PR_NUMBER" --body-file qwen-review.md --repo "$REPOSITORY"意图:
- 如果 Qwen 输出不为空,则一定以 PR 评论的形式留下。
- 评论的撰写由使用
GITHUB_TOKEN和gh pr comment的确定性步骤负责。
额外观察:
最初误读了输出名称为 steps.qwen_review.outputs.qwen_result。实际查看 QwenLM/qwen-code-action 的 action.yml 后发现,复合步骤内部会生成 qwen_result,但向 action 外部公开的输出名称是 summary。
outputs:
summary:
value: ${{ steps.qwen_run.outputs.qwen_result }}所以后续的评论步骤需要读取 steps.qwen_review.outputs.summary。如果读取 qwen_result,即使 Qwen 正常生成了评论正文,post 步骤也会被跳过。
注意事项
pull_request_target 工作流不是基于 PR 分支的工作流文件,而是基于 base 分支的工作流文件执行。
因此,仅在 PR 分支上提交工作流修改并不会改变当前 PR 的 pull_request_target 行为。
要实际生效,需要以下任意一种方式:
- 首先将工作流修改合并到
main。 - 然后在该 PR 中留下
@qwen /review,或推送新提交以运行已更改的工作流。
在本次任务中,先将工作流修改合并到 main,再在 PR #5 中重新触发 Qwen review,以确认是否真正生成评论。
安全规范
工作流文档中不要记录 API key、endpoint URL、provider base URL 等敏感信息。
在 GitHub Actions 日志中,以下值也必须进行 secret 掩码处理。
OPENAI_API_KEY
OPENAI_BASE_URL
OPENAI_MODEL
GITHUB_TOKEN文档只保留模型更改事实和 workflow 结构,实际的 secret 值不记录。
当前结论
此次观察确认的内容如下。
- PR 创建本身正常运行。
- CodeRabbit、Sourcery、Qodo 正常响应 PR。
- Qwen workflow 在
pull_request_target中也以 success 结束。 - 但在原有结构下,Qwen 可以不实际写评论,而是将工具调用指令以文本形式输出。
- 因此需要将 “workflow 成功” 与 “PR 评论写入成功” 分开来看。
- 将 Qwen 的输出改为让 GitHub Actions 后续步骤直接发布为评论会更安全。