qwen-code/.github/workflows
Shaojin Wen 1f9318f974
feat(triage): stop in-agent CI polling, finalize evidence and approval after CI completes (#7693)
* feat(triage): stop in-agent CI polling, finalize evidence and approval after CI completes

The triage agent's Stage 2b polled pending checks for up to 10 minutes, but
this repo's unit suite runs ~30 minutes, so the poll always burned its full
budget, gave up with 'CI still running', and Stage 3 could then approve before
the suite finished (observed on a PR approved 12 minutes before its Test job
completed).

Split the wait out of the agent entirely:

- pr-workflow.md Stage 2b now forbids polling: fetch check-runs once, report
  pending checks honestly, and wrap the CI table in qwen-triage-ci region
  markers keyed to the reviewed SHA.
- Stage 3 defers a clean-verdict approval when checks are still pending: the
  comment carries an approve-on-green marker instead of an immediate APPROVE.
- New qwen-triage-finalize.yml fires on workflow_run completion of 'Qwen Code
  CI' / 'E2E Tests' and, with plain bash over the API (no model, no checkout),
  rewrites the marked table region with the settled results and posts the
  commit-pinned approval only when every check landed green — failing closed
  on red checks, a moved head, or a closed/draft PR, and flipping the triage
  status comment to say which way it resolved.

Markers are honored only in comments authored by the bot identity itself, and
check names (attacker-influenced on fork PRs) go through the same HTML-escape
chain the skill mandates for file paths.

Stage comments now land ~10 minutes sooner and the approval, when deferred,
lands at CI completion with full evidence instead of before it.

* fix(triage): address finalize review — broken red gate, table truncation, dead trigger

Review findings on the finalize workflow, all reproduced before fixing:

- Blocker 1: the RED jq used the array-first membership form, where | rebinds
  . and .conclusion indexes an array — jq exits 5 every run, RED comes back
  empty, [ "" -gt 0 ] errors, and control falls through to the approve path:
  a red CI auto-approved. The gate now binds the conclusion before the
  membership test (IN(...)), and the counters are numeric-validated so any
  future jq failure reads as 'cannot attest', never 'approve'.
- Blocker 2: the table rendered raw check-runs — on a real PR (96 runs, 35
  names, 68 skipped) alphabetical sort + head -60 truncated away every actual
  test job. table_rows now dedups per name (latest run), drops skipped rows,
  and sorts running/non-green first so the cap can only cut green rows.
  Replayed against the same PR: 96 rows -> 16, unit suite present.
- The approval gate now reads workflow runs filtered to event=pull_request
  (deduped per workflow) instead of head-SHA check-runs, which also carry
  long-running bot orchestration jobs that would wedge PENDING above zero at
  the exact moment the last CI workflow fires — silently dropping the
  deferred approval forever. The skill's Stage 3 PENDING count matches.
- E2E Tests had no pull_request trigger (dead entry); the workflows list is
  now exactly the six pull_request-triggered workflows, so the last finisher
  always re-fires the job.
- Head/state re-check moved before the red/deferred verdicts so a
  cancel-in-progress firing on a stale SHA cannot stamp a red status over
  the new head's comment; the still-deferred branch now updates the status
  comment instead of staying invisible.
- replace_region fails closed when the end-marker text only precedes the
  begin marker (awk END guard) — previously that shape truncated the comment
  body, eating the signature and reviewed-commit footer.
- Region content is deterministic (no run URL) so the no-op cmp works;
  empty run list or unavailable gate skips approval; comment wording fixed
  (workflow_run jobs are attributed to the default branch, so the self-check
  exclusion is belt-and-braces, not load-bearing).

Tests now execute the decision logic, not just grep for it: gate_counts and
table_rows run against fixtures covering every conclusion class, non-PR
events, re-run dedup, skipped filtering, ordering, and both marker-order
failure shapes. 30/30 passing.

* fix(triage): keep a stale finalize firing from clobbering the newer review's status comment

The status comment is deliberately not SHA-scoped (the triage workflow
creates it unscoped; scoping only the finalize side would orphan the
pairing), so a finalize firing for an old SHA that loses the race against a
newer head's green approval would overwrite the  status with a stale
warning. Guard the stale path: when the current head already carries bot
sha= markers (a re-review owns the status comment), stay silent; when the
head moved with no re-review yet — triage does not auto-rerun on
synchronize — the stale note is accurate and still posts. Closed/draft PRs
now just log instead of flipping the status.

* fix(triage): close the guardrail bypass and align the finalize table with the gate

Second review round, all four findings reproduced or confirmed before fixing:

- The approve-on-green marker was emitted in Step 1 while the fork-refactor
  GUARD only ran in Step 2 — a marker that slipped out on a fork refactor
  would have been honored by the finalize job on green CI, bypassing the
  guardrail entirely. GUARD now computes in Step 1 and gates the marker's
  emission, and the finalize job re-asserts it structurally from the PR
  state it already fetched (null head.repo = deleted fork = blocked), with
  a 'guarded' status message instead of an approval.
- table_rows now restricts check-runs to the suites of the same deduped
  event=pull_request workflow runs the gate trusts. Without it, 5 of 8
  rendered rows on this PR's own head were bot plumbing presented as CI
  evidence; with it, 115 raw check-runs reduce to exactly the 3 CI rows.
- A firing that saw PENDING>0 after the approval landed flipped the status
  comment back to 'deferred' with nothing to ever right it; the
  already-approved branch now repairs the status.
- Zero surviving table rows (failed runs fetch, missing suite ids) skips
  the region rewrite instead of blanking the agent's table, and
  replace_region refuses an empty region file (an unchecked getline would
  have deleted the region and its markers unrecoverably).

Nits: the house github.repository guard on the job, the table header
matches the skill template, and the run-URL stays out of the region so the
no-op cmp keeps working.
2026-07-25 00:58:16 +00:00
..
audio-capture-prebuilds.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
build-and-publish-image.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
cd-cua-driver.yml fix(mcp): add opt-in model payload filtering (#7413) 2026-07-21 09:49:04 +00:00
cd-mobile-mcp.yml fix(mcp): add opt-in model payload filtering (#7413) 2026-07-21 09:49:04 +00:00
ci.yml test(triage): regression-guard the triage workflow, and make the git cleanup an allowlist (#7660) 2026-07-24 11:02:19 +00:00
codeql.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
comment-attachment-guard.yml ci: add suspicious comment attachment guard (#6599) 2026-07-10 09:40:54 +00:00
desktop-release.yml fix(ci): avoid oversized desktop release notes (#6792) 2026-07-13 03:25:21 +00:00
docs-page-action.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
e2e.yml ci: quarantine cron-interactive from push E2E to nightly-only (#6986) 2026-07-15 17:18:28 +00:00
finalize-release.yml ci(release): finalize stable releases asynchronously (#6868) 2026-07-15 00:30:51 +00:00
gemini-scheduled-pr-triage.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
main-ci-failure-issue.yml feat(release): generate AI-assisted release notes (#6756) 2026-07-12 13:00:22 +00:00
pr-force-push-reminder.yml ci(autofix): run agents on dedicated ECS runners (#6207) 2026-07-03 07:40:07 +00:00
pr-self-report-label.yml ci: label a PR that closes an issue its own author opened (#7630) 2026-07-24 05:50:47 +00:00
qwen-autofix.yml refactor(autofix): extract review verification runner (#7644) 2026-07-24 16:46:24 +00:00
qwen-ci-flaky-rerun.yml fix(ci): stop a slow patrol classifier from killing every flaky rerun (#7358) 2026-07-21 02:33:51 +00:00
qwen-code-pr-review.yml fix(ci): serialise the two workflows that push to a PR head branch (#7392) 2026-07-21 07:40:56 +00:00
qwen-fleet-shepherd.yml feat(autofix): label-driven takeover and release; fix forced-dispatch green no-op (#7165) 2026-07-19 07:35:13 +00:00
qwen-issue-followup-bot.yml fix(ci): consolidate issue triage ownership (#7180) 2026-07-19 10:58:40 +00:00
qwen-pr-safety-precheck.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
qwen-triage-finalize.yml feat(triage): stop in-agent CI polling, finalize evidence and approval after CI completes (#7693) 2026-07-25 00:58:16 +00:00
qwen-triage.yml fix(ci): don't fail triage cleanup when there is nothing to clean (#7688) 2026-07-24 17:44:25 +00:00
release-sdk-java.yml fix(sdk-java): Harden daemon transport reliability (#7603) 2026-07-24 04:22:05 +00:00
release-sdk-python.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
release-sdk.yml fix(ci): skip empty SDK release PR (#6861) 2026-07-14 13:19:42 +00:00
release-vscode-companion.yml fix(ci): add retry logic to VSCode IDE Companion publish steps (#6574) 2026-07-09 09:54:27 +00:00
release.yml ci: move release-note classifier from per-PR workflow to release-time batch (#7339) 2026-07-20 23:52:09 +00:00
sdk-java.yml fix(sdk-java): Harden daemon transport reliability (#7603) 2026-07-24 04:22:05 +00:00
sdk-python.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
serve-ab-publish.yml ci(serve): daemon A/B before/after preview on response-surface PRs (#6975) 2026-07-16 00:58:52 +00:00
serve-ab.yml ci(serve): daemon A/B before/after preview on response-surface PRs (#6975) 2026-07-16 00:58:52 +00:00
stale.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
sync-cua-driver-to-oss.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
sync-release-to-oss.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
terminal-bench.yml Upgrade GitHub Actions for Node 24 compatibility (#5157) 2026-07-07 12:17:22 +00:00
update-ecs-runner-qwen.yml fix(ci): update qwen in the runner's active npm prefix (#7689) 2026-07-24 19:11:41 +00:00
web-shell-visuals-cleanup.yml feat(web-shell): auto-post visual previews (screenshots + flow GIFs) on PRs (#6880) 2026-07-15 06:48:52 +00:00
web-shell-visuals-publish.yml fix(ci): don't let one failing scenario sink the whole visual preview (#7511) 2026-07-23 02:34:07 +00:00
web-shell-visuals.yml fix(ci): don't let one failing scenario sink the whole visual preview (#7511) 2026-07-23 02:34:07 +00:00