mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
ci: run coverage-exempt heavy suites uninstrumented in parallel
The coverage lane's wall clock was pinned by a few compiler- and subprocess-bound suites whose v8 instrumentation tax is a multiple of their runtime while contributing nothing the per-file thresholds need: typert generator fixtures (whole-workspace compiler analysis; its src is threshold-excluded) and three scripts/ child-process fixture suites (scripts/ sources are never coverage-measured; in-process imports are covered by their owning package tests). Split ci-coverage into two parallel gates: the instrumented run sets DSH_COVERAGE_EXEMPT_HEAVY=1 and vitest.config.ts drops the exempt suites from both projects (CLI --exclude cannot reach per-project include resolution); a second uninstrumented gate runs exactly those suites, so the aggregate still executes every test. Membership contract and the filter/exclude pairs live in scripts/coverage-exempt.ts. Local 6-worker A/B: instrumented gate 900s -> 260s wall; exempt gate 262s wall runs beside it, so the lane converges near the slower of the two (~4.4min vs ~7min single-gate). DSH_GATE_CONCURRENCY now has two schedulable gates in this lane.
This commit is contained in:
41
scripts/coverage-exempt.ts
Normal file
41
scripts/coverage-exempt.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Heavy suites the coverage aggregate runs uninstrumented in a parallel gate.
|
||||
* Membership contract: a suite qualifies only when every coverage-measured
|
||||
* file it executes in-process (`coverage.include` spans package src trees;
|
||||
* typert generator src is threshold-excluded in vitest.config.ts) is already
|
||||
* fully covered by other suites, so removing it from the instrumented run
|
||||
* changes no threshold outcome. The aggregate still runs every listed suite
|
||||
* plain beside the instrumented gate, so correctness signal is unchanged —
|
||||
* only the v8 instrumentation tax on compiler- and subprocess-heavy fixtures
|
||||
* is dropped.
|
||||
*/
|
||||
|
||||
/** One coverage-exempt suite: a Vitest CLI filter and its exclude glob. */
|
||||
export interface CoverageExemptSuite {
|
||||
/** Positional file filter selecting the suite in the uninstrumented gate. */
|
||||
readonly filter: string
|
||||
/** Exclude glob removing the suite from the instrumented gate. */
|
||||
readonly exclude: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to `1` by the instrumented coverage gate; vitest.config.ts then drops
|
||||
* the exempt suites from every project. CLI `--exclude` cannot express this:
|
||||
* it does not reach per-project include resolution.
|
||||
*/
|
||||
export const COVERAGE_EXEMPT_ENV = 'DSH_COVERAGE_EXEMPT_HEAVY'
|
||||
|
||||
/** Coverage-exempt heavy suites; keep filter and exclude selecting the same files. */
|
||||
export const coverageExemptHeavySuites: readonly CoverageExemptSuite[] = [
|
||||
// Whole-workspace compiler analysis per case — the lane's longest tail.
|
||||
// Generator src is threshold-excluded; tools-catalog's registry and
|
||||
// tool-cordis imports are fully covered by those packages' own tests.
|
||||
{
|
||||
filter: 'packages/typert/generator/tests/',
|
||||
exclude: 'packages/typert/generator/tests/**',
|
||||
},
|
||||
// Real child-process fixtures over scripts/ sources, which coverage never measures.
|
||||
{ filter: 'scripts/install-lefthook.spec.ts', exclude: 'scripts/install-lefthook.spec.ts' },
|
||||
{ filter: 'scripts/oxlint-contract.spec.ts', exclude: 'scripts/oxlint-contract.spec.ts' },
|
||||
{ filter: 'scripts/change-scope.spec.ts', exclude: 'scripts/change-scope.spec.ts' },
|
||||
]
|
||||
@@ -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,30 @@ 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).
|
||||
function coverageGates(): Gate[] {
|
||||
return [
|
||||
pnpmExec('coverage', [
|
||||
'vitest',
|
||||
'run',
|
||||
'--coverage',
|
||||
...positiveIntArg('DSH_COVERAGE_MAX_WORKERS', '--maxWorkers'),
|
||||
], {
|
||||
label: 'test:coverage',
|
||||
env: { [COVERAGE_EXEMPT_ENV]: '1' },
|
||||
}),
|
||||
pnpmExec('coverage-exempt-heavy', [
|
||||
'vitest',
|
||||
'run',
|
||||
...coverageExemptHeavySuites.map(suite => suite.filter),
|
||||
...positiveIntArg('DSH_COVERAGE_MAX_WORKERS', '--maxWorkers'),
|
||||
], {
|
||||
label: 'test:coverage-exempt-heavy',
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
// Example and package snapshots boot their bins in `lib` mode (built artifacts under plain Node,
|
||||
|
||||
Reference in New Issue
Block a user