Merge remote-tracking branch 'origin/master' into fix/node26-vitest-webstorage
# Conflicts: # scripts/run-gates.spec.ts # vitest.config.ts
This commit is contained in:
@@ -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 =
|
||||
@@ -195,14 +196,14 @@ export function gatesForMode(selected: Mode): Gate[] {
|
||||
case 'ci-linux-primary':
|
||||
return [...ciPrimaryGates(), webSnapshotGate(['built-package-invariants'])]
|
||||
case 'ci-static':
|
||||
return ciStaticGates()
|
||||
return ciStaticGates({ ownsBuild: false })
|
||||
case 'ci-lint':
|
||||
return [
|
||||
lintGate(),
|
||||
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(),
|
||||
@@ -300,16 +301,21 @@ function nodeCompatSmokeGates(): Gate[] {
|
||||
]
|
||||
}
|
||||
|
||||
function ciStaticGates(): Gate[] {
|
||||
function ciStaticGates(options: { ownsBuild: boolean }): Gate[] {
|
||||
return [
|
||||
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
|
||||
pnpmScript('constraints', 'constraints'),
|
||||
pnpmScript('package-invariants', 'verify-package-invariants', { label: 'package invariants' }),
|
||||
pnpmScript('cordis-config', 'verify-cordis-config', { label: 'Cordis config' }),
|
||||
pnpmScript('build', 'build'),
|
||||
...options.ownsBuild ? [pnpmScript('build', 'build')] : [],
|
||||
...docSyncLeafGates({
|
||||
docTypecheckNeeds: ['build'],
|
||||
docTypecheckEnv: { DSH_DOC_TYPECHECK_USE_BUILD_OUTPUT: '1' },
|
||||
includeDocTypecheck: options.ownsBuild,
|
||||
...options.ownsBuild
|
||||
? {
|
||||
docTypecheckNeeds: ['build'],
|
||||
docTypecheckEnv: { DSH_DOC_TYPECHECK_USE_BUILD_OUTPUT: '1' },
|
||||
}
|
||||
: {},
|
||||
docsBuildScript: 'docs:build:mpa',
|
||||
}),
|
||||
pnpmScript('module-graph', 'verify-module-graph', { label: 'module graph' }),
|
||||
@@ -331,23 +337,28 @@ function ciArtifactGates(): Gate[] {
|
||||
}
|
||||
|
||||
function ciConsumerGates(): Gate[] {
|
||||
const publicArtifacts = ['publint']
|
||||
const restoredBuild = ['built-package-invariants']
|
||||
const builtTree = ['build']
|
||||
const validatedBuild = ['built-package-invariants']
|
||||
return [
|
||||
pnpmScript('build', 'build'),
|
||||
pnpmScript('node-compat', 'check:node-compat', { label: 'Node compatibility' }),
|
||||
pnpmScript('publint', 'publint', { needs: builtTree }),
|
||||
builtPackageInvariantsGate(['publint']),
|
||||
pnpmScript('lint-and-duplication', 'check:ci:lint', {
|
||||
label: 'lint and duplication',
|
||||
needs: restoredBuild,
|
||||
needs: validatedBuild,
|
||||
}),
|
||||
snapshotGate(validatedBuild),
|
||||
webSnapshotGate(validatedBuild),
|
||||
pnpmScript('doc-typecheck', 'doc-typecheck', {
|
||||
needs: validatedBuild,
|
||||
env: { DSH_DOC_TYPECHECK_USE_BUILD_OUTPUT: '1' },
|
||||
}),
|
||||
pnpmScript('node-compat', 'check:node-compat', { label: 'Node compatibility' }),
|
||||
snapshotGate(restoredBuild),
|
||||
webSnapshotGate(restoredBuild),
|
||||
pnpmScript('publint', 'publint'),
|
||||
pnpmScript('node-next-types', 'verify-node-next-types', {
|
||||
label: 'node-next types',
|
||||
needs: restoredBuild,
|
||||
needs: validatedBuild,
|
||||
}),
|
||||
builtPackageInvariantsGate(publicArtifacts),
|
||||
builtBinSmokeGate(restoredBuild),
|
||||
builtBinSmokeGate(validatedBuild),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -382,7 +393,7 @@ function ciWindowsCompleteGates(): Gate[] {
|
||||
|
||||
function ciWindowsObservationalGates(): Gate[] {
|
||||
return [
|
||||
...ciStaticGates(),
|
||||
...ciStaticGates({ ownsBuild: true }),
|
||||
// Linux owns required lint, coverage, and snapshots; Windows omits those duplicates.
|
||||
pnpmScript('duplication', 'duplication'),
|
||||
pnpmScript('publint', 'publint', { needs: ['build'] }),
|
||||
@@ -402,20 +413,56 @@ 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,
|
||||
// plugins via real exports); repository-script snapshots execute their real source entry path.
|
||||
// Build-owning modes wait on `build`; a restored-artifact mode passes its validation dependency.
|
||||
// Callers wait either on `build` or on a validation gate that transitively owns that build.
|
||||
function snapshotGate(needs: string[] = ['build']): Gate {
|
||||
return pnpmScript('snapshot', 'test:snapshot', {
|
||||
env: { DSH_EXAMPLE_MODE: 'lib' },
|
||||
@@ -463,6 +510,7 @@ function hygieneLeafGates(options: { artifactNeeds?: string[] } = {}): Gate[] {
|
||||
}
|
||||
|
||||
function docSyncLeafGates(options: {
|
||||
includeDocTypecheck?: boolean
|
||||
docTypecheckNeeds?: string[]
|
||||
docTypecheckEnv?: Record<string, string | undefined>
|
||||
docsBuildScript?: 'docs:build' | 'docs:build:mpa'
|
||||
@@ -471,7 +519,9 @@ function docSyncLeafGates(options: {
|
||||
if (options.docTypecheckNeeds !== undefined) docTypecheckOptions.needs = options.docTypecheckNeeds
|
||||
if (options.docTypecheckEnv !== undefined) docTypecheckOptions.env = options.docTypecheckEnv
|
||||
return [
|
||||
pnpmScript('doc-typecheck', 'doc-typecheck', docTypecheckOptions),
|
||||
...options.includeDocTypecheck === false
|
||||
? []
|
||||
: [pnpmScript('doc-typecheck', 'doc-typecheck', docTypecheckOptions)],
|
||||
pnpmScript('cordis-catalog', 'verify-cordis-catalog', { label: 'cordis catalog' }),
|
||||
pnpmScript('export-jsdoc', 'verify-export-jsdoc', { label: 'export jsdoc' }),
|
||||
pnpmScript('tool-catalog', 'verify-tool-catalog', { label: 'tool catalog' }),
|
||||
|
||||
Reference in New Issue
Block a user