Skip to content

ci: shard-timings-refresh 的写回步骤缺两个 env 变量,每周定时刷新在算完之后死于 RUN_COUNT: unbound variable —— 数据集已 22 天未动,而 pull_request 演练结构上跑不到这条腿 #18341

Description

@os-try-charles

.github/workflows/shard-timings-refresh.yml 的写回步骤(行 636)在 set -euo pipefail 下引用了两个没有导出到该步骤的变量,于是每周一的定时刷新都会在算完之后、推之前死掉。⇒ scripts/test-shard-timings.json 自 2026-08-24 起未动过,22 天。

⚠️ priority: 与 domain: 故意留空 —— 分诊的活,不是本席的。
⚠️ 本卡改 .github/workflows/** ⇒ 受管面,席位 auto_merge 恒 422,只能人工合(与 #18096 / #18224 同一堵墙)。

根因 —— 行 653 用了 $RUN_COUNT 与 $RUNS,行 638–641 的 env: 只给了两个

636  - name: Push the refresh branch and open the pull request
637    if: steps.compare.outputs.changed == 'true' && github.event_name != 'pull_request'
638    env:
639      GH_TOKEN:  ${{ secrets.RELEASE_PUSH_TOKEN || github.token }}
640      RUN_ID:    ${{ steps.generate.outputs.run_id }}
641      HEAD_SHA:  ${{ steps.generate.outputs.head_sha }}      ← ⛔ 没有 RUNS,没有 RUN_COUNT
642    run: |
643      set -euo pipefail                                       ← -u 就是执行判决的那个字母
...
653        -m "… artifacts of $RUN_COUNT accumulated run(s) ($RUNS), newest $RUN_ID at $HEAD_SHA. …"

发火对照,同一文件同一批 outputs:紧邻的「Compose the pull request body」步骤(行 522)把四个全导出了:

524    env:
525      RUN_ID:    ${{ steps.generate.outputs.run_id }}
526      RUNS:      ${{ steps.generate.outputs.runs }}        ← 这两个在这里有
527      RUN_COUNT: ${{ steps.generate.outputs.run_count }}   ←
528      HEAD_SHA:  ${{ steps.generate.outputs.head_sha }}

⇒ 四个 output 都存在、都可导;⛔ 不是 generator 少产了值,是写回步骤漏抄了两行。

实测 —— 唯一一次定时运行的日志(run 34810389734,2026-09-14T05:38Z)

前面每一步都绿,数据集是算出来了的:

 8  Self-test the generator and the run selector            success
10  Choose a green, uncensored, un-replayed run             success
11  Regenerate the dataset, accumulating runs until …       success
12  Compare against the committed dataset                   success
13  Predicted bins, before and after                        success
14  Compose the pull request body                           success
15  Push the refresh branch and open the pull request       FAILURE   ←
16  Dry run — the pull request this would have opened       skipped

日志末两行,逐字:

2026-09-14T05:40:01.8259343Z Switched to a new branch 'claude/shard-timings-refresh-34808103618'
2026-09-14T05:40:01.8336893Z /home/runner/work/_temp/….sh: line 9: RUN_COUNT: unbound variable
2026-09-14T05:40:01.8347096Z ##[error]Process completed with exit code 1.

分支切出来了、git add 也过了,死在 git commit 拼消息体那一行。

⭐ 为什么合入前的演练抓不到它 —— 推送路径结构上跑不到

工作流头注写着本车道「改动在合并前先演练」。演练确实跑了,但它跑的是另一条分支:

行 637  写回步骤    if: … && github.event_name != 'pull_request'
行 690  演练步骤    if: … && github.event_name == 'pull_request'

⇒ 在 pull_request 上,写回步骤永远 skipped。实测四次运行的分派:

run 7  schedule      failure   ← 写回步骤唯一一次真跑,就是它死的那次
run 6  pull_request  success   ← 步骤 15 skipped,步骤 16 success
run 5  pull_request  success   ← 同上
run 4  pull_request  failure   (别的原因)
run 1  pull_request  failure   (别的原因)

⇒ 写回路径的首次执行就是 2026-09-14 那次定时运行。演练与被演练的是互斥的两条腿,而合并门只看得见其中一条。

影响 —— 一张 p1 卡正卡在这个通道上

scripts/test-shard-timings.json 在 origin/main 上的最近两次改动:

e75e34381  2026-08-24  fix(ci): … shard timings re-measured (#11868)
7c9e5a59b  2026-08-21  ci(test-core): balance the Test Core shards on measured suite duration …

⇒ 22 天没动。而 #16173(priority:p1,pm:on-hold)的 dev 报告里那个 open_questions[0] 问的正是「这些 run summary 怎么送到 generator 手上」,推荐 B = 先落 #16464(定时刷新工作流),让刷新发生在 runner 内部,没有下载可被拒。

B 已经落了 —— #16464 closed completed,shard-timings-refresh.yml 就在 origin/main 上。⛔ 但它从未交付过一次刷新。⇒ #16173 等的是一个已经建好、却在最后一米静默失败的通道。

验收(⛔ 不规定实现)

  1. 让写回步骤拿到它引用的每一个变量。⛔ 不许反过来把 $RUN_COUNT/$RUNS 从提交消息里删掉换取绿 —— 那两个值是这个文件 provenance 的全部内容(「Generated, never hand-edited」靠它们才成立)。
  2. ⭐ 两个方向都要量:构造缺一个变量让它红,补齐让它绿。⛔ 只证补齐后绿不算。
  3. ⭐ 补上一条结构性的防线,让「env: 漏导致 set -u 炸」这一类下次在合并前就被抓到 —— 演练腿与写回腿共用同一个 env: 块,或一条比对两个 if: 互斥步骤 env: 键集的检查,或别的。⛔ 本卡不指定哪一条,但只修那两行不够:同一个形状在这个文件里还有第二处的可能没被排除(⛔ 本席没查)。
  4. 修完触发一次 workflow_dispatch,拿到一个真开出来的 PR 作为验收读数。⛔ 「下周一等着看」不是验收。
  5. ⛔ 不许在本卡里顺手改 #16173 的阈值(MAX_SHARD_OVER_MEAN / MAX_MEASURED_OVER_PREDICTED)—— partitioner 自己的头注把抬这两个数点名为唯一不可能正确的动作,且抬 ratchet 上限是人工地板。

⛔ 没量的部分,不许当读数用

  • ⛔ 没跑过修复,也没跑过 workflow_dispatch。 本卡只量了失败,⛔ 不主张补两行 env: 之后整步就绿 —— 行 653 之后还有 git push / gh pr create / 标签写回三段,它们一次都没被执行过,后面藏着第二个 unbound variable 或权限问题完全可能。
  • ⛔ 没审这个文件其余 716 行里有没有同形的 env: 漏项。抽查到的只有行 636 这一处与行 522 那一处对照。
  • ⛔ 没量 run 4 与 run 1 那两次 pull_request 失败的原因,它们与本卡是否同因未知。
  • ⛔ 没量定时触发本身是否每周都在放(total_count 只有 5 次运行、其中 schedule 仅 1 次)。本卡不主张调度器漏放,也不主张它没漏 —— 工作流 2026-09-07 才落,到 2026-09-14 只经过一个周一,与「每周一放一次」一致,但一个样本证不了周期性。
  • 查重:按更新时间枚举 2026-09-06 以来的 2500 条(未穷尽),另对故障之后的窗口做了完整枚举 —— 卡号 18136..18340 每一个整数都在手(缺 0 个),shard-timings / RUN_COUNT / unbound variable 命中 0。

Refs:#16173(priority:p1 pm:on-hold,其 open_questions[0] 等的就是这条通道)· #16464(落了工作流,closed completed)· #16445(为此临时抬到 45 分钟的墙)· #16465(pm:blocked 的漂移告警)

domain:devx 执行席 · 座位贴 #6023 · 读数取自 origin/main 与 Actions run 34810389734 的作业日志


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions