feat(benchmark): add release evaluation pipeline#7584
Conversation
End-to-end test reportThe exact PR head
This validates the requested path: Release/manual prerelease signal → GitHub Action → ECS self-hosted runner → SQLite worker → Harbor Qwen Code agent → grader → checksummed artifacts → public score in the same GitHub Release. |
gwinthis
left a comment
There was a problem hiding this comment.
Architecture Review: COMMENT (C=0)
Summary
Large feature (+3330/-0) implementing an ECS-based release benchmark pipeline: GitHub Release trigger → SQLite queue → systemd worker → Harbor Docker execution → result published back to GitHub Release.
Architecture Assessment
Strengths:
- Clear separation of concerns: GitHub Actions (trigger/validation), SQLite (durable queue), systemd worker (execution), Harbor (isolation). Each layer owns one responsibility.
- Durable enqueue pattern: GitHub job ends after SQLite enqueue — doesn't hold a runner during multi-hour benchmark. "Successful Action" means "validated + accepted", not "finished".
- Immutable version chain: annotated-tag dereferencing to 40-char commit SHA ensures the benchmarked version is immutable.
- Idempotent run creation: SQLite WAL mode with run/instance/event records, heartbeat, attempts, terminal state.
- Release tag verification: publisher verifies release tag == benchmarked qwen_ref; requires prerelease for manual publication.
- Minimal POC scope: one runner, one suite, SQLite as local truth, Harbor as Docker framework — deliberately small.
Scope observations (non-blocking):
- Single self-hosted runner is a bottleneck for concurrent benchmarks — acceptable for POC
- SQLite is local to the runner — no multi-runner coordination yet
- The
stale.ymlPOC test trampoline is a creative workaround for GitHub'sworkflow_dispatchregistration limitation
Pattern
Durable enqueue for long-running CI jobs: When a CI trigger starts a multi-minute or multi-hour job, don't hold the runner. Validate + enqueue durably (SQLite), return success meaning "accepted", and let a separate worker own execution, heartbeat, retry, and completion. This separates trigger reliability from execution reliability.
中文说明
架构评审:COMMENT (C=0)
概要
大型功能(+3330/-0):ECS 发布评测流水线。GitHub Release 触发 → SQLite 队列 → systemd worker → Harbor Docker 执行 → 结果发布回 GitHub Release。
架构评估
- 关注点分离: GitHub Actions(触发/验证)、SQLite(持久队列)、systemd worker(执行)、Harbor(隔离)
- 持久入队模式: GitHub job 在 SQLite 入队后结束——不占用 runner
- 不可变版本链: annotated-tag 解引用到 40 字符 commit SHA
模式
长时间 CI 作业的持久入队: 多分钟/多小时的 CI 作业不占用 runner。验证 + 持久入队(SQLite),返回"已接受",让独立 worker 负责执行、心跳、重试和完成。
— qwen3.7-max via Qwen Code /review
Review: release evaluation pipelineReviewed at head This is a genuinely well-structured POC — the failure taxonomy ( The blocking problems are in the trigger boundary and what reaches the public Release, plus three CI gates that were verified with different flags than CI uses. Blocker 1 — the release trigger fires on every stable tag family, and writes to their release notes
These events really do fire: For a foreign tag the chain runs all the way to a public write. ## What's Changed
* upstream notes here
<!-- qwen-code-benchmark:start -->
## Qwen Code benchmark
| Field | Result |
| --- | --- |
| Status | **Failed — not scored** |
| Dataset | `swe-bench/swe-bench-verified` at `2` |
| Suite | `swebench_verified_harbor_smoke` |
| Evaluation | Qwen Code agent (Harbor) |
| Cases | 0 / 1 completed |
| Score | Not published |
| Qwen Code | `cua-driver-rs-v0.6.8` · [`bbbbbbb`](.../commit/bbbb...) |
| Run | `qwen-bench-c10eb53c1ac54d50` |
<!-- qwen-code-benchmark:end -->Suggested fixes, both cheap:
Blocker 2 — a single-case smoke publishes as "Score 100.00%" on the official releaseSame default-suite path, but on a real | Status | **Completed** |
| Dataset | `swe-bench/swe-bench-verified` at `2` |
| Suite | `swebench_verified_harbor_smoke` |
| Evaluation | Qwen Code agent (Harbor) |
| Cases | 1 / 1 completed |
| Results | 1 resolved · 0 unresolved · 0 infrastructure errors |
| Score | **100.00%** |The PR description is careful that the smoke "is not intended to represent the full 500-case suite", but the published artifact carries none of that framing. A reader sees "Qwen Code benchmark", dataset I'd set Blocker 3 — three CI gates fail; two were verified with non-CI flagsyamllint (this is the current red check, 17 errors). Every value needs single quotes ( prettier — shellcheck — the PR verified with A Medium
Your own
The worker hands its entire environment, including The 16 tests never run in CI. Smaller items
Overlap with #7656#7656 (same author, also draft) is another VerdictRequest changes. Blockers 1 and 2 both end in a public write that misrepresents things — one to unrelated products' release notes, one as an unqualified 100% SWE-bench score — and I'd want those closed before this leaves draft. Blocker 3 is mechanical. The underlying worker, state machine, and artifact design look solid and I don't think they need rework. 中文摘要在 head 三个阻塞项:
中等问题: 其他: 另外 #7656 与本 PR 目标重合且同样是 结论: Request changes。阻塞项 1、2 都会造成对外的错误公开写入,建议在退出 draft 前解决;阻塞项 3 是机械修复。底层 worker / 状态机 / 产物设计不需要返工。 |
Context
Qwen Code needs a reproducible and reviewable path from a published version to a public benchmark result. Before this change, the GitHub trigger, ECS execution prototype, and result display logic lived on separate branches and still included an unused HTTP control plane.
This PR consolidates them into one ECS-based release benchmark pipeline. It deliberately keeps the POC small: one self-hosted runner, one systemd worker, SQLite as the local queue/source of truth, Harbor as the Docker execution framework, and the triggering GitHub Release as the only public result surface.
End-to-end flow
The GitHub job intentionally ends after durable enqueue. A successful Action means that the immutable version was validated and the request was accepted by SQLite; it does not claim that the multi-minute or multi-hour benchmark has already finished. The ECS worker owns execution, heartbeat, retry, completion validation, artifacts, and asynchronous Release publication.
Trigger behavior
release.publishedswebench_verified_harbor_smokein the POCworkflow_dispatchrelease_idis suppliedrelease.publishedThe production workflow is
.github/workflows/benchmark-dispatch.yml. The manual job instale.ymlis a POC test trampoline because GitHub only registers a newly addedworkflow_dispatchworkflow after it exists on the default branch. It allowed the exact PR implementation to be exercised before merge. This PR remains a draft while that POC-only entry is reviewed.What is included
GitHub orchestration
release.publishedtrigger plus a manual prerelease path/usr/local/sbin/qwen-benchmark-dispatchWorker and state model
runs,instances, and append-onlyeventsA run is successful only when every instance frozen in its manifest has exactly one validated terminal result. Action completion, worker process liveness, or a partially written Harbor result is not treated as benchmark completion.
Harbor execution
The publishable POC suite runs the SWE-bench Verified task
sympy__sympy-20590through the open-source Harbor framework. Harbor starts the Docker testbed, installs@qwen-code/qwen-code@<release-version>, runs the Qwen Code agent, and invokes the verifier. Result parsing confirms that Harbor actually recorded the Qwen Code version derived from the requested Release tag.The current POC executes one case at a time with Harbor
--n-concurrent 1. It is intended to prove the control and data path, not to represent the resource model or runtime of the full 500-case SWE-bench Verified suite.Artifact and publication contract
Private run artifacts contain:
summary.jsonstatus.jsonchecksums.sha256publisher-error.jsononly when GitHub publication failsOnly suites with
publish: truemay update GitHub. A successful public table contains:A failed terminal run publishes
Failed — not scoredand status/count information, but no numerical score. Raw trajectories, patches, Docker logs, secrets, internal paths, and model/provider configuration are never copied into the public Release.Release content is bounded by paired markers:
A rerun replaces only this block and preserves content before and after it.
Retry and failure semantics
Automatic retry is limited to classified infrastructure failures, for example:
The POC allows one infrastructure retry (
max_attempts=2). These benchmark outcomes are terminal and are not retried:A publication API failure does not rewrite the benchmark result. It is recorded separately as
publisher-error.json; a durable publication outbox is a production follow-up.Version and publication safety
tag_namepublish: trueEnd-to-end validation
The exact PR head
1a1b0c233be182f101f3e90156721aadc5078ed8was tested against an existing nightly prerelease. The test did not create a Release or tag and did not modify a stable Release.successqwen-bench-fea3c395c9f04249,deduplicated=falsev0.20.0-nightly.20260722.b98306b7e,prerelease=true77115af615fca031a57505dee07deeaf702a0937swe-bench/swe-bench-verified@2sympy__sympy-20590RUNNING_AGENT → GRADING → UPLOADING → SUCCEEDED1.0has_exception=falseGET 200,PATCH 200; existing notes preservederror.json, nopublisher-error.json; worker remainedactiveThe detailed evidence is also recorded in a separate PR comment so that future description edits do not erase the test trail.
Test coverage
shellcheck -e SC1090 benchmark-service/deploy/qwen-benchmark-dispatchpassedThe tests cover submit/idempotency, Harbor result parsing and version validation, worker state/failure handling, publishable-suite gating, Release tag/prerelease binding, paired-marker preservation, invalid Harbor tag handling, and checksum inclusion of publication errors.
Reviewer guide
Recommended review order:
.github/workflows/benchmark-dispatch.yml— trigger, immutable tag resolution, permissions, and dispatch boundary.benchmark-service/qwen_benchmark/suites.json— allowlisted suites, pinned inputs, timeouts, and publication flags.benchmark-service/qwen_benchmark/store.py— SQLite schema, idempotency, claiming, heartbeat, and state transitions.benchmark-service/qwen_benchmark/worker.py— completion, retry, failure, checksums, and publication ordering.benchmark-service/qwen_benchmark/harbor_runner.py— exact npm release installation and Harbor/grader parsing.benchmark-service/qwen_benchmark/publisher.py— public schema, Release binding, and marker replacement.benchmark-service/deploy/— systemd, environment templates, Docker configuration, and restricted sudo command.benchmark-service/tests/anddocs/design/qwen-code-benchmark-release-pipeline.md.To reproduce the code-level checks:
Deployment and rollback
The ECS deployment uses
/srv/qwen-benchmarkfor source, state, artifacts, Harbor jobs, workspaces, and cache. The worker runs asqwen-benchmark-worker.service; the self-hosted runner account can invoke only the dispatcher through the provided sudoers rule.For rollout:
activeRollback is to stop the worker, restore the timestamped ECS worker backup and previous unit/config, restart the service, and revert this PR. SQLite state and historical artifacts are retained for diagnosis.
Known limitations and production follow-ups
stale.ymldispatch trampoline should be removed once the production workflow is registered on the default branch中文摘要
本 PR 把之前分散的触发、ECS worker 和结果展示 POC 合并为一条可复现链路:
GitHub Release → self-hosted ECS runner → SQLite → systemd worker → Harbor/Qwen Code Agent → grader → 校验和产物 → 同一个 GitHub Release 的公开汇总。GitHub Action 只负责解析不可变版本并可靠入队,不会占用 runner 等待数小时;ECS worker 才负责 heartbeat、执行、retry、grader、完整性检查和最终回写。只有 manifest 中所有 case 都有唯一终态并通过校验后,才会发布成功分数。人工触发只能回写 tag 完全一致的 prerelease,正式
release.published才进入稳定版本自动触发路径。本次真实测试是 SWE-bench Verified 的单 case smoke,用于证明完整控制链路,不代表已经执行完整 500-case 数据集。现有 nightly prerelease 上的测试结果为 1/1 resolved、reward 1.0、100.00%,Action、ECS、Harbor、grader、22 项 checksum 和 Release 回写全部通过。