diff --git a/scripts/ci-changed-scope.d.mts b/scripts/ci-changed-scope.d.mts index 3a8ab4b30bc..62ff09bda35 100644 --- a/scripts/ci-changed-scope.d.mts +++ b/scripts/ci-changed-scope.d.mts @@ -14,8 +14,21 @@ export type InstallSmokeScope = { runFullInstallSmoke: boolean; }; +export type NodeFastScope = { + runFastOnly: boolean; + runPluginContracts: boolean; + runCiRouting: boolean; +}; + +export type ChangedScopeArgs = { + base: string; + head: string; + mergeHeadFirstParent: boolean; +}; + export function detectChangedScope(changedPaths: string[]): ChangedScope; export function shouldRunNativeI18n(changedPaths: string[]): boolean; +export function detectNodeFastScope(changedPaths: string[]): NodeFastScope; export function detectInstallSmokeScope(changedPaths: string[]): InstallSmokeScope; export function listChangedPaths( base: string, @@ -27,10 +40,8 @@ export function writeGitHubOutput( scope: ChangedScope, outputPath?: string, installSmokeScope?: InstallSmokeScope, - nodeFastScope?: { - runFastOnly: boolean; - runPluginContracts: boolean; - runCiRouting: boolean; - }, + nodeFastScope?: NodeFastScope, runNativeI18n?: boolean, ): void; + +export function parseArgs(argv: string[]): ChangedScopeArgs; diff --git a/scripts/docs-link-audit.d.mts b/scripts/docs-link-audit.d.mts index 7cc2d22f53a..63f55aabd29 100644 --- a/scripts/docs-link-audit.d.mts +++ b/scripts/docs-link-audit.d.mts @@ -11,12 +11,92 @@ export type ResolveRouteResult = { loop?: boolean; }; +export type MirroredDocsDir = { + cleanup: () => void; + dir: string; + mirroredClawHub: boolean; +}; + +export type ScriptSpawnOptions = { + cwd: string; + env?: NodeJS.ProcessEnv; + shell?: boolean; + stdio: string; +}; + +export type ScriptSpawnResult = { + status: number | null; + error?: { code?: string }; +}; + +export type ScriptSpawn = ( + command: string, + args: string[], + options: ScriptSpawnOptions, +) => ScriptSpawnResult; + +export type ScriptInvocation = { + command: string; + args: string[]; + options?: Partial & { + detached?: boolean; + windowsVerbatimArguments?: boolean; + }; +}; + export function normalizeRoute(route: string): string; export function resolveRoute( route: string, options?: { redirects?: Map; routes?: Set }, ): ResolveRouteResult; -export function auditDocsLinks(): { + +export function sanitizeDocsConfigForEnglishOnly(value: unknown): unknown; + +export function prepareMirroredDocsDir( + sourceDir?: string, + options?: { + resolveClawHubRepoPathImpl?: ( + value?: string, + options?: { required?: boolean }, + ) => string | undefined; + syncClawHubDocsTreeImpl?: ( + targetDocsDir: string, + options?: { repoPath?: string; required?: boolean }, + ) => unknown; + }, +): MirroredDocsDir; + +export function prepareAnchorAuditDocsDir(sourceDir?: string): string; + +export function resolveMintlifyAnchorAuditInvocation(params: { + cwd: string; + nodeVersion?: string; + spawnSyncImpl: ScriptSpawn; + env?: NodeJS.ProcessEnv; + nodeExecPath?: string; + npmExecPath?: string; + platform?: NodeJS.Platform; + comSpec?: string; +}): ScriptInvocation; + +export function auditDocsLinks(options?: { + docsDir?: string; + allowExternalClawHubRoutes?: boolean; +}): { checked: number; broken: BrokenDocLink[]; }; + +export function runDocsLinkAuditCli(options?: { + args?: string[]; + comSpec?: string; + env?: NodeJS.ProcessEnv; + nodeExecPath?: string; + nodeVersion?: string; + npmExecPath?: string; + platform?: NodeJS.Platform; + spawnSyncImpl?: ScriptSpawn; + prepareAnchorAuditDocsDirImpl?: (sourceDir?: string) => string; + prepareMirroredDocsDirImpl?: (sourceDir?: string) => MirroredDocsDir; + cleanupAnchorAuditDocsDirImpl?: (dir: string) => void; +}): number; diff --git a/scripts/test-projects.test-support.d.mts b/scripts/test-projects.test-support.d.mts index 49a9427f5ee..1f1d0a138b9 100644 --- a/scripts/test-projects.test-support.d.mts +++ b/scripts/test-projects.test-support.d.mts @@ -1,3 +1,5 @@ +import type { VitestHostInfo } from "./lib/vitest-local-scheduling.mjs"; + export type VitestRunPlan = { config: string; forwardedArgs: string[]; @@ -11,9 +13,19 @@ export type VitestRunSpec = { includeFilePath: string | null; includePatterns: string[] | null; pnpmArgs: string[]; + preflightPnpmArgs: string[] | null; watchMode: boolean; }; +export type FailedVitestShard = { + code?: number | null; + config: string; + includePatterns?: string[] | null; + noOutputTimedOut?: boolean; + order?: number; + signal?: string | null; +}; + export type ChangedTestTargetOptions = { cwd?: string; env?: Record; @@ -29,6 +41,13 @@ export type ChangedTestTargetPlan = { export const DEFAULT_TEST_PROJECTS_VITEST_NO_OUTPUT_TIMEOUT_MS: string; export const DEFAULT_TEST_PROJECTS_VITEST_NO_OUTPUT_HEARTBEAT_MS: string; +export function orderFullSuiteSpecsForParallelRun( + specs: T[], + shardTimings?: ReadonlyMap, +): T[]; + +export function formatNoChangedTestTargetLines(skippedBroadFallbackPaths: string[]): string[]; + export function parseTestProjectsArgs( args: string[], cwd?: string, @@ -45,6 +64,22 @@ export function buildVitestRunPlans( options?: ChangedTestTargetOptions, ): VitestRunPlan[]; +export function buildFullSuiteVitestRunPlans(args: string[], cwd?: string): VitestRunPlan[]; + +export function shouldUseLocalFullSuiteParallelByDefault( + env?: Record, +): boolean; + +export function shouldExpandLocalFullSuiteShardsByDefault( + env?: Record, +): boolean; + +export function resolveParallelFullSuiteConcurrency( + specCount: number, + env?: Record, + hostInfo?: VitestHostInfo, +): number; + export function resolveChangedTargetArgs( args: string[], cwd?: string, @@ -75,6 +110,8 @@ export function createVitestRunSpecs( }, ): VitestRunSpec[]; +export function createVitestPreflightPnpmArgs(config: string): string[] | null; + export function findUnmatchedExplicitTestTargets( args: string[], cwd?: string, @@ -84,21 +121,45 @@ export function findUnmatchedExplicitTestTargets( includePattern?: string; }>; -export function applyDefaultVitestNoOutputTimeout( - specs: VitestRunSpec[], +export function applyDefaultVitestNoOutputTimeout< + T extends { config: string; env: NodeJS.ProcessEnv; watchMode: boolean }, +>( + specs: T[], params?: { env?: Record; }, -): VitestRunSpec[]; +): Array & { env: NodeJS.ProcessEnv }>; -export function applyDefaultMultiSpecVitestCachePaths( - specs: VitestRunSpec[], +export function applyDefaultMultiSpecVitestCachePaths< + T extends { config: string; env: NodeJS.ProcessEnv; watchMode: boolean }, +>( + specs: T[], params?: { cwd?: string; env?: Record; }, -): VitestRunSpec[]; +): Array & { env: NodeJS.ProcessEnv }>; + +export function applyParallelVitestCachePaths( + specs: T[], + params?: { + cwd?: string; + env?: NodeJS.ProcessEnv; + }, +): Array & { env: NodeJS.ProcessEnv }>; + +export function shouldRetryVitestNoOutputTimeout(env?: Record): boolean; + +export function shouldAcquireLocalHeavyCheckLock( + runSpecs: Array>, + env?: Record, +): boolean; export function writeVitestIncludeFile(filePath: string, includePatterns: string[]): void; +export function formatFailedShardDigest( + failures: FailedVitestShard[], + options?: { limit?: number }, +): string[]; + export function buildVitestArgs(args: string[], cwd?: string): string[]; diff --git a/src/infra/scripts-modules.d.ts b/src/infra/scripts-modules.d.ts index 6a370db57b4..956422444c3 100644 --- a/src/infra/scripts-modules.d.ts +++ b/src/infra/scripts-modules.d.ts @@ -18,19 +18,3 @@ declare module "../../scripts/watch-node.mjs" { lockDisabled?: boolean; }): Promise; } - -declare module "../../scripts/ci-changed-scope.mjs" { - export function detectChangedScope(paths: string[]): { - runNode: boolean; - runMacos: boolean; - runAndroid: boolean; - runWindows: boolean; - runSkillsPython: boolean; - runChangedSmoke: boolean; - runControlUiI18n: boolean; - }; - export function detectInstallSmokeScope(paths: string[]): { - runFastInstallSmoke: boolean; - runFullInstallSmoke: boolean; - }; -} diff --git a/src/scripts/ci-changed-scope.test.ts b/src/scripts/ci-changed-scope.test.ts index 630248a64a3..f7d36554867 100644 --- a/src/scripts/ci-changed-scope.test.ts +++ b/src/scripts/ci-changed-scope.test.ts @@ -13,39 +13,7 @@ const { listChangedPaths, parseArgs, shouldRunNativeI18n, -} = (await import("../../scripts/ci-changed-scope.mjs")) as unknown as { - detectChangedScope: (paths: string[]) => { - runNode: boolean; - runMacos: boolean; - runIosBuild: boolean; - runAndroid: boolean; - runWindows: boolean; - runSkillsPython: boolean; - runChangedSmoke: boolean; - runControlUiI18n: boolean; - }; - detectInstallSmokeScope: (paths: string[]) => { - runFastInstallSmoke: boolean; - runFullInstallSmoke: boolean; - }; - detectNodeFastScope: (paths: string[]) => { - runFastOnly: boolean; - runPluginContracts: boolean; - runCiRouting: boolean; - }; - shouldRunNativeI18n: (paths: string[]) => boolean; - listChangedPaths: ( - base: string, - head?: string, - cwd?: string, - preferMergeHeadFirstParent?: boolean, - ) => string[]; - parseArgs: (argv: string[]) => { - base: string; - head: string; - mergeHeadFirstParent: boolean; - }; -}; +} = await import("../../scripts/ci-changed-scope.mjs"); const markerPaths: string[] = []; const tempDirs: string[] = []; diff --git a/src/scripts/docs-link-audit.test.ts b/src/scripts/docs-link-audit.test.ts index 7707d079a23..d1c502dc30b 100644 --- a/src/scripts/docs-link-audit.test.ts +++ b/src/scripts/docs-link-audit.test.ts @@ -12,48 +12,7 @@ const { resolveRoute, runDocsLinkAuditCli, sanitizeDocsConfigForEnglishOnly, -} = (await import("../../scripts/docs-link-audit.mjs")) as unknown as { - normalizeRoute: (route: string) => string; - prepareAnchorAuditDocsDir: (sourceDir?: string) => string; - prepareMirroredDocsDir: ( - sourceDir?: string, - options?: { - resolveClawHubRepoPathImpl?: (value?: string, options?: { required?: boolean }) => string; - syncClawHubDocsTreeImpl?: ( - targetDocsDir: string, - options?: { repoPath?: string; required?: boolean }, - ) => unknown; - }, - ) => { - cleanup: () => void; - dir: string; - mirroredClawHub: boolean; - }; - resolveRoute: ( - route: string, - options?: { redirects?: Map; routes?: Set }, - ) => { ok: boolean; terminal: string; loop?: boolean }; - runDocsLinkAuditCli: (options?: { - args?: string[]; - nodeVersion?: string; - spawnSyncImpl?: ( - command: string, - args: string[], - options: { cwd: string; env?: NodeJS.ProcessEnv; shell?: boolean; stdio: string }, - ) => { status: number | null; error?: { code?: string } }; - env?: NodeJS.ProcessEnv; - nodeExecPath?: string; - npmExecPath?: string; - prepareAnchorAuditDocsDirImpl?: (sourceDir?: string) => string; - cleanupAnchorAuditDocsDirImpl?: (dir: string) => void; - prepareMirroredDocsDirImpl?: (sourceDir?: string) => { - cleanup: () => void; - dir: string; - mirroredClawHub: boolean; - }; - }) => number; - sanitizeDocsConfigForEnglishOnly: (value: unknown) => unknown; -}; +} = await import("../../scripts/docs-link-audit.mjs"); describe("docs-link-audit", () => { function tempEntries(prefix: string): Set { diff --git a/src/scripts/test-projects.test.ts b/src/scripts/test-projects.test.ts index 12c6251c8e3..6ca40f012dd 100644 --- a/src/scripts/test-projects.test.ts +++ b/src/scripts/test-projects.test.ts @@ -16,98 +16,7 @@ const { resolveChangedTargetArgs, resolveChangedTestTargetPlan, resolveParallelFullSuiteConcurrency, -} = (await import("../../scripts/test-projects.test-support.mjs")) as unknown as { - applyParallelVitestCachePaths: ( - specs: Array<{ - config: string; - env: NodeJS.ProcessEnv; - }>, - params?: { - cwd?: string; - env?: NodeJS.ProcessEnv; - }, - ) => Array<{ - config: string; - env: NodeJS.ProcessEnv; - }>; - buildFullSuiteVitestRunPlans: ( - args: string[], - cwd?: string, - ) => Array<{ - config: string; - forwardedArgs: string[]; - includePatterns: string[] | null; - watchMode: boolean; - }>; - buildVitestArgs: (args: string[], cwd?: string) => string[]; - buildVitestRunPlans: ( - args: string[], - cwd?: string, - listChangedPaths?: (baseRef: string, cwd: string) => string[], - ) => Array<{ - config: string; - forwardedArgs: string[]; - includePatterns: string[] | null; - watchMode: boolean; - }>; - createVitestRunSpecs: ( - args: string[], - params?: { - baseEnv?: NodeJS.ProcessEnv; - cwd?: string; - tempDir?: string; - }, - ) => Array<{ - config: string; - env: NodeJS.ProcessEnv; - includeFilePath: string | null; - includePatterns: string[] | null; - pnpmArgs: string[]; - watchMode: boolean; - }>; - findUnmatchedExplicitTestTargets: ( - args: string[], - cwd?: string, - ) => Array<{ - target: string; - reason: "glob-matched-no-files" | "path-does-not-exist" | "target-matched-no-test-files"; - includePattern?: string; - }>; - parseTestProjectsArgs: ( - args: string[], - cwd?: string, - ) => { - forwardedArgs: string[]; - targetArgs: string[]; - watchMode: boolean; - }; - resolveChangedTargetArgs: ( - args: string[], - cwd?: string, - listChangedPaths?: (baseRef: string, cwd: string) => string[], - options?: { - cwd?: string; - env?: NodeJS.ProcessEnv; - broad?: boolean; - }, - ) => string[] | null; - resolveChangedTestTargetPlan: ( - changedPaths: string[], - ) => - | { mode: "none"; targets: string[] } - | { mode: "targets"; targets: string[] } - | { mode: "broad"; targets: string[] }; - resolveParallelFullSuiteConcurrency: ( - specCount: number, - env?: NodeJS.ProcessEnv, - hostInfo?: { - cpuCount?: number; - loadAverage1m?: number; - totalMemoryBytes?: number; - freeMemoryBytes?: number; - }, - ) => number; -}; +} = await import("../../scripts/test-projects.test-support.mjs"); const runVitestModulePath = "../../scripts/run-vitest.mjs"; const { resolveVitestCliEntry, resolveVitestNodeArgs } = (await import( diff --git a/test/vitest/vitest.shared.config.ts b/test/vitest/vitest.shared.config.ts index 160280ec5ad..4644ee364f0 100644 --- a/test/vitest/vitest.shared.config.ts +++ b/test/vitest/vitest.shared.config.ts @@ -10,6 +10,10 @@ import { resolveLocalVitestMaxWorkers as resolveLocalVitestMaxWorkersImpl, resolveLocalVitestScheduling as resolveLocalVitestSchedulingImpl, } from "../../scripts/lib/vitest-local-scheduling.mjs"; +import type { + LocalVitestScheduling, + VitestHostInfo, +} from "../../scripts/lib/vitest-local-scheduling.mjs"; import { BUNDLED_PLUGIN_ROOT_DIR, BUNDLED_PLUGIN_TEST_GLOB, @@ -17,19 +21,9 @@ import { import { loadVitestExperimentalConfig } from "./vitest.performance-config.ts"; import { shouldPrintVitestThrottle } from "./vitest.system-load.ts"; -type VitestHostInfo = { - cpuCount?: number; - loadAverage1m?: number; - totalMemoryBytes?: number; -}; - export type OpenClawVitestPool = "forks" | "threads"; -export type LocalVitestScheduling = { - maxWorkers: number; - fileParallelism: boolean; - throttledBySystem: boolean; -}; +export type { LocalVitestScheduling }; export const jsdomOptimizedDeps = { optimizer: { @@ -41,7 +35,7 @@ export const jsdomOptimizedDeps = { }; function detectVitestHostInfo(): Required { - return detectVitestHostInfoImpl() as Required; + return detectVitestHostInfoImpl(); } export function resolveLocalVitestMaxWorkers( @@ -57,7 +51,7 @@ export function resolveLocalVitestScheduling( system: VitestHostInfo = detectVitestHostInfo(), pool: OpenClawVitestPool = resolveDefaultVitestPool(env), ): LocalVitestScheduling { - return resolveLocalVitestSchedulingImpl(env, system, pool) as LocalVitestScheduling; + return resolveLocalVitestSchedulingImpl(env, system, pool); } export function resolveDefaultVitestPool(