Skip to content

fix(ci): acknowledge queued qwen review requests#4847

Merged
yiliang114 merged 9 commits into
QwenLM:mainfrom
qqqys:codex/review-queued-ack
Jun 9, 2026
Merged

fix(ci): acknowledge queued qwen review requests#4847
yiliang114 merged 9 commits into
QwenLM:mainfrom
qqqys:codex/review-queued-ack

Conversation

@qqqys

@qqqys qqqys commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Adds an immediate acknowledgement for explicit Qwen Code PR review requests. When a collaborator comments @qwen-code /review in a PR conversation, review comment, or review body, the workflow now posts a short PR comment with a link to the Actions run before the self-hosted review job is picked up.

Why it's needed

The actual review still depends on the self-hosted ecs-qwen runner. When that runner is busy, the review job can remain queued with no visible PR conversation feedback, which makes it look like Qwen Code did not trigger. This gives users a quick accepted/queued signal without changing the review execution environment.

Reviewer Test Plan

How to verify

Comment @qwen-code /review on an open PR as an owner, member, or collaborator. Confirm that the workflow posts a queued acknowledgement with a run link, then confirm that the existing review job still runs through the self-hosted review path.

Evidence (Before & After)

Before: an accepted review request could sit queued on the self-hosted runner with no PR conversation feedback. After: the workflow posts _Qwen Code review request accepted. Review is queued in [workflow run](...)._ before the self-hosted runner picks up the review.

Tested on

OS Status
🍏 macOS ✅ tested
🪟 Windows N/A
🐧 Linux N/A

Environment (optional)

Validated workflow formatting locally with npx prettier --check .github/workflows/qwen-code-pr-review.yml. actionlint was not available in this environment, and the GitHub event itself must be verified by the PR workflow.

Risk & Scope

  • Main risk or tradeoff: Explicit review requests now add one short PR comment before the actual review result.
  • Not validated / out of scope: End-to-end GitHub event execution before merge; this requires the workflow to run in GitHub Actions.
  • Breaking changes / migration notes: None.

Linked Issues

Fixes #4846

中文说明

这个 PR 做了什么

为显式的 Qwen Code PR review 请求增加即时确认反馈。当 owner、member 或 collaborator 在 PR 对话、review comment 或 review body 中评论 @qwen-code /review 时,workflow 会先发布一条带 Actions run 链接的简短 PR 评论,然后再等待 self-hosted review job 被调度。

为什么需要

真正的 review 仍然依赖 self-hosted ecs-qwen runner。当 runner 繁忙时,review job 可能长时间排队,而且 PR 对话区没有任何反馈,看起来就像 Qwen Code 没有触发。这个改动在不改变 review 执行环境的前提下,让用户能立即看到请求已被接受并进入队列。

Reviewer Test Plan

如何验证

以 owner、member 或 collaborator 身份在一个打开的 PR 上评论 @qwen-code /review。确认 workflow 发布了带 run 链接的 queued acknowledgement,然后确认现有 review job 仍然走 self-hosted review 路径。

证据(Before & After)

Before:review 请求已被接受时,可能因为 self-hosted runner 排队而在 PR 对话区没有任何反馈。After:workflow 会先发布 _Qwen Code review request accepted. Review is queued in [workflow run](...)._,再等待 self-hosted runner 执行 review。

Tested on

OS Status
🍏 macOS ✅ tested
🪟 Windows N/A
🐧 Linux N/A

环境(可选)

本地通过 npx prettier --check .github/workflows/qwen-code-pr-review.yml 验证 workflow 格式。当前环境没有 actionlint,GitHub event 级别的端到端验证需要在 GitHub Actions 中完成。

风险与范围

  • 主要风险或取舍:显式 review 请求现在会在真正 review 结果前多发一条简短 PR 评论。
  • 未验证 / 范围外:合并前无法在本地端到端验证 GitHub event 执行,需要依赖 GitHub Actions 实跑。
  • Breaking changes / migration notes:无。

关联 Issue

Fixes #4846

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

On direction: this solves a genuine UX gap — when the self-hosted ecs-qwen runner is busy, there's zero feedback in the PR conversation, which looks broken. A fast acknowledgement on ubuntu-latest before the heavy review job starts is the right architecture. The linked issue #4846 confirms this is a real pain point.

On approach: the scope is tight — one job, one step, 42 lines added. The if conditions correctly mirror the review-pr job's explicit-trigger branches (issue_comment, pull_request_review_comment, pull_request_review) while intentionally omitting pull_request_target and workflow_dispatch (those don't need an ack). Permissions (pull-requests: read + issues: write) are appropriate for posting a PR comment via gh pr comment.

One minor observation: the ack-review-request job has no concurrency group, so rapid repeated /review comments would each post a separate ack. Low-risk since the review job's own concurrency group with cancel-in-progress handles dedup on the heavy side. Not a blocker.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

方向:解决了一个真实的 UX 问题——当 self-hosted ecs-qwen runner 繁忙时,PR 对话区没有任何反馈,看起来像没有触发。在 ubuntu-latest 上快速发一条确认消息,让重型 review job 启动前就有反馈,是正确的架构。关联的 issue #4846 确认了这是一个实际痛点。

方案:范围紧凑——一个 job、一个 step、42 行新增。if 条件正确镜像了 review-pr job 的显式触发分支(issue_commentpull_request_review_commentpull_request_review),同时有意省略了 pull_request_targetworkflow_dispatch(这些不需要确认)。权限(pull-requests: read + issues: write)适合通过 gh pr comment 发 PR 评论。

一个小观察:ack-review-request job 没有 concurrency 组,快速重复的 /review 评论会各自发一条确认。风险低,因为 review job 自己的 cancel-in-progress 并发组在重型侧做了去重。不阻塞。

进入代码审查 🔍

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Code Review

The diff is 42 lines added to a single workflow file, and it's clean:

  • Trigger conditions correctly mirror the three explicit-trigger branches from review-pr (issue_comment, pull_request_review_comment, pull_request_review). The pull_request_target and workflow_dispatch events are intentionally excluded — those don't need an ack since they either auto-fire or are manually triggered with visible UI.
  • Permissions are properly scoped: pull-requests: read for reading PR data, issues: write for posting the comment via gh pr comment. No unnecessary permissions.
  • runs-on: ubuntu-latest is the right choice — this job needs to start fast to give immediate feedback, which is the whole point. The self-hosted runner is reserved for the actual review.
  • Environment variables are properly quoted with ${{ }} expressions. The PR_NUMBER and RUN_URL are derived from GitHub context (not user input), so no injection risk.
  • YAML formatting passes Prettier. YAML syntax is valid.

No correctness bugs, security issues, or AGENTS.md violations found.

Testing

This is a GitHub Actions workflow file change — there's no user-facing CLI behavior to drive via tmux. The change can only be verified end-to-end when GitHub Actions executes it on a real /review trigger.

Verification performed:

$ npx prettier --check .github/workflows/qwen-code-pr-review.yml
Checking formatting...
All matched files use Prettier code style!

$ python3 -c "import yaml; yaml.safe_load(open('.github/workflows/qwen-code-pr-review.yml')); print('YAML syntax valid')"
YAML syntax valid

$ gh pr checks 4847
CodeQL                     pass    4m31s
Lint                       pass    4m4s
Classify PR                pass    4s
Test (ubuntu-latest)       pending
Test (macos-latest)        pending
Test (windows-latest)      pending
review-pr                  pending

Lint and CodeQL pass. Tests are pending (not affected by this workflow-only change). actionlint was not available in this environment — the workflow should be verified by a maintainer with actionlint access or by observing the first live execution.

中文说明

代码审查

diff 是单个 workflow 文件新增 42 行,代码干净:

  • 触发条件正确镜像了 review-pr 的三个显式触发分支(issue_commentpull_request_review_commentpull_request_review)。有意排除了 pull_request_targetworkflow_dispatch——这些不需要确认,因为前者自动触发,后者有手动 UI。
  • 权限作用域合理:pull-requests: read 读取 PR 数据,issues: write 通过 gh pr comment 发评论。没有多余权限。
  • runs-on: ubuntu-latest 是正确选择——这个 job 需要快速启动以提供即时反馈,这正是它的意义所在。self-hosted runner 留给实际 review。
  • 环境变量${{ }} 表达式正确引用。PR_NUMBERRUN_URL 来自 GitHub context(非用户输入),无注入风险。
  • YAML 格式通过 Prettier 检查,YAML 语法有效。

未发现正确性 bug、安全问题或 AGENTS.md 违规。

测试

这是 GitHub Actions workflow 文件变更——没有用户可见的 CLI 行为可以通过 tmux 驱动测试。变更只能在 GitHub Actions 对真实 /review 触发执行时端到端验证。

已执行的验证:Prettier 格式检查通过,YAML 语法有效,Lint 和 CodeQL CI 检查通过。当前环境无 actionlint——建议有 actionlint 的维护者额外验证,或观察首次实际执行。

Qwen Code · qwen3.7-max

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Straightforward, well-scoped change. The ack job is the simplest possible solution — one step on a fast runner, posting one comment. The trigger conditions are correctly mirrored from the review job, permissions are tight, and there's no user-input injection surface.

The only thing we can't verify locally is the live GitHub Actions execution (will the ack actually appear before the review job picks up?). But the risk is minimal — worst case, an extra PR comment appears slightly after the review starts, which is no worse than the current state.

Approved. ✅

中文说明

简洁、范围合理的变更。ack job 是最简方案——快速 runner 上一个 step 发一条评论。触发条件从 review job 正确镜像,权限收紧,无用户输入注入面。

唯一无法在本地验证的是 GitHub Actions 实际执行(ack 是否真的在 review job 启动前出现?)。但风险极低——最坏情况是确认评论在 review 开始后才出现,这不会比当前状态更差。

通过 ✅

Qwen Code · qwen3.7-max

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, looks ready to ship. ✅

Comment on lines +71 to +73
gh pr comment "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] This job posts "…Review is queued…" whenever a privileged user comments @qwen-code /review on an open PR, but it has no fork check — while the review-pr job silently exit 0s for fork PRs (isCrossRepository, lines 229-234) with no comment, and that clean exit also bypasses the failure() fallback (line 293). So a maintainer requesting a review on an external contributor's fork PR (the common case) gets a "queued" promise that is never fulfilled and never explained. The gate keys on the commenter's author_association, not the PR author's, so fork PRs do reach it. Guard the ack with the same fork check (this also exercises the otherwise-unused pull-requests: read permission); alternatively fold the ack into review-pr after its fork/state checks, or reword the message so it doesn't promise a review.

Suggested change
gh pr comment "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"
set -euo pipefail
IS_FORK="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json isCrossRepository --jq '.isCrossRepository')"
if [ "$IS_FORK" = "true" ]; then
echo "Skipping ack: PR #${PR_NUMBER} is a fork PR; review-pr skips forks." >&2
exit 0
fi
gh pr comment "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"

— claude-opus-4-8 via Claude Code /qreview

(github.event.review.author_association == 'OWNER' ||
github.event.review.author_association == 'MEMBER' ||
github.event.review.author_association == 'COLLABORATOR'))
runs-on: 'ubuntu-latest'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This job has no concurrency group, while review-pr uses concurrency: { group: qwen-pr-review-<pr>, cancel-in-progress: true } (lines 109-111). Rapid duplicate @qwen-code /review triggers therefore post one "queued" ack per event while only a single review actually runs — comment spam that undercuts the "one clear signal" goal of this feature. Mirror the review job's pattern, but with a distinct group name so the fast ack doesn't cancel (or get cancelled by) the long-running review:

Suggested change
runs-on: 'ubuntu-latest'
concurrency:
group: 'qwen-pr-ack-${{ github.event.issue.number || github.event.pull_request.number }}'
cancel-in-progress: true
runs-on: 'ubuntu-latest'

— claude-opus-4-8 via Claude Code /qreview

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No review findings. Downgraded from Approve to Comment: CI failing (triage). — qwen3.7-max via Qwen Code /review

wenshao
wenshao previously approved these changes Jun 8, 2026

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No issues found. LGTM! ✅ — qwen3.7-max via Qwen Code /review

# Conflicts:
#	.github/workflows/qwen-code-pr-review.yml
@wenshao

wenshao commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

✅ Local verification — queued-review acknowledgement workflow

Verified .github/workflows/qwen-code-pr-review.yml as a merge reference. The PR is rebased on current main (origin/main is an ancestor), so the branch head already is the post-merge state and main hasn't touched this file. Since this is a GitHub Actions change, "real testing" here = lint the workflow + exercise the gating expression and the shell step directly. act/actionlint weren't available in this environment (no Docker), so I used shellcheck, prettier, a faithful evaluator of the exact if, and real execution of the extracted shell step.

1. Lint & format — clean

  • prettier --check → ✅ All matched files use Prettier code style!
  • shellcheck on the extracted ack run: script → ✅ clean
  • YAML parses; on: already includes issue_comment, pull_request_review_comment, and pull_request_review (the events the new job keys on).

2. Structure & consistency

  • The new ack-review-request job is purely additive (+52/−0; every existing job is byte-unchanged).
  • Runs on ubuntu-latest, not the self-hosted ecs-qwen runner — so the acknowledgement is independent of the busy review runner, which is exactly the problem this PR targets.
  • Permissions are correct & minimal: pull-requests: read (for gh pr view) + issues: write (a PR conversation comment is an issue comment, which is what gh pr comment posts). It posts via GITHUB_TOKEN, which by design does not recursively re-trigger the workflow.
  • PR-scoped concurrency with cancel-in-progress (repeated /review comments collapse to the latest ack).
  • Gating consistency (the key check): the ack job's three event branches (issue_comment / pull_request_review_comment / pull_request_review) are verbatim-identical to the matching comment/review-trigger branches of the existing review-pr job. So the ack fires under exactly the conditions that start a real comment/review-triggered review, and it correctly omits the pull_request_target (automatic-review) branch.

3. Gating truth-table — 18 / 18 (faithful evaluation of the exact if)

Input Result
@qwen-code /review (exact) — OWNER/MEMBER/COLLABORATOR, open PR — all 3 event types ✅ ack
@qwen-code /review <args> (space-prefixed) ✅ ack
@qwen-code /reviewers, @qwen-code /review-now, mid-comment mention ⛔ skip (no false match)
author NONE / CONTRIBUTOR / FIRST_TIME_CONTRIBUTOR ⛔ skip
PR closed, or plain issue (not a PR) ⛔ skip
pull_request_target (opened) / workflow_dispatch ⛔ skip

4. Shell step — real execution (mocked gh)

Ran the extracted run: script end-to-end:

  • non-fork PR → posts exactly _Qwen Code review request accepted. Review is queued in [workflow run](<run-url>)._
  • fork PR (isCrossRepository=true) → skips, posts nothing, exits 0 with Skipping ack… on stderr ✅

Observations (minor, non-blocking; both pre-existing / shared with review-pr)

  • Fork-skip premise. The ack skips forks because "review-pr skips forks", but that skip is enforced by the qwen /review tooling at runtime, not by this workflow's if/steps (review-pr has no isCrossRepository gate). Skipping the ack on forks is the safe direction either way — it can't make a false "queued" promise, and it's no worse than today's no-ack behavior.
  • format(..., '\n') newline sub-condition. startsWith(body, format('@qwen-code /review{0}', '\n')) is copied verbatim from review-pr. GitHub expression string literals don't process \n as a newline, so this sub-condition likely matches a literal \n rather than a real newline (effectively inert). Impact is nil — the exact-match and space-prefix conditions cover the real cases — and the ack stays identical to review-pr regardless. Worth a separate look if multi-line trigger comments matter, but out of scope for this PR.

Verdict

Verified. The new job is additive, correctly gated (identical to the real review trigger), correctly scoped to ubuntu-latest with minimal permissions, lint/format-clean, and the shell step behaves correctly for both fork and non-fork PRs. No blockers found.

Scope: static lint + faithful gating-expression evaluation + real shell-step execution. The live GitHub event delivery itself can only be exercised by the workflow on an actual comment.

echo "should_review=false" >> "$GITHUB_OUTPUT"
IS_FORK="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json isCrossRepository --jq '.isCrossRepository')"
if [ "$IS_FORK" = "true" ]; then
echo "Skipping ack: PR #${PR_NUMBER} is a fork PR; review-pr skips forks." >&2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The fork-PR skip here is inconsistent with review-pr's actual behavior. The review-pr job's if condition for issue_comment, pull_request_review_comment, and pull_request_review events contains no fork check — so a collaborator commenting @qwen-code /review on a fork PR will trigger review-pr (which runs the full review and posts inline comments), but the ack job silently exits. The user sees review results with no prior "queued" acknowledgement, and the log message "review-pr skips forks" makes a false claim about the other job.

Two options to resolve:

  1. Remove the fork check from ack-review-request so the ack is posted consistently with review-pr's actual behavior (simpler).
  2. Add a matching fork check to review-pr for comment-triggered code paths if the intent is to not review fork PRs at all (this would be a broader behavioral change).

The two jobs must agree on the fork policy.

— qwen3.7-max via Qwen Code /review

github.event.review.author_association == 'COLLABORATOR'))
concurrency:
group: 'qwen-pr-ack-${{ github.event.issue.number || github.event.pull_request.number }}'
cancel-in-progress: true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] cancel-in-progress: true on a PR-scoped group contradicts the workflow-level concurrency policy. The workflow-level comment states "Comment/review events use per-run groups to avoid cancelling active reviews" and sets cancel-in-progress to false for non-pull_request_target events. This ack job instead uses a PR-scoped group with unconditional cancellation.

In practice, if two /review comments are posted in quick succession, the second run cancels the first — but if the first gh pr comment already completed, cancellation has no effect and both ack comments are posted anyway. Consider cancel-in-progress: false to align with the workflow-level design, or remove the concurrency block entirely since each ack run is cheap and idempotent.

Suggested change
cancel-in-progress: true
cancel-in-progress: false

— qwen3.7-max via Qwen Code /review


delay-automatic-review:
ack-review-request:
if: |-

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The if condition's three comment/review event branches are duplicated character-for-character between ack-review-request and review-pr (~27 lines each). Any future change to trigger syntax (e.g., adding an alias, changing the author_association allow-list) must be made in both places — if one is updated and the other is not, the two jobs accept different inputs, causing confusing mismatches (user gets an ack but no review, or vice versa).

GitHub Actions doesn't support YAML anchors or shared expressions across jobs, so the duplication is structurally required. Adding a sync comment on both blocks would alert future editors:

    # KEEP IN SYNC with review-pr.if (explicit-trigger branches)
    if: |-

— qwen3.7-max via Qwen Code /review

pull-requests: 'read'
issues: 'write'
steps:
- name: 'Post queued acknowledgement'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] pull-requests: 'read' should be 'write'gh pr comment (line 93) requires pull-requests: write to post comments on pull requests. The review-pr job in the same file uses pull-requests: 'write' (line 255) for the same operation. With 'read', the ack step will fail with a 403 error at runtime.

Suggested change
- name: 'Post queued acknowledgement'
pull-requests: 'write'
issues: 'write'

— qwen3.7-max via Qwen Code /review

wenshao
wenshao previously approved these changes Jun 8, 2026
runs-on: 'ubuntu-latest'
permissions:
pull-requests: 'write'
issues: 'write'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] issues: 'write' is declared but the job only runs gh pr comment, which requires pull-requests: write — the Issues API is never called. Removing this excess permission follows least-privilege and reduces the blast radius if GITHUB_TOKEN is ever exposed through a future change.

Suggested change
issues: 'write'
pull-requests: 'write'

— qwen3.7-max via Qwen Code /review

cancel-in-progress: "${{ github.event_name == 'pull_request_target' && github.event.action == 'synchronize' }}"

jobs:
ack-review-request:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] ack-review-request and review-pr run as independent jobs with no ordering guarantee. When the self-hosted runner is busy, ack (on ubuntu-latest) posts the "queued" message quickly — which is the expected case. But if review-pr finishes before the ack job starts (e.g., runner was already warm), users would see the review result before the "queued" acknowledgement, which is confusing.

Consider folding the ack into review-pr as an early step (after its fork/state guards), so the ack is only posted when the review will actually run. This also eliminates the duplicated if condition flagged in the prior review.

— qwen3.7-max via Qwen Code /review

PR_NUMBER: '${{ github.event.issue.number || github.event.pull_request.number }}'
RUN_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
run: |-
set -euo pipefail

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] If gh pr comment fails (rate limit, transient 5xx, token scope issue), the user sees nothing on the PR — the /review request appears silently ignored. The review-pr job has a dedicated "Post fallback comment on failure" step using the failure() condition. Consider adding a similar fallback step here, or at minimum logging to $GITHUB_STEP_SUMMARY so the failure is discoverable without navigating into workflow run logs.

— qwen3.7-max via Qwen Code /review

const result = formatDateForContext();
expect(typeof result).toBe('string');
expect(result.length).toBeGreaterThan(0);
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The test file fix (adding missing }); closers for the formatDateForContext describe block) appears already merged to main via PR #4863 ("fix(core): add missing closing braces in formatDateForContent test block"). This branch likely needs rebasing onto current main — after rebase, this file change will become a no-op and drop out of the diff.

— qwen3.7-max via Qwen Code /review

permissions:
pull-requests: 'write'
issues: 'write'
steps:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This job has no timeout-minutes. The review-pr job sets timeout-minutes: 60, but this ack job — which makes a single gh pr comment API call — relies on the GitHub Actions default of 360 minutes. If the API hangs (rate limit, partial outage), the workflow run stays "in progress" indefinitely.

Suggested change
steps:
timeout-minutes: 5
steps:

— qwen3.7-max via Qwen Code /review

(github.event.review.body == '@qwen-code /review' ||
startsWith(github.event.review.body, '@qwen-code /review ') ||
startsWith(github.event.review.body, format('@qwen-code /review{0}', '\n'))) &&
(github.event.review.author_association == 'OWNER' ||

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The pull_request_review trigger fires for all review submission types (approved, changes_requested, commented). A collaborator who approves a PR with body @qwen-code /review would simultaneously record a human approval AND trigger a full Qwen review — creating a contradictory review state where an approval coexists with a bot review that may flag issues.

Add a state filter:

Suggested change
(github.event.review.author_association == 'OWNER' ||
(github.event.review.body == '@qwen-code /review' ||
startsWith(github.event.review.body, '@qwen-code /review ') ||
startsWith(github.event.review.body, format('@qwen-code /review{0}', '\n'))) &&
github.event.review.state == 'commented' &&

— qwen3.7-max via Qwen Code /review

set -euo pipefail
gh pr comment "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The ack comment body has no machine-readable marker (e.g., an HTML comment). Any future code that needs to detect, suppress, or replace a previously-posted ack comment (e.g., deduplication, updating when the review completes) must match on visible prose text, which breaks on rewording or localization.

Embed a hidden marker:

Suggested change
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"
--body "<!-- qwen-review-ack -->_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"

— qwen3.7-max via Qwen Code /review

env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
PR_NUMBER: '${{ github.event.issue.number || github.event.pull_request.number }}'
RUN_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This step writes nothing to $GITHUB_STEP_SUMMARY. All other jobs in this workflow (delay-automatic-review, authorize-review-request, review-pr) write diagnostic output to the step summary. When debugging "bot said queued but nothing happened," the ack step shows only a green checkmark with no summary text.

Add summary output:

Suggested change
RUN_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
run: |-
set -euo pipefail
gh pr comment "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"
echo "Ack posted on PR #${PR_NUMBER}." >> "$GITHUB_STEP_SUMMARY"

— qwen3.7-max via Qwen Code /review

steps:
- name: 'Post queued acknowledgement'
env:
GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This job uses secrets.GITHUB_TOKEN for a write operation (gh pr comment), but the review-pr job uses secrets.CI_BOT_PAT for its write operations. This creates inconsistent comment attribution: the ack appears as github-actions[bot], while the actual review and failure fallback comments appear as the CI bot user. Consider using CI_BOT_PAT for consistency, or add a comment explaining the deliberate choice.

— qwen3.7-max via Qwen Code /review

--repo "$GITHUB_REPOSITORY" \
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"

review-config:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The ack job posts the acknowledgement based solely on the trigger-time event payload, without re-checking whether the PR is still open. The review-pr job defensively re-verifies PR state via gh pr view before running. If the PR is closed or merged between the trigger event and ack execution (rare but possible with queued concurrency), the ack promises a review that the review-pr job will skip.

Consider adding a lightweight state check:

Suggested change
review-config:
run: |-
set -euo pipefail
PR_STATE="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json state --jq '.state')"
if [ "$PR_STATE" != "OPEN" ]; then
echo "PR is $PR_STATE, skipping ack." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
gh pr comment "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"

— qwen3.7-max via Qwen Code /review

fi
gh pr comment "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--body "<!-- qwen-review-ack -->_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] The <!-- qwen-review-ack --> HTML marker is embedded in the comment body, but no workflow step ever reads or checks for it. Combined with cancel-in-progress: false on the ack concurrency group, rapid /review triggers produce multiple identical ack comments on the PR — the marker implies dedup intent that was never implemented.

Consider either adding a pre-post check (query existing comments for the marker via gh api and skip/edit if found) or removing the marker to avoid the misleading signal.

— qwen3.7-max via Qwen Code /review

(github.event.review.body == '@qwen-code /review' ||
startsWith(github.event.review.body, '@qwen-code /review ') ||
startsWith(github.event.review.body, format('@qwen-code /review{0}', '\n'))) &&
github.event.review.state == 'commented' &&

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] This github.event.review.state == 'commented' guard is added to both the new ack-review-request job and the existing review-pr job. On main, the review-pr job accepts pull_request_review events of any state — a maintainer who approves or requests changes with @qwen-code /review in the body triggers the bot. After this change, only commented-state reviews trigger review-pr, so the same maintainer gets no response at all (no ack, no bot review, no diagnostic).

If narrowing review-pr is intentional, consider documenting the behavioral change in the PR description. If only the ack job needs the guard, remove it from review-pr.

— qwen3.7-max via Qwen Code /review

@wenshao

wenshao commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

✅ Local re-verification (updated) — queued-review acknowledgement

Re-verified against current head 57bb9ea. This supersedes my earlier note above — the PR has changed since: it is now +74/−0 across two files and is no longer purely additive (it also tightens the existing review-pr trigger and ships a test-file fix).

No Docker here, so act/actionlint can't run. "Real test" = trial 3-way merge against current main + lint + faithful evaluation of the exact if + actual execution of the extracted shell step in tmux with a mocked gh.

What the PR changes (head 57bb9ea)

  • .github/workflows/qwen-code-pr-review.yml (+71/−0): new ack-review-request job; plus one added AND‑clause github.event.review.state == 'commented' inside the existing review-pr.if; plus two KEEP IN SYNC comments.
  • packages/core/src/utils/environmentContext.test.ts (+3/−0): adds the missing }); }); closing braces.

1. Merge‑correctness — clean ✅ (the test fix also independently landed on main)

The test‑file fix duplicates #4863 (36dd4be0b — the single commit main has that this branch lacks). Both add the identical closing braces over a genuinely‑broken merge‑base, so the risk was a double‑close → syntax error. Checked with a non‑destructive 3‑way merge (git merge-tree):

  • No conflict (merged tree 0766ebd).
  • The merged environmentContext.test.ts is byte‑identical to main's #4863 version (already CI‑green) — single set of braces, no doubling.
  • esbuild parses it (no syntax error), braces balance (148/148, 453/453, 97/97), prettier‑clean.

2. Lint & format — clean ✅

  • prettier --check on the merged workflow and test file → All matched files use Prettier code style!
  • shellcheck -s bash on the extracted ack run: block → clean.

3. Gating — ack fires iff a real explicit‑trigger review fires ✅

Both if expressions were whitespace‑normalized and compared:

  • All three ack branches (issue_comment / pull_request_review_comment / pull_request_review) are verbatim substrings of review-pr.if.
  • review-pr.if ends with exactly ‹ack‑expression› + ')' → the explicit‑trigger branches are byte‑identical between the two jobs (matching the KEEP IN SYNC comments).
  • Faithful truth‑table over 20 payloads → 20/20 (exact / space‑arg → ack; /reviewers, /review-now, mid‑comment mention, NONE/CONTRIBUTOR/FIRST_TIME_CONTRIBUTOR, closed PR, plain issue, pull_request_target, workflow_dispatchskip).

4. Shell step — real execution in tmux (mocked gh), every path ✅

Ran the extracted run: end‑to‑end with a mock gh driven by canned PR state / existing‑comment id:

Scenario gh call sequence Result
No prior ack pr viewapi …/commentspr comment posts the exact body <!-- qwen-review-ack -->_…queued in [workflow run](‹url›)._
Existing ack (id 123456) pr viewapi …/commentsapi --method PATCH …/comments/123456 updates in place with fresh run URL; no second comment ✅ idempotent (no spam)
PR CLOSED pr view only short‑circuits, writes nothing, exit 0
PR MERGED pr view only skips, writes nothing

5. Structure & security ✅

  • runs-on: ubuntu-latest — decoupled from the busy self‑hosted ecs-qwen runner (the whole point: the ack posts immediately even while the review is queued).
  • concurrency: qwen-pr-ack-‹PR#›, cancel-in-progress: false — serializes ack runs per‑PR so the read‑then‑update is race‑free; repeated /review updates the same comment instead of stacking.
  • Author‑association gate (OWNER/MEMBER/COLLABORATOR) limits triggering to trusted users; the ack is posted by GITHUB_TOKEN and its body doesn't match @qwen-code /review, so there's no self‑retrigger loop.
  • on: includes all three events the if keys on (no dead job); timeout-minutes: 5.
  • Dropping the old fork‑skip is actually a fix: the ack now fires exactly when the explicit review fires (byte‑identical if), so a collaborator‑triggered review on a fork PR now correctly gets an ack too.

Observations (non‑blocking; for reviewer awareness)

  1. Behavioral change to review-pr not mentioned in the description. Adding review.state == 'commented' means a review submitted as Approve or Request changes whose body contains @qwen-code /review will no longer trigger a review (it did before). The common issue_comment path is unaffected. It keeps ack/review consistent and is defensible — but please confirm it's intended.
    • pull_request_review old → new: approved: trigger→skip · changes_requested: trigger→skip · commented: trigger (unchanged).
  2. permissions: pull-requests: write is broader than needed. The step only does gh pr view --json state (read); every comment write goes through the issues endpoint (issues: write). pull-requests: read would suffice (least‑privilege).
  3. Inert '\n' sub‑condition (pre‑existing, copied verbatim from review-pr): format('@qwen-code /review{0}', '\n') is a literal backslash‑n in GitHub expressions (single‑quoted literals don't escape), not a newline — so a command on its own line followed by a real newline won't match via that clause. Not introduced here; now shared by both jobs.

Verdict

Verified — merge‑ready, no blockers. Clean 3‑way merge with main (the test fix de‑duplicates with #4863, no conflict, merged file == main's CI‑green version), lint/format‑clean, gating provably in sync (20/20), and the shell step — including the new idempotent update path — behaves correctly under real execution. One thing to confirm before merge: the undocumented review-pr tightening (obs. 1); minor least‑privilege nit (obs. 2).

Scope: trial 3‑way merge + static lint + faithful gating evaluation + real tmux shell‑step execution with mocked gh. Live GitHub event delivery itself can only be exercised by the workflow on an actual comment. Head 57bb9ea.


中文小结

已针对最新 head 57bb9ea 重新验证(PR 自上次核验后已变化,现为 +74/−0、不再是纯新增)。

  • main 试合并干净:测试文件的补括号修复与 #4863 重复,三方合并零冲突,合并后该文件与 main 版本逐字节一致(已过 CI),无重复括号;esbuild 可解析、括号平衡、prettier 通过。
  • Lint:prettier、shellcheck -s bash 均通过。
  • 门控:ack 的 if 与(同步加上 review.state=='commented' 的)review-pr.if 三个显式分支逐字节一致,真值表 20/20
  • Shell 步骤在 tmux 中实跑(mock gh):新建评论 / 幂等更新(PATCH,不重复刷评论)/ PR 关闭或合并时跳过——全部正确。
  • 结论:可合并、无阻断项。 需确认 1 点:本 PR 顺带收紧了 review-pr 触发——以 Approve / Request changes 形式提交且正文含 @qwen-code /review 的 review 将不再触发(描述未提及,issue_comment 路径不受影响);另 pull-requests: write 可降为 read

wenshao
wenshao previously approved these changes Jun 8, 2026
EXISTING_ACK_ID="$(
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \
--paginate \
--jq 'map(select(.body | contains("<!-- qwen-review-ack -->")))[-1].id // ""'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] --paginate --jq evaluates the jq filter per page independently. The expression map(select(...))[-1].id // "" returns "" (an empty line) for pages with no matching comment. On PRs with >30 comments (default GitHub API page size), EXISTING_ACK_ID captures a multi-line string like "\n12345". The subsequent [ -n "$EXISTING_ACK_ID" ] test is true, and the PATCH URL issues/comments/${EXISTING_ACK_ID} becomes malformed (contains a newline), causing a 404.

Suggested change
--jq 'map(select(.body | contains("<!-- qwen-review-ack -->")))[-1].id // ""'
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \
--paginate -F per_page=100 \
| jq -sr '[.[][] | select(.body | contains("<!-- qwen-review-ack -->"))] | last | .id // empty'

— qwen3.7-max via Qwen Code /review

EXISTING_ACK_ID="$(
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \
--paginate \
--jq 'map(select(.body | contains("<!-- qwen-review-ack -->")))[-1].id // ""'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Critical] No author check on ack comment lookup — bot may edit arbitrary user comments

The jq filter select(.body | contains("<!-- qwen-review-ack -->")) matches any comment containing the marker, regardless of author. Any authenticated GitHub user can plant <!-- qwen-review-ack --> in a comment on a public repo PR. When a maintainer later triggers /review, the bot PATCHes the attacker's comment, overwriting its content with the ack message.

Suggested fix: Add an author filter to the jq expression:

--jq 'map(select(.body | contains("<!-- qwen-review-ack -->")) | select(.user.login == "github-actions[bot]"))[-1].id // ""'

— qwen3.7-max via Qwen Code /review

exit 0
fi
ACK_BODY="<!-- qwen-review-ack -->_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"
EXISTING_ACK_ID="$(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[Suggestion] gh api lookup failure under set -euo pipefail aborts the entire step

The EXISTING_ACK_ID assignment runs in a $() subshell with no error handler. If gh api fails (rate limit, transient error), set -e aborts the step — neither the PATCH nor gh pr comment branch executes. The user sees no acknowledgement at all, when the worst-case fallback (a duplicate ack comment) is harmless.

Suggested change
EXISTING_ACK_ID="$(
EXISTING_ACK_ID="$(
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \
--paginate \
--jq 'map(select(.body | contains("<!-- qwen-review-ack -->")))[-1].id // ""'
)" || EXISTING_ACK_ID=""

— qwen3.7-max via Qwen Code /review

Copilot AI left a comment

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.

Pull request overview

Adds a GitHub-hosted “ack” job to the Qwen PR review workflow so explicit @qwen-code /review requests immediately receive a short PR comment linking to the workflow run, even if the self-hosted runner is busy/queued.

Changes:

  • Add ack-review-request job that detects explicit /review triggers (issue comments, PR review comments, PR reviews) and posts/updates a single “queued” acknowledgement comment with a run link.
  • Keep existing review-pr job routing intact, with an added note to keep explicit-trigger if logic in sync.
  • Adjust environmentContext.test.ts by closing test blocks (appears unrelated to the workflow change).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
.github/workflows/qwen-code-pr-review.yml Adds an acknowledgement job that comments on the PR immediately after explicit /review triggers, linking to the current Actions run.
packages/core/src/utils/environmentContext.test.ts Closes test suite blocks around formatDateForContext (scope appears unrelated to CI change).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +402 to +404
});
});

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No new issues found. The code incorporates fixes from extensive prior review cycles and is clean. LGTM! ✅ — qwen3.7-max via Qwen Code /review

@yiliang114 yiliang114 merged commit 9533afa into QwenLM:main Jun 9, 2026
27 checks 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.

Show an immediate queued status when Qwen Code PR review is triggered

5 participants