fix(ci): acknowledge queued qwen review requests#4847
Conversation
|
Thanks for the PR! Template looks good ✓ On direction: this solves a genuine UX gap — when the self-hosted On approach: the scope is tight — one job, one step, 42 lines added. The One minor observation: the Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 方向:解决了一个真实的 UX 问题——当 self-hosted 方案:范围紧凑——一个 job、一个 step、42 行新增。 一个小观察: 进入代码审查 🔍 — Qwen Code · qwen3.7-max |
Code ReviewThe diff is 42 lines added to a single workflow file, and it's clean:
No correctness bugs, security issues, or AGENTS.md violations found. TestingThis 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 Verification performed: Lint and CodeQL pass. Tests are pending (not affected by this workflow-only change). 中文说明代码审查diff 是单个 workflow 文件新增 42 行,代码干净:
未发现正确性 bug、安全问题或 AGENTS.md 违规。 测试这是 GitHub Actions workflow 文件变更——没有用户可见的 CLI 行为可以通过 tmux 驱动测试。变更只能在 GitHub Actions 对真实 已执行的验证:Prettier 格式检查通过,YAML 语法有效,Lint 和 CodeQL CI 检查通过。当前环境无 — Qwen Code · qwen3.7-max |
|
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
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
| gh pr comment "$PR_NUMBER" \ | ||
| --repo "$GITHUB_REPOSITORY" \ | ||
| --body "_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._" |
There was a problem hiding this comment.
[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.
| 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' |
There was a problem hiding this comment.
[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:
| 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
left a comment
There was a problem hiding this comment.
No review findings. Downgraded from Approve to Comment: CI failing (triage). — qwen3.7-max via Qwen Code /review
wenshao
left a comment
There was a problem hiding this comment.
No issues found. LGTM! ✅ — qwen3.7-max via Qwen Code /review
# Conflicts: # .github/workflows/qwen-code-pr-review.yml
✅ Local verification — queued-review acknowledgement workflowVerified 1. Lint & format — clean
2. Structure & consistency
3. Gating truth-table — 18 / 18 (faithful evaluation of the exact
|
| 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 withSkipping 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 /reviewtooling at runtime, not by this workflow'sif/steps (review-prhas noisCrossRepositorygate). 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 fromreview-pr. GitHub expression string literals don't process\nas a newline, so this sub-condition likely matches a literal\nrather 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 toreview-prregardless. 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 |
There was a problem hiding this comment.
[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:
- Remove the fork check from
ack-review-requestso the ack is posted consistently withreview-pr's actual behavior (simpler). - Add a matching fork check to
review-prfor 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 |
There was a problem hiding this comment.
[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.
| cancel-in-progress: true | |
| cancel-in-progress: false |
— qwen3.7-max via Qwen Code /review
|
|
||
| delay-automatic-review: | ||
| ack-review-request: | ||
| if: |- |
There was a problem hiding this comment.
[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' |
There was a problem hiding this comment.
[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.
| - name: 'Post queued acknowledgement' | |
| pull-requests: 'write' | |
| issues: 'write' |
— qwen3.7-max via Qwen Code /review
| runs-on: 'ubuntu-latest' | ||
| permissions: | ||
| pull-requests: 'write' | ||
| issues: 'write' |
There was a problem hiding this comment.
[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.
| 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: |
There was a problem hiding this comment.
[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 |
There was a problem hiding this comment.
[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); | ||
| }); |
There was a problem hiding this comment.
[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: |
There was a problem hiding this comment.
[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.
| 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' || |
There was a problem hiding this comment.
[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:
| (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})._" |
There was a problem hiding this comment.
[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:
| --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 }}' |
There was a problem hiding this comment.
[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:
| 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 }}' |
There was a problem hiding this comment.
[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: |
There was a problem hiding this comment.
[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:
| 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})._" |
There was a problem hiding this comment.
[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' && |
There was a problem hiding this comment.
[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
✅ Local re-verification (updated) — queued-review acknowledgement
No Docker here, so What the PR changes (head
|
| Scenario | gh call sequence |
Result |
|---|---|---|
| No prior ack | pr view → api …/comments → pr comment |
posts the exact body <!-- qwen-review-ack -->_…queued in [workflow run](‹url›)._ |
| Existing ack (id 123456) | pr view → api …/comments → api --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‑hostedecs-qwenrunner (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/reviewupdates the same comment instead of stacking.- Author‑association gate (
OWNER/MEMBER/COLLABORATOR) limits triggering to trusted users; the ack is posted byGITHUB_TOKENand its body doesn't match@qwen-code /review, so there's no self‑retrigger loop. on:includes all three events theifkeys 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)
- Behavioral change to
review-prnot mentioned in the description. Addingreview.state == 'commented'means a review submitted as Approve or Request changes whose body contains@qwen-code /reviewwill no longer trigger a review (it did before). The commonissue_commentpath is unaffected. It keeps ack/review consistent and is defensible — but please confirm it's intended.pull_request_reviewold → new:approved:trigger→skip ·changes_requested:trigger→skip ·commented: trigger (unchanged).
permissions: pull-requests: writeis broader than needed. The step only doesgh pr view --json state(read); every comment write goes through theissuesendpoint (issues: write).pull-requests: readwould suffice (least‑privilege).- Inert
'\n'sub‑condition (pre‑existing, copied verbatim fromreview-pr):format('@qwen-code /review{0}', '\n')is a literal backslash‑nin 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。
| EXISTING_ACK_ID="$( | ||
| gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \ | ||
| --paginate \ | ||
| --jq 'map(select(.body | contains("<!-- qwen-review-ack -->")))[-1].id // ""' |
There was a problem hiding this comment.
[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.
| --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 // ""' |
There was a problem hiding this comment.
[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="$( |
There was a problem hiding this comment.
[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.
| 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
There was a problem hiding this comment.
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-requestjob that detects explicit/reviewtriggers (issue comments, PR review comments, PR reviews) and posts/updates a single “queued” acknowledgement comment with a run link. - Keep existing
review-prjob routing intact, with an added note to keep explicit-triggeriflogic in sync. - Adjust
environmentContext.test.tsby 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.
| }); | ||
| }); | ||
|
|
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
No new issues found. The code incorporates fixes from extensive prior review cycles and is clean. LGTM! ✅ — qwen3.7-max via Qwen Code /review
What this PR does
Adds an immediate acknowledgement for explicit Qwen Code PR review requests. When a collaborator comments
@qwen-code /reviewin 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-qwenrunner. 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 /reviewon 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
Environment (optional)
Validated workflow formatting locally with
npx prettier --check .github/workflows/qwen-code-pr-review.yml.actionlintwas not available in this environment, and the GitHub event itself must be verified by the PR workflow.Risk & Scope
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-qwenrunner。当 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
环境(可选)
本地通过
npx prettier --check .github/workflows/qwen-code-pr-review.yml验证 workflow 格式。当前环境没有actionlint,GitHub event 级别的端到端验证需要在 GitHub Actions 中完成。风险与范围
关联 Issue
Fixes #4846