|
|
@@ -9,6 +9,7 @@ import { spawn } from 'node:child_process'
|
|
|
import { availableParallelism } from 'node:os'
|
|
|
import { resolve } from 'node:path'
|
|
|
import { performance } from 'node:perf_hooks'
|
|
|
+import { COVERAGE_EXEMPT_ENV, coverageExemptHeavySuites } from './coverage-exempt.ts'
|
|
|
|
|
|
/** A named aggregate exposed by the gate runner. */
|
|
|
export type Mode =
|
|
|
@@ -202,7 +203,7 @@ export function gatesForMode(selected: Mode): Gate[] {
|
|
|
pnpmScript('duplication', 'duplication'),
|
|
|
]
|
|
|
case 'ci-coverage':
|
|
|
- return [coverageGate()]
|
|
|
+ return coverageGates()
|
|
|
case 'ci-snapshot':
|
|
|
return [pnpmScript('build', 'build'), snapshotGate()]
|
|
|
case 'ci-artifacts':
|
|
|
@@ -248,7 +249,7 @@ function ciPrimaryGates(): Gate[] {
|
|
|
pnpmScript('typecheck', 'typecheck'),
|
|
|
lintGate(),
|
|
|
pnpmScript('duplication', 'duplication'),
|
|
|
- coverageGate(),
|
|
|
+ ...coverageGates(),
|
|
|
...nodeCompatSmokeGates(),
|
|
|
snapshotGate(),
|
|
|
...docSyncLeafGates(),
|
|
|
@@ -407,15 +408,51 @@ function lintGate(): Gate {
|
|
|
: { displayCommand: `DSH_OXLINT_THREADS=${raw} pnpm run lint` })
|
|
|
}
|
|
|
|
|
|
-function coverageGate(): Gate {
|
|
|
- return pnpmExec('coverage', [
|
|
|
- 'vitest',
|
|
|
- 'run',
|
|
|
- '--coverage',
|
|
|
- ...positiveIntArg('DSH_COVERAGE_MAX_WORKERS', '--maxWorkers'),
|
|
|
- ], {
|
|
|
- label: 'test:coverage',
|
|
|
- })
|
|
|
+// The heavy suites run uninstrumented beside the thresholded gate: their
|
|
|
+// compiler- and subprocess-bound fixtures pay a multiple of their runtime
|
|
|
+// under v8 instrumentation while contributing nothing the thresholds need
|
|
|
+// (membership contract in scripts/coverage-exempt.ts).
|
|
|
+//
|
|
|
+// DSH_COVERAGE_MAX_WORKERS is the lane's worker budget, so the two parallel
|
|
|
+// gates split it instead of each claiming it whole (the failover pool's
|
|
|
+// 8 x 6-instance bound assumes one lane never exceeds its value). The exempt
|
|
|
+// gate's wall clock is dominated by its longest single file, so it takes the
|
|
|
+// small share. A budget of 1 gives each gate 1 worker; lanes that need a
|
|
|
+// strict total of one (the serial reference jobs) also set
|
|
|
+// DSH_GATE_CONCURRENCY=1, which keeps the gates from overlapping at all.
|
|
|
+function coverageWorkerArgs(): { instrumented: string[]; exempt: string[] } {
|
|
|
+ const [flag] = positiveIntArg('DSH_COVERAGE_MAX_WORKERS', '--maxWorkers')
|
|
|
+ if (flag === undefined) return { instrumented: [], exempt: [] }
|
|
|
+ const total = Number.parseInt(flag.split('=')[1] ?? '', 10)
|
|
|
+ const exempt = Math.max(1, Math.floor(total / 3))
|
|
|
+ const instrumented = Math.max(1, total - exempt)
|
|
|
+ return {
|
|
|
+ instrumented: [`--maxWorkers=${String(instrumented)}`],
|
|
|
+ exempt: [`--maxWorkers=${String(exempt)}`],
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function coverageGates(): Gate[] {
|
|
|
+ const workers = coverageWorkerArgs()
|
|
|
+ return [
|
|
|
+ pnpmExec('coverage', [
|
|
|
+ 'vitest',
|
|
|
+ 'run',
|
|
|
+ '--coverage',
|
|
|
+ ...workers.instrumented,
|
|
|
+ ], {
|
|
|
+ label: 'test:coverage',
|
|
|
+ env: { [COVERAGE_EXEMPT_ENV]: '1' },
|
|
|
+ }),
|
|
|
+ pnpmExec('coverage-exempt-heavy', [
|
|
|
+ 'vitest',
|
|
|
+ 'run',
|
|
|
+ ...coverageExemptHeavySuites.map(suite => suite.filter),
|
|
|
+ ...workers.exempt,
|
|
|
+ ], {
|
|
|
+ label: 'test:coverage-exempt-heavy',
|
|
|
+ }),
|
|
|
+ ]
|
|
|
}
|
|
|
|
|
|
// Example and package snapshots boot their bins in `lib` mode (built artifacts under plain Node,
|