feat(ci): let the PR review canary cohort carry its own endpoint (#16130)

* feat(ci): let the PR review canary cohort carry its own endpoint

The review canary split (QWEN_PR_REVIEW_MODEL_CANARY/PERCENT) only moves
the model name; both cohorts share REVIEW_OPENAI_BASE_URL and its key, so
a rate-limited canary model also burns the shared gateway's quota — the
shape behind the 429-storm review timeouts.

Add an optional endpoint pair for the canary cohort:
QWEN_PR_REVIEW_BASE_URL_CANARY (variable) + REVIEW_OPENAI_API_KEY_CANARY
(secret). When the bucket routes to the canary and both are set, base URL
and key move with the model and the canary host joins NO_PROXY. A URL
without its own key, or an unparseable URL, degrades to the default
cohort with a warning — forwarding the default key to another provider
would leak it. A canary model identical to the default model disables the
override (buckets are indistinguishable). The cohort notice now prints
the resolved cohort so rollouts stay attributable.

Unset, behavior is byte-for-byte today's: model-only split on the shared
endpoint.

* fix(ci): drop inert canary NO_PROXY append and record the workflow's new size

The canary endpoint override appended its host to NO_PROXY, but nothing in this
job consumes it: configure_qwen_network unsets HTTPS_PROXY/https_proxy/
HTTP_PROXY/http_proxy before the override runs, qwen does not consult NO_PROXY
when building its proxy agent, and the gh/git wrappers that do get the proxy
back only talk to github.com. Removing the two exports also removes the comment
that claimed a proxy-bypass symmetry the step cannot produce.

Lint & Static was red in "Check workflow file size": 276955 bytes against a
recorded 272192 with a 4096 allowance. The growth is the feature itself (the
env pair, the override block, the resolved-cohort field), not prose that could
move into a sibling file, so the baseline moves with the file rather than the
rationale being cut to fit.

Co-authored-by: Qwen-Coder <[email protected]>
Patrol-Run: qwen-pr-closeout/jmvz69ico8s

* refactor(ci): simplify canary endpoint validation

Co-authored-by: Qwen-Coder <[email protected]>

---------

Co-authored-by: qwen-code patrol <[email protected]>
This commit is contained in:
易良andQwen-Coder authored and GitHub committed 2026-11-02 23:22:43 +08:00
1 parent 14de8a035e
commit 4dce337ea2
3 files changed
+177 -9

No files matched your search

+1 -1
View File
@@ -41,7 +41,7 @@
5942 qwen-autofix-fork-signal.yml
469584 qwen-autofix.yml
7061 qwen-ci-flaky-rerun.yml
272192 qwen-code-pr-review.yml
276955 qwen-code-pr-review.yml
107075 qwen-fleet-shepherd.yml
22680 qwen-issue-followup-bot.yml
5760 qwen-pr-safety-precheck.yml
+39 -1
View File
@@ -1054,6 +1054,13 @@ jobs:
REVIEW_MODEL_DEFAULT: '${{ vars.QWEN_PR_REVIEW_MODEL }}'
REVIEW_MODEL_CANARY: '${{ vars.QWEN_PR_REVIEW_MODEL_CANARY }}'
REVIEW_MODEL_CANARY_PERCENT: '${{ vars.QWEN_PR_REVIEW_MODEL_CANARY_PERCENT }}'
# The canary cohort may also carry its own endpoint: a second
# gateway with its own quota, or a provider the default gateway
# does not serve. The pair is all-or-nothing — a URL without its
# own key would send the default key to another provider, so the
# override below refuses that shape and keeps the default cohort.
REVIEW_BASE_URL_CANARY: '${{ vars.QWEN_PR_REVIEW_BASE_URL_CANARY }}'
REVIEW_API_KEY_CANARY: '${{ secrets.REVIEW_OPENAI_API_KEY_CANARY }}'
QWEN_PR_REVIEW_EFFORT: '${{ vars.QWEN_PR_REVIEW_EFFORT }}'
PR_NUMBER: '${{ steps.context.outputs.pr_number }}'
REVIEW_MODE: '${{ steps.context.outputs.review_mode }}'
@@ -1733,13 +1740,44 @@ jobs:
"${REVIEW_MODEL_DEFAULT:-}" "$REVIEW_MODEL_CANARY" \
"$CANARY_PERCENT_EFFECTIVE" "${PR_NUMBER:-}")"
export OPENAI_MODEL
# The canary cohort may carry its own endpoint as well as its own
# model: REVIEW_BASE_URL_CANARY/REVIEW_API_KEY_CANARY move the
# canary's traffic onto a second gateway so its quota is isolated
# from the default cohort's. The pair is all-or-nothing — a URL
# without its own key would send the default key to another
# provider — and an unparseable URL routes nowhere, so both shapes
# degrade to the default cohort, the same direction every canary
# misconfiguration takes.
REVIEW_BASE_URL_CANARY="${REVIEW_BASE_URL_CANARY:-}"
REVIEW_BASE_URL_CANARY="${REVIEW_BASE_URL_CANARY#"${REVIEW_BASE_URL_CANARY%%[![:space:]]*}"}"
REVIEW_BASE_URL_CANARY="${REVIEW_BASE_URL_CANARY%"${REVIEW_BASE_URL_CANARY##*[![:space:]]}"}"
REVIEW_COHORT=default
if [ -n "$REVIEW_MODEL_CANARY" ] &&
[ "${OPENAI_MODEL:-}" = "$REVIEW_MODEL_CANARY" ] &&
[ "$OPENAI_MODEL" != "${REVIEW_MODEL_DEFAULT:-}" ]; then
REVIEW_COHORT=canary
fi
if [ "$REVIEW_COHORT" = canary ] && [ -n "$REVIEW_BASE_URL_CANARY" ]; then
if [ -n "${REVIEW_API_KEY_CANARY:-}" ] &&
node -e 'try{if(!new URL(process.env.REVIEW_BASE_URL_CANARY).host)process.exit(1)}catch{process.exit(1)}' 2>/dev/null; then
OPENAI_BASE_URL="$REVIEW_BASE_URL_CANARY"
OPENAI_API_KEY="$REVIEW_API_KEY_CANARY"
export OPENAI_BASE_URL OPENAI_API_KEY
else
echo "::warning::canary endpoint unusable (REVIEW_OPENAI_API_KEY_CANARY missing or QWEN_PR_REVIEW_BASE_URL_CANARY unparseable); falling back to the default cohort."
OPENAI_MODEL="${REVIEW_MODEL_DEFAULT:-}"
REVIEW_COHORT=default
export OPENAI_MODEL
fi
fi
# The run's own record of which cohort served this review: the model
# is not carried anywhere else a later comparison could read it (the
# cost ledger has tokens, not a model), so a rollout that cannot be
# told apart afterwards is unmeasurable. Both fields are the resolved
# ones — the raw percent would certify a cohort the router clamped
# away.
echo "::notice title=Review model::${OPENAI_MODEL:-<CLI default>} (PR #${PR_NUMBER:-?}, canary ${CANARY_PERCENT_EFFECTIVE}%)"
echo "::notice title=Review model::${OPENAI_MODEL:-<CLI default>} (PR #${PR_NUMBER:-?}, canary ${CANARY_PERCENT_EFFECTIVE}%, cohort ${REVIEW_COHORT})"
MODEL_ARGS=()
if [ -n "${OPENAI_MODEL:-}" ]; then