Repository navigation
ci(ui-merge): Test UI runs only the ui tests a pull request or merge group affects — the root ci.yml wires ui/scripts/select-affected-tests.mjs - #25882
Conversation
…up affects Wire ui/scripts/select-affected-tests.mjs into the root test-ui job and teach the selector the changes outside ui/ that every ui test runs through (a non-documentation workspace-root file, patches/, one of the monorepo packages the ui tests read built). Claude-Session: https://claude.ai/code/session_015oJuSyTy7Y3cm91KJMEW2m Co-Authored-By: Claude <noreply@anthropic.com>
… nested-layout selector cases Claude-Session: https://claude.ai/code/session_015oJuSyTy7Y3cm91KJMEW2m Co-Authored-By: Claude <noreply@anthropic.com>
…st-ui job through helpers/root-ci Claude-Session: https://claude.ai/code/session_015oJuSyTy7Y3cm91KJMEW2m Co-Authored-By: Claude <noreply@anthropic.com>
|
CI on
Reading from this run, the always-on shape (no ui package changed): the 16 Test UI shards took 2.1–3.7 min each, 46 runner-min in total. Before this PR, the same jobs ran the full suite: 6.6–12.0 min per shard and 184 runner-min in run 40251065567 (a ci.yml-only change), and 8.5–14.3 min per shard in run 40248884869. Head is now Generated by Claude Code |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40263268635 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by Tesla · project thread
Fixes #25868
Part of #25677
Clause-②: no
Metadata-protocol: none
维护者速读(草稿)
ci.yml的 Test UI(16 个分片)在 pull request 和 merge queue 上不再每次跑全量 ui 测试,而是先用 objectui 原有的ui/scripts/select-affected-tests.mjs选出本次改动影响到的测试文件,只跑这些。push 到 main、每小时的 schedule 和手动触发仍然跑全量。patches/,以及 ui 测试读取其构建产物的 7 个 @objectstack 包)一律全量。回滚:revert 本 PR 即恢复每次全量。.github/workflows/ci.yml),需要你批准后由席位落地。What changed
.github/workflows/ci.yml, jobtest-ui— objectui's two-step wiring, ported:Select the tests this change affects(idselect):pull_requestandmerge_grouprun the selector; every other event writesmode=full. Fails open: no base, a non-zero exit or no verdict line meansmode=full, never a skip. The exit status is captured beside the output, not through a command substitution.merge-base(origin/BASE_REF, HEAD), the same base Test Core uses, not the payload's frozenbase.sha. With the frozen sha, every commitmaingained while the PR was open (a lockfile bump among them) would be charged to the PR and turn it into a full run. A merge group diffs frommerge_group.base_sha.Run the ui tests (shard N/16)reads the output's VALUE (affected/full). Onaffectedit runspnpm --dir ui exec vitest run --shard=N/16 ... FILTERSwith the filters relative toui/(the vitest root), as positionals with no separator, which is the only formui/scripts/vitest-invocation-guard.mjsaccepts. Onfullit runs the command it ran before.fetch-depth: 0so the base's history is there (Test Core and Type Check UI do the same).ui/scripts/select-affected-tests.mjs— the git paths already went through--relative(tooling(objectui-readiness 4): objectui scripts address git paths relative to the repo root —git show ref:packages/…,diff --name-only,ls-files,ls-treebreak one level down in ui/; prefix via nestedPrefix() (parent #25677, 2d/6) #25728). Its own diff dropped every changed file outsideui/, though, so a lockfile bump, a roottsconfig.jsonor apackages/specchange selected only the always-on set (measured below). New:changedOutsideTree()lists the monorepo's own changes (git at the workspace root,--relativeagain, theui/prefix dropped), andoutsideTreeReasons()turns them into full-run reasons:patches/(the rule the selector already applied to objectui's own root, now applied to the root this tree installs from);dependencies/peerDependencies/optionalDependencies). On this tree that set is exactly the seven packages theui_consumersfilter names: spec, client, core, types, lint, formula, sdui-parser.ui/(other packages, docs,.changeset/,.github/,scripts/) reaches ui tests only through the always-on set, as before.ui/scripts/__tests__/select-affected-tests-wiring.test.tsnow reads the rootci.yml(located throughworkspaceRoot()) and runs both steps there at the monorepo root. Agitstand-in answersmerge-baseas HEAD and records the call, so the legs assert the step asks forrefs/remotes/origin/mainandHEAD. A new leg covers a failing merge-base: full run. The controls are unchanged.ui/scripts/__tests__/select-affected-tests.test.ts: theci.ymlwiring block now reads the root job (includingfetch-depth: 0and the 16-wide matrix). A new nested-layout fixture (ui/under a parent workspace) covers each outside-tree rule in both directions. One case runs real git in a scratch repo to show thatchangedFilesandchangedOutsideTreesplit one diff between them.The turbo parity case (
agrees with turbo on who depends on whom) was already green in the merged layout onmain. It is unchanged and still green.ui/.github/workflows/ci.yml(objectui's copy, which runs nowhere) is left as it is; the governance-workflow audit owns it.Measured
Selector verdicts on this tree (
c475b45b+ this diff), from scratch commits in a detached worktree:ui/(this PR's own shape: workflow +ui/scripts)ui/packages/plugin-gantt/src/index.tsui/packages/plugin-kanban/src/KanbanColumnSummary.ts(reaches app-shell)pnpm-lock.yaml+packages/spec/src/index.ts, before this diffWeighted by
ui/scripts/test-shard-timings.json(the sequencer's per-file dataset): always-on alone is 8.8% of the summed file time, plugin-gantt 20.2%, plugin-kanban 54.2%,ui/packages/fields88.9%. Each shard still pays its fixed cost (checkout, install, building the seven packages). The before/after shard wall times are read from this PR's own Test UI run, which is the always-on shape, and posted on the card.Verification
pnpm exec vitest run scripts/__tests__/select-affected-tests.test.ts scripts/__tests__/select-affected-tests-wiring.test.ts(inui/): 2 files, 49 tests, all pass.ui/scripts/__tests__suite (pnpm exec vitest run scripts/__tests__inui/, headbc79c8aa): 190 files, 5608 passed, 2 skipped, 1 failed. The failure ischeck-pre-install-import-graph.test.ts> "finds no pre-install gate reaching a package" (unresolved: scripts/objectstack-pin.mjs, which the cutover deleted andui/.github/workflows/*still name). It fails the same way onc475b45bwith this diff's four files restored (37 tests, 1 failed), so it is red onmainalready and not this PR's. It is reported to the dispatcher. That file is in the always-on set, so it keeps running on every affected Test UI run.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran: 63 derived, 59 run with exit 0, 4 NOT MEASURED (exit 3, built dists absent):check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closure,check:sourcemap-no-sources-content. These are Build Core's guards, and Build Core runs them on this PR (ci.ymlis in thecorefilter).Acceptance notes
uifilter decides that, unchanged). On a merge group, Test UI runs today for every entry, and this diff makes it full for an entry that touches the seven packages or a root install input, and affected otherwise. ci(ui-merge): every merge-queue entry runs all four ui lanes because theuifilter output falls back to 'true' on merge_group — decide the ui lanes from the diff againstmerge_group.base_sha, as Test Core already does (parent #25677) #25867 (merge_group ui path diff) is the card that decides whether such an entry runs Test UI at all.Generated by Claude Code