fix(ci): harden the zero-build coverage assertion and list all skip suites
Strengthen the ci-workflow.spec.ts guard to match any 'pnpm run build' spelling (corepack prefix, multi-line run blocks) instead of one exact string, and complete the lib-consuming self-skip inventory with the webworker-runtime transform-corpus import sweep alongside the packer image assertions and the built-package check. Update the ci.yml comment and the partitioned-coverage note (both languages) to match, and drop the stale 'post-build' phase wording and the native-Windows build-wait rationale from the coverage-exempt comment.
This commit is contained in:
parent
e2ef25b06e
commit
2dd8b3eac3
6 changed files with 18 additions and 13 deletions
|
|
@ -2,5 +2,5 @@
|
|||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-18-in-job-partitioned-coverage.md
|
||||
2026-08-18-in-job-partitioned-coverage.md: 2bde2a8ea1144543cac2e44bc30828ae9b52b5b4
|
||||
2026-08-18-in-job-partitioned-coverage.zh.md: 95f6ccdeedf1117fe8ea769d7555361b285c368c
|
||||
2026-08-18-in-job-partitioned-coverage.md: ae6ca04106d4ea11d6fbcce2d3c26917ac08d77d
|
||||
2026-08-18-in-job-partitioned-coverage.zh.md: d683f7eab4a77a7e3f6205bbd51fadc68922e48d
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ When partitioning is enabled, `scripts/run-gates.ts` selects `pnpm run test:cove
|
|||
|
||||
The coordinator waits for every child, validates that the blob directory contains exactly the expected files, and then runs one `vitest --merge-reports ... --coverage` command. Only that merged command applies the repository's per-file statement, branch, function, and line thresholds, so a partition is never judged against an intentionally partial inventory.
|
||||
|
||||
`DSH_COVERAGE_MAX_WORKERS` continues to size the uninstrumented exempt gate and the ordinary non-partitioned path; it does not resize partition children. Native Windows gives the exempt gate two workers and admits four concurrent outer gates. In the complete reference, the workspace build and production-site validation start immediately and both coverage gates wait for the complete build; the wait also keeps the exempt gate's temporary Oxlint probes from racing source compilation. The pull-request coverage job runs the same zero-build coverage as Linux: workspace imports resolve to `src` through the tsconfig paths map, and the lib-consuming suites — the exempt gate's packer image assertions and the instrumented corpus's built-package check — self-skip on unbuilt checkouts. The observational inventory waits only for both coverage gates to settle, so it still runs after a coverage failure; each gate's `needs` dependencies remain pass-required. Linux overlaps four instrumented partition processes with two exempt workers, restoring the ordinary path's former four-way instrumented concurrency while keeping every instrumented process single-worker.
|
||||
`DSH_COVERAGE_MAX_WORKERS` continues to size the uninstrumented exempt gate and the ordinary non-partitioned path; it does not resize partition children. Native Windows gives the exempt gate two workers and admits four concurrent outer gates. In the complete reference, the workspace build and production-site validation start immediately and both coverage gates wait for the complete build; the wait also keeps the exempt gate's temporary Oxlint probes from racing source compilation. The pull-request coverage job runs the same zero-build coverage as Linux: workspace imports resolve to `src` through the tsconfig paths map, and the lib-consuming suites — the exempt gate's packer image assertions and full-corpus import sweep, and the instrumented corpus's built-package check — self-skip on unbuilt checkouts. The observational inventory waits only for both coverage gates to settle, so it still runs after a coverage failure; each gate's `needs` dependencies remain pass-required. Linux overlaps four instrumented partition processes with two exempt workers, restoring the ordinary path's former four-way instrumented concurrency while keeping every instrumented process single-worker.
|
||||
|
||||
## Failure and output semantics
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ A normal failed test still emits a blob through `--coverage.reportOnFailure`, al
|
|||
|
||||
`scripts/coverage-partitions.spec.ts` pins argument construction, package-script separator removal, one-worker partitions, weighted longest-processing-time assignment (including a case that fails when assignment ignores recorded weights), the single merged threshold command, failed-test merging, failure diagnostics before complete-blob validation, waiting for sibling partitions after a spawn failure, and link-safe cleanup. `scripts/run-gates.spec.ts` pins opt-in selection, invalid-count rejection, both native Windows coverage gates' complete-build dependency, the complete Windows inventory with its blocking split, and unbuffered streamed output. React fake-timer cases that can move between partitions advance timers inside `act()`; geometry-dependent portal tests stub their element rectangles so a different shard schedule cannot turn deferred updates or jsdom coordinates into coverage-only failures.
|
||||
|
||||
Completed native Windows comparisons measured two partitions near 405 seconds and sixteen partitions at 112.66–122.01 seconds under the earlier gate ordering; those values compare partition latency, not the current peak. The current post-build phase runs four instrumented partition processes beside two exempt workers, for six coverage execution units. Sixteen partitions would raise that phase to eighteen before any still-running production-site work or system overhead. Four partitions keep separate-process isolation and match Linux, at the cost of a longer single-job coverage wall time; the trade-off is accepted to reduce vitest worker startup failures under high self-hosted concurrency. Two Linux samples measured the conservative two-partition configuration at 276.68 and 282.27 seconds; that configuration was stable but halved the ordinary path's four instrumented workers. Four partitions restore that fan-out, for six total coverage execution units on the 16-core hosted runner and at most 36 across the failover VM's six runner instances. These values come from completed runs or fixed capacity bounds; an unfinished run crossing an arbitrary elapsed-time mark is not evidence for increasing concurrency.
|
||||
Completed native Windows comparisons measured two partitions near 405 seconds and sixteen partitions at 112.66–122.01 seconds under the earlier gate ordering; those values compare partition latency, not the current peak. The current coverage phase runs four instrumented partition processes beside two exempt workers, for six coverage execution units. Sixteen partitions would raise that phase to eighteen before any still-running production-site work or system overhead. Four partitions keep separate-process isolation and match Linux, at the cost of a longer single-job coverage wall time; the trade-off is accepted to reduce vitest worker startup failures under high self-hosted concurrency. Two Linux samples measured the conservative two-partition configuration at 276.68 and 282.27 seconds; that configuration was stable but halved the ordinary path's four instrumented workers. Four partitions restore that fan-out, for six total coverage execution units on the 16-core hosted runner and at most 36 across the failover VM's six runner instances. These values come from completed runs or fixed capacity bounds; an unfinished run crossing an arbitrary elapsed-time mark is not evidence for increasing concurrency.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Status: implemented
|
|||
|
||||
协调器等待全部子进程结束,验证 blob 目录只包含预期文件,然后执行一次 `vitest --merge-reports ... --coverage`。只有这条合并命令应用仓库的逐文件语句、分支、函数与行阈值,因此系统不会拿有意不完整的测试清单单独判定任一分区。
|
||||
|
||||
`DSH_COVERAGE_MAX_WORKERS` 继续控制无插桩豁免门禁和普通非分区路径的规模,不会调整分区子进程。原生 Windows 为豁免门禁分配 2 个 worker,并允许 4 道外层门禁并发。在完整参考流程中,工作区构建与生产网站验证会立即启动,两道覆盖率门禁都等待完整构建;这次等待也能避免豁免门禁的临时 Oxlint 探针与源码编译竞态。拉取请求覆盖率 job 与 Linux 一样以零构建方式运行:工作区导入通过 tsconfig paths 映射解析到 `src`,而消费构建产物的套件——豁免门禁的打包器镜像断言与插桩语料的 built-package 校验——在未构建的检出上会自跳。观测性清单只等待两道覆盖率门禁结算,因此在覆盖率失败后仍会运行;各门禁自身的 `needs` 依赖仍要求前置门禁通过。Linux 让 4 个插桩分区进程与 2 个豁免 worker 重叠运行,在保持每个插桩进程只有 1 个 worker 的同时,恢复普通路径原有的 4 路插桩并发。
|
||||
`DSH_COVERAGE_MAX_WORKERS` 继续控制无插桩豁免门禁和普通非分区路径的规模,不会调整分区子进程。原生 Windows 为豁免门禁分配 2 个 worker,并允许 4 道外层门禁并发。在完整参考流程中,工作区构建与生产网站验证会立即启动,两道覆盖率门禁都等待完整构建;这次等待也能避免豁免门禁的临时 Oxlint 探针与源码编译竞态。拉取请求覆盖率 job 与 Linux 一样以零构建方式运行:工作区导入通过 tsconfig paths 映射解析到 `src`,而消费构建产物的套件——豁免门禁的打包器镜像断言与全语料导入 sweep,以及插桩语料的 built-package 校验——在未构建的检出上会自跳。观测性清单只等待两道覆盖率门禁结算,因此在覆盖率失败后仍会运行;各门禁自身的 `needs` 依赖仍要求前置门禁通过。Linux 让 4 个插桩分区进程与 2 个豁免 worker 重叠运行,在保持每个插桩进程只有 1 个 worker 的同时,恢复普通路径原有的 4 路插桩并发。
|
||||
|
||||
## 失败与输出语义
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ Status: implemented
|
|||
|
||||
`scripts/coverage-partitions.spec.ts` 固定了参数构造、包脚本分隔符移除、单 worker 分区、加权最长处理时间分配(含一个在分配忽略记录权重时必然失败的用例)、唯一一次合并阈值命令、失败测试合并、完整 blob 校验前的失败诊断、spawn 失败后等待兄弟分区,以及链接安全清理。`scripts/run-gates.spec.ts` 固定了显式启用、非法数量拒绝、两道原生 Windows 覆盖率门禁对完整构建的依赖、完整 Windows 清单及其阻断性划分,以及不缓冲的流式输出。可能在分区间移动的 React fake-timer 用例会在 `act()` 内推进计时器;依赖几何位置的 portal 测试会固定元素矩形,使不同分片调度不会把延迟更新或 jsdom 坐标变成只在覆盖率运行中出现的失败。
|
||||
|
||||
已完成的原生 Windows 对比中,双分区耗时约 405 秒,16 分区耗时 112.66–122.01 秒;这些数据来自先前的门禁顺序,只用于比较分区延迟,不代表当前峰值。当前的构建后阶段会让 4 个插桩分区进程与 2 个豁免 worker 并行,共形成 6 个覆盖率执行单元。若改为 16 个分区,则在尚未结束的生产网站工作或系统开销计入之前,该阶段就会达到 18 个执行单元。4 个分区保留独立进程隔离并与 Linux 对齐,代价是单 job 覆盖率墙钟更长;这是为了降低自托管高并发下 vitest worker 启动失败而接受的取舍。两个 Linux 样本中,保守的双分区配置耗时 276.68 秒和 282.27 秒;该配置运行稳定,却把普通路径原有的 4 个插桩 worker 减半。4 个分区恢复这份并发,使 16 核托管 runner 上的覆盖率执行单元总数为 6,故障切换虚拟机的 6 个 runner 实例最多合计 36 个执行单元。这些数值来自完整运行或固定容量上限;运行尚未结束时跨过任意耗时刻度,不构成增加并发的证据。
|
||||
已完成的原生 Windows 对比中,双分区耗时约 405 秒,16 分区耗时 112.66–122.01 秒;这些数据来自先前的门禁顺序,只用于比较分区延迟,不代表当前峰值。当前的覆盖率阶段会让 4 个插桩分区进程与 2 个豁免 worker 并行,共形成 6 个覆盖率执行单元。若改为 16 个分区,则在尚未结束的生产网站工作或系统开销计入之前,该阶段就会达到 18 个执行单元。4 个分区保留独立进程隔离并与 Linux 对齐,代价是单 job 覆盖率墙钟更长;这是为了降低自托管高并发下 vitest worker 启动失败而接受的取舍。两个 Linux 样本中,保守的双分区配置耗时 276.68 秒和 282.27 秒;该配置运行稳定,却把普通路径原有的 4 个插桩 worker 减半。4 个分区恢复这份并发,使 16 核托管 runner 上的覆盖率执行单元总数为 6,故障切换虚拟机的 6 个 runner 实例最多合计 36 个执行单元。这些数值来自完整运行或固定容量上限;运行尚未结束时跨过任意耗时刻度,不构成增加并发的证据。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
|
|
|
|||
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
|
@ -514,8 +514,9 @@ jobs:
|
|||
}
|
||||
# No build before coverage, matching the Linux lane: workspace imports
|
||||
# resolve to src through the tsconfig paths map, and the lib-consuming
|
||||
# suites (webworker-packer image-loadable, session-persistence-sqlite
|
||||
# built-package) self-skip on unbuilt checkouts.
|
||||
# suites (webworker-packer image-loadable, webworker-runtime
|
||||
# transform-corpus, session-persistence-sqlite built-package) self-skip
|
||||
# on unbuilt checkouts.
|
||||
- name: Run Windows coverage
|
||||
shell: pwsh
|
||||
run: pnpm run check:ci:coverage
|
||||
|
|
|
|||
|
|
@ -156,9 +156,12 @@ describe('CI workflow', () => {
|
|||
expect(coverageCommands.map(step => step.run)).toContain('pnpm run check:ci:coverage')
|
||||
// Windows coverage runs zero-build like the Linux lane: workspace imports
|
||||
// resolve to src through the tsconfig paths map, and the lib-consuming
|
||||
// suites (webworker-packer image-loadable, session-persistence-sqlite
|
||||
// built-package) self-skip on unbuilt checkouts.
|
||||
expect(coverageCommands.map(step => step.run)).not.toContain('pnpm run build')
|
||||
// suites (webworker-packer image-loadable, webworker-runtime
|
||||
// transform-corpus, session-persistence-sqlite built-package) self-skip
|
||||
// on unbuilt checkouts. The regex catches a regression spelled as
|
||||
// 'corepack pnpm run build' or folded into a multi-line run block, which
|
||||
// an exact string match would miss.
|
||||
expect(coverageCommands.every(step => !/\bpnpm\s+run\s+build(?:\s|$)/.test(step.run))).toBe(true)
|
||||
|
||||
// windows-native-tests runs the Windows-specific specs.
|
||||
expect(windowsNativeTests.name).toBe('windows node 24 / native tests')
|
||||
|
|
|
|||
|
|
@ -50,8 +50,9 @@ export const coverageExemptHeavySuites: readonly CoverageExemptSuite[] = [
|
|||
{ filter: 'scripts/change-scope.spec.ts', exclude: 'scripts/change-scope.spec.ts' },
|
||||
{ filter: 'scripts/translation-pairing-merge.spec.ts', exclude: 'scripts/translation-pairing-merge.spec.ts' },
|
||||
// Built-artifact proof. Packer/runtime src is threshold-excluded, and the
|
||||
// native Windows aggregate makes this uninstrumented gate wait for build so
|
||||
// the suite never observes a partially emitted workspace closure.
|
||||
// suite self-skips on unbuilt checkouts; the serial-windows complete
|
||||
// reference still starts this uninstrumented gate after its build gate, so
|
||||
// the assertions execute against complete real artifacts there.
|
||||
{
|
||||
filter: 'packages/experimental/webworker-packer/tests/image-loadable.spec.ts',
|
||||
exclude: 'packages/experimental/webworker-packer/tests/image-loadable.spec.ts',
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue