Repository navigation
Autofix pushes cancel in-progress review-pr, creating a self-reinforcing loop on bot-authored PRs #8888
Copy link
Copy link
Closed
Labels
category/developmentDevelopment experienceDevelopment experiencepriority/P2Medium - Moderately impactful, noticeable problemMedium - Moderately impactful, noticeable problemscope/github-actionsGitHub Actions integrationGitHub Actions integrationstatus/ready-for-humanSpecified but requires human judgment to implement; not suitable for an autonomous agentSpecified but requires human judgment to implement; not suitable for an autonomous agenttype/bugSomething isn't working as expectedSomething isn't working as expected
Description
What happened?
On bot-authored PRs (qwen-code-dev-bot), the autofix workflow and the review-pr workflow form a self-reinforcing cancellation loop:
- Autofix bot pushes a commit to address review feedback
- GitHub fires
pull_request_target: synchronizeon the push qwen-code-pr-review.ymlhascancel-in-progress: trueonsynchronizeevents — the in-progress review-pr run is killed immediately- A new review-pr starts from scratch on the new head
- The autofix bot picks up partial review output from the previous (now-cancelled) run, pushes more fixes → goto 2
This means the review-pr never gets enough uninterrupted time to complete a full review pass. Each autofix push resets hours of review work.
Concrete case: PR #8830
| Time (UTC) | Event | Review-pr status |
|---|---|---|
| 04:27 | PR created (efb6fee, 2 files) | review-pr starts |
| 05:10 | bot push 38569c9 | review-pr killed (ran 43 min) |
| 05:29 | bot merge main (a1faea1) | review-pr killed (ran 19 min) |
| 05:49 | human reviewer finds tsc error | — |
| 06:20 | bot push acb6475 (fix type) | review-pr killed (ran 51 min) |
| 08:43 | review-pr finally posts findings (7 issues) | longest window: 2h23m |
| 09:46 | bot push 01f27b1 | review-pr killed (ran 63 min) |
| 12:02 | review-pr round 2 posts findings | — |
| 12:45 | bot push 3300977 | review-pr killed (ran 43 min) |
| 13:57 | bot merge main (0e16199) | review-pr killed (ran ~72 min) |
| now | — | review-pr still in_progress |
- 7 commits in ~9.5 hours
- review-pr cancelled and restarted at least 6 times
- Longest uninterrupted review window: ~3h26m (06:20→09:46), but the review took 2h23m to produce output
- PR scope: 2 files → 15+ files across 3 packages
concurrencycost ledger for this PR: 83 API calls, ~8.7M input tokens, ~199K output tokens
Root cause
qwen-code-pr-review.yml line 65:
cancel-in-progress: "${{ github.event_name == 'pull_request_target' && (github.event.action == 'synchronize' || github.event.action == 'closed') }}"Every autofix push is a synchronize event to the PR, which unconditionally cancels the in-progress review-pr.
Why this matters
- Reviews are incomplete — the review bot never finishes a full pass, so findings are fragmented across multiple runs
- PR scope explodes — each partial review catches new issues in the previous fix, and the autofix bot keeps expanding the PR to address them
- Humans can't keep up — by the time a human reviewer opens the PR, the bot has already pushed 3-4 rounds of changes
- Massive CI waste — every review-pr cancellation discards compute/token work; PR fix(core): compute stored provider version from built-in template so 'update all' clears the prompt #8830 alone consumed ~8.7M tokens
Suggested fix
Options (not mutually exclusive):
- Don't cancel review-pr on autofix bot pushes — skip
cancel-in-progresswhen the push author isqwen-code-dev-bot(the autofix bot's own pushes, not human pushes or base updates) - Add a cooldown — after an autofix push, wait for review-pr to complete (or timeout) before allowing the next autofix round
- Run review-pr only on
opened/reopened, notsynchronize, for bot-authored PRs — let the scheduled autofix scan pick up new feedback instead of real-time triggers
中文
发生了什么?
在 bot 创建的 PR(qwen-code-dev-bot)上,autofix 工作流和 review-pr 工作流形成了自我强化的取消循环:
- Autofix bot 推送 commit 修复 review 意见
- GitHub 在 push 时触发
pull_request_target: synchronize qwen-code-pr-review.yml在synchronize事件上设置了cancel-in-progress: true—— 正在运行的 review-pr 被立即杀死- 新的 review-pr 在新 head 上从头开始
- Autofix bot 拿到上一轮(已被取消的)review 的部分输出,推送更多修复 → 回到第 2 步
这意味着 review-pr 永远得不到足够的连续时间来跑完一次完整的审查。每次 autofix push 都会重置数小时的审查工作。
具体案例:PR #8830
| 时间 (UTC) | 事件 | review-pr 状态 |
|---|---|---|
| 04:27 | PR 创建(efb6fee,2 个文件) | review-pr 开始 |
| 05:10 | bot push 38569c9 | review-pr 被杀(跑了 43 分钟) |
| 05:29 | bot merge main(a1faea1) | review-pr 被杀(跑了 19 分钟) |
| 05:49 | 人类 reviewer 发现 tsc 错误 | — |
| 06:20 | bot push acb6475(修类型) | review-pr 被杀(跑了 51 分钟) |
| 08:43 | review-pr 终于产出结果(7 个 findings) | 最长窗口:2h23min |
| 09:46 | bot push 01f27b1 | review-pr 被杀(跑了 63 分钟) |
| 12:02 | review-pr 第 2 轮产出 | — |
| 12:45 | bot push 3300977 | review-pr 被杀(跑了 43 分钟) |
| 13:57 | bot merge main(0e16199) | review-pr 被杀(跑了 ~72 分钟) |
| 现在 | — | review-pr 仍在 in_progress |
- 7 个 commit,约 9.5 小时内
- review-pr 被取消并重启了 至少 6 次
- 最长不中断审查窗口:约 3h26min(06:20→09:46),但 review 花了 2h23min 才产出结果
- PR 范围:2 个文件 → 3 个包共 15+ 个文件
- 该 PR 的
concurrency账本:83 次 API 调用,~8.7M 输入 token,~199K 输出 token
根因
qwen-code-pr-review.yml 第 65 行:
cancel-in-progress: "${{ github.event_name == 'pull_request_target' && (github.event.action == 'synchronize' || github.event.action == 'closed') }}"每次 autofix push 对 PR 来说都是 synchronize 事件,无条件取消正在运行的 review-pr。
为什么这很重要
- 审查不完整 —— review bot 永远无法完成一次完整审查,发现的问题分散在多次运行中
- PR 范围膨胀 —— 每次部分审查都能在上一次修复中发现新问题,autofix bot 不断扩展 PR 去处理
- 人类跟不上 —— 人类 reviewer 打开 PR 时,bot 已经推了 3-4 轮改动
- 巨大的 CI 浪费 —— 每次 review-pr 取消都丢弃了计算/token 工作;仅 PR fix(core): compute stored provider version from built-in template so 'update all' clears the prompt #8830 就消耗了约 8.7M token
建议修复
选项(不互斥):
- 不在 autofix bot 的 push 上取消 review-pr —— 当 push 作者是
qwen-code-dev-bot(autofix bot 自己的 push,不是人类的 push 或 base 更新)时跳过cancel-in-progress - 添加冷却期 —— autofix push 之后,等待 review-pr 完成(或超时)再允许下一轮 autofix
- 对 bot 创建的 PR,review-pr 只在
opened/reopened上运行,不在synchronize上运行 —— 让定时 autofix 扫描来获取新反馈,而不是实时触发
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
category/developmentDevelopment experienceDevelopment experiencepriority/P2Medium - Moderately impactful, noticeable problemMedium - Moderately impactful, noticeable problemscope/github-actionsGitHub Actions integrationGitHub Actions integrationstatus/ready-for-humanSpecified but requires human judgment to implement; not suitable for an autonomous agentSpecified but requires human judgment to implement; not suitable for an autonomous agenttype/bugSomething isn't working as expectedSomething isn't working as expected
Activity
doudouOUC commentedon Aug 10, 2026
Confirmed against current
main— the analysis matches what the workflows actually do, and there are two reinforcing mechanisms (one on each side) worth adding.Root cause (verified)
.github/workflows/qwen-code-pr-review.yml, concurrency block (lines 51–59 onmain):Every
synchronizekills the in-flight review regardless of who pushed — the expression never consultsgithub.event.sender.login.Why the 10-minute delay doesn't help here
delay-automatic-reviewdoes debounceopened/synchronizevia theqwen-pr-review-delayenvironment wait timer (currently 10 minutes per the comment in the file), but that only coalesces pushes less than 10 minutes apart. Autofix rounds in the #8830 timeline are ~40–90 minutes apart, so every push sails through the delay gate and cancels a review that needs 1–3 hours to finish a pass.The autofix side never waits for the review either
qwen-autofix.ymlline 155 explicitly excludes review-pr from the checks it waits on before pushing:So the two workflows have no mutual synchronization at all: autofix pushes as soon as it has actionable (even partial) findings, and each push resets the review. With the
*/10cron plus thepull_request_review: submittedtrigger, partial findings are picked up within minutes — that's the "goto 2" in the loop description.Notes on the suggested fixes
cancel-in-progressaccepts an expression, andgithub.event.sender.loginis available onsynchronize(sender = the pusher), so bot pushes can be excluded. Two caveats: (a) with cancellation disabled for bot pushes, eachsynchronizestill enqueues a fresh run in the PR-scoped group and those runs then execute sequentially — to avoid a queue pile-up you'd likely want to skip the trigger itself for bot pushes (an option-3 variant), not just the cancellation; (b) the bot login isvars.AUTOFIX_BOT_LOGIN || 'qwen-code-dev-bot'in qwen-autofix.yml, so the guard should key off the same variable rather than a hardcoded login.gh run list --workflow qwen-code-pr-review.yml --branch <head> --status in_progressand defer the round if a review is running — the*/10cron retries naturally, so a deferral costs at most one tick. This also attacks the "partial findings → scope explosion" symptom directly, because autofix would respond to a complete pass.Net: option 3 for bot-authored PRs (review on
opened/reopenedand explicit/review; let the scheduled scan pick up the rest) combined with option 2 as the autofix-side guard looks like the smallest change that breaks the loop from both directions.fix(autofix): hold autofix rounds while review-pr is in flight (QwenL…
fix(ci): salvage superseded review runs and hold the loop's report-ti…
fix(ci): salvage superseded review runs and hold the loop's report-ti…