From 7f28369030a00deb6f43e4822e5ec7486265f265 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 7 Aug 2026 12:06:21 +0000 Subject: [PATCH] =?UTF-8?q?ci(workflows):=20objectui-pin-freshness=20?= =?UTF-8?q?=E8=A1=A5=20merge=5Fgroup=20=E8=A7=A6=E5=8F=91=E5=99=A8,?= =?UTF-8?q?=E9=98=9F=E5=88=97=E4=B8=96=E4=BB=A3=E8=B5=B0=20advisory=20?= =?UTF-8?q?=E8=BD=A6=E9=81=93=20(#6121)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 该 workflow 的注释明文邀请维护者把 `Console Pin Freshness` 加进 main 的 required 集,而它只订阅 pull_request + workflow_dispatch。合并队列在 gh-readonly-queue/** 世代上重新求值 required checks,一个在队列世代上不产生 check run 的 required context 会让每个世代永久等待(#3622 原型)。本仓队列是 活的(event=merge_group 共 2745 次运行,最近一批在今天 12:00 前后)。 三处改动,全部在同一文件内: 1. on: 增加裸键 merge_group:(与 ci.yml / lint.yml / spec-liveness-check.yml 同族写法)。 2. 邀请注释改写为带前置条件的邀请:加入 required 集之所以安全,正是因为 merge_group 触发器现在存在;后来的编辑者在保留/加入 required 前必须确认 该触发器仍在。 3. 车道判据由 `[ "$EVENT" != "pull_request" ]` 改为按事件显式分类。这一处是 加触发器的必要组成:该否定式在 on: 只有两项的年代等价于 workflow_dispatch, 加入 merge_group 后会把每个队列世代扫进 BLOCKING 车道,而脚本在 enforcing 模式下只要 pin != objectui main HEAD 就 exit 1 —— 即本文件自述的"两次 pin bump 之间的常态"。只加触发器会得到一个系统性飘红的队列检查,设为 required 后每个 PR 都被踢出队列,等于把 pending 死锁换成红色死锁,issue 想要的 "之后加 required 才安全"并不成立。新判据落实的是文件里已写下的既有政策 (blocks only on the release lane),不是新政策。 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01BDmDsu2575gDxeMCxXhDE3 --- .github/workflows/objectui-pin-freshness.yml | 50 ++++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/.github/workflows/objectui-pin-freshness.yml b/.github/workflows/objectui-pin-freshness.yml index 64436c3a21..2eeaeebb71 100644 --- a/.github/workflows/objectui-pin-freshness.yml +++ b/.github/workflows/objectui-pin-freshness.yml @@ -31,16 +31,35 @@ name: Console Pin Freshness # either way, so a green run on an ordinary PR still shows how far the pin has # drifted. # -# REQUIRED-CHECK ENFORCEMENT IS NOT SELF-DECLARED -# ----------------------------------------------- +# REQUIRED-CHECK ENFORCEMENT IS NOT SELF-DECLARED — AND IT HAS A PRECONDITION +# ---------------------------------------------------------------------------- # A workflow cannot make itself required. A maintainer must add the # `Console Pin Freshness` context to the branch-protection rule for `main` # (Settings → Branches → main → Require status checks to pass). Until then this # workflow REPORTS on the release PR without blocking the merge button. +# +# ⚠️ THE PRECONDITION IS THE `merge_group:` TRIGGER BELOW (#6121). Adding this +# context to a required set is safe ONLY BECAUSE that trigger now exists. The +# paragraph above states the PR half of the rule — "a required context that +# reports nothing leaves every PR stuck" — and until #6121 this file invited +# maintainers into the required set while missing the QUEUE half: branch +# protection is evaluated AGAIN on the `gh-readonly-queue/**` generation, so a +# required context that produces no run THERE parks every queue generation +# forever (#3622 is the prototype for that deadlock). +# +# FUTURE EDITORS: before this context is added to — or left in — any required +# set, confirm `merge_group:` is still in `on:` below. Deleting that trigger +# does not fail loudly; it deadlocks the merge queue for every PR in the repo. on: pull_request: branches: [main] + # Merge queue (see ci.yml for the full note): a required context must report + # on queue generations too, or queue builds wait forever on a check that never + # arrives. This is the precondition documented above (#6121). Which LANE the + # event lands in — blocking vs reporting — is decided in the pin-freshness + # step below, not here. + merge_group: workflow_dispatch: concurrency: @@ -87,12 +106,33 @@ jobs: # with the title configured in release.yml. Either identifies the lane; # both are checked so a future rename of one does not silently disarm # the gate. - if [ "$EVENT" != "pull_request" ] \ + # + # LANE BY EVENT — classify every new trigger HERE, explicitly (#6121). + # This test used to read `[ "$EVENT" != "pull_request" ]`, a negation + # that meant "workflow_dispatch" back when `on:` had exactly two + # entries. Adding `merge_group:` is the moment that proxy breaks: the + # negation would sweep every queue generation into the BLOCKING lane, + # where this gate goes red whenever the pin lags — the repo's normal + # state between bumps (see WHERE IT BLOCKS at the top) — and a required + # context that is systematically red EJECTS every PR from the queue. + # That would trade one deadlock for another rather than fix it. + # + # workflow_dispatch → BLOCKS. A human asked for the full check. + # merge_group → reports. The queue generation of an ordinary PR + # is an ordinary PR; the Version Packages PR is + # enforced on its own `pull_request` run, and + # release.yml runs this same script on the publish + # path — the backstop with no override input. + # pull_request → BLOCKS on the release lane only. + # + # HEAD_REF and PR_TITLE are empty on merge_group (no `pull_request` in + # the payload), so the two release-lane tests are false there anyway. + if [ "$EVENT" = "workflow_dispatch" ] \ || [ "$HEAD_REF" = "changeset-release/main" ] \ || [ "$PR_TITLE" = "chore: version packages" ]; then - echo "::notice::Release lane — the objectui pin-freshness gate BLOCKS here (#3340)." + echo "::notice::Release lane or manual run — the objectui pin-freshness gate BLOCKS here (#3340)." node scripts/check-objectui-pin-fresh.mjs else - echo "::notice::Not the Version Packages PR — pin freshness is reported but does not block (a pin lagging between bumps is normal). It blocks on the release PR." + echo "::notice::Not the release lane — pin freshness is reported but does not block (a pin lagging between bumps is normal). It blocks on the Version Packages PR and on the publish path." node scripts/check-objectui-pin-fresh.mjs --advisory fi