diff --git a/scripts/test-projects.mjs b/scripts/test-projects.mjs index c76d07e55bd..e818d2d4f31 100644 --- a/scripts/test-projects.mjs +++ b/scripts/test-projects.mjs @@ -7,6 +7,7 @@ import { createVitestRunSpecs, parseTestProjectsArgs, resolveChangedTargetArgs, + shouldUseLocalFullSuiteParallelByDefault, writeVitestIncludeFile, } from "./test-projects.test-support.mjs"; import { @@ -125,10 +126,15 @@ function resolveParallelFullSuiteConcurrency(specCount, env) { if (override !== null) { return Math.min(override, specCount); } + if (env.OPENCLAW_TEST_PROJECTS_SERIAL === "1") { + return 1; + } + if (env.CI === "true" || env.GITHUB_ACTIONS === "true") { + return 1; + } if ( - env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS !== "1" || - env.CI === "true" || - env.GITHUB_ACTIONS === "true" + env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS !== "1" && + !shouldUseLocalFullSuiteParallelByDefault(env) ) { return 1; } diff --git a/scripts/test-projects.test-support.mjs b/scripts/test-projects.test-support.mjs index 85b55c0206d..1392327ebbb 100644 --- a/scripts/test-projects.test-support.mjs +++ b/scripts/test-projects.test-support.mjs @@ -623,7 +623,8 @@ export function buildFullSuiteVitestRunPlans(args, cwd = process.cwd()) { const parallelShardCount = Number.parseInt(process.env.OPENCLAW_TEST_PROJECTS_PARALLEL ?? "", 10); const expandToProjectConfigs = process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS === "1" || - (Number.isFinite(parallelShardCount) && parallelShardCount > 1); + (Number.isFinite(parallelShardCount) && parallelShardCount > 1) || + shouldUseLocalFullSuiteParallelByDefault(process.env); return fullSuiteVitestShards.flatMap((shard) => { if ( process.env.OPENCLAW_TEST_SKIP_FULL_EXTENSIONS_SHARD === "1" && @@ -642,6 +643,12 @@ export function buildFullSuiteVitestRunPlans(args, cwd = process.cwd()) { }); } +export function shouldUseLocalFullSuiteParallelByDefault(env = process.env) { + return ( + env.OPENCLAW_TEST_PROJECTS_SERIAL !== "1" && env.CI !== "true" && env.GITHUB_ACTIONS !== "true" + ); +} + export function createVitestRunSpecs(args, params = {}) { const cwd = params.cwd ?? process.cwd(); const plans = buildVitestRunPlans(args, cwd); diff --git a/test/scripts/test-projects.test.ts b/test/scripts/test-projects.test.ts index 6ada3dc0d51..da3f61d30fb 100644 --- a/test/scripts/test-projects.test.ts +++ b/test/scripts/test-projects.test.ts @@ -196,9 +196,11 @@ describe("scripts/test-projects changed-target routing", () => { describe("scripts/test-projects full-suite sharding", () => { it("splits untargeted runs into fixed core shards and per-extension configs", () => { const previousParallel = process.env.OPENCLAW_TEST_PROJECTS_PARALLEL; + const previousSerial = process.env.OPENCLAW_TEST_PROJECTS_SERIAL; delete process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS; delete process.env.OPENCLAW_TEST_SKIP_FULL_EXTENSIONS_SHARD; delete process.env.OPENCLAW_TEST_PROJECTS_PARALLEL; + process.env.OPENCLAW_TEST_PROJECTS_SERIAL = "1"; try { expect(buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config)).toEqual([ "vitest.full-core-unit-fast.config.ts", @@ -239,13 +241,67 @@ describe("scripts/test-projects full-suite sharding", () => { } else { process.env.OPENCLAW_TEST_PROJECTS_PARALLEL = previousParallel; } + if (previousSerial === undefined) { + delete process.env.OPENCLAW_TEST_PROJECTS_SERIAL; + } else { + process.env.OPENCLAW_TEST_PROJECTS_SERIAL = previousSerial; + } + } + }); + + it("expands untargeted local runs to leaf project configs by default", () => { + const previousLeafShards = process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS; + const previousParallel = process.env.OPENCLAW_TEST_PROJECTS_PARALLEL; + const previousSerial = process.env.OPENCLAW_TEST_PROJECTS_SERIAL; + const previousCi = process.env.CI; + const previousActions = process.env.GITHUB_ACTIONS; + delete process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS; + delete process.env.OPENCLAW_TEST_PROJECTS_PARALLEL; + delete process.env.OPENCLAW_TEST_PROJECTS_SERIAL; + delete process.env.CI; + delete process.env.GITHUB_ACTIONS; + try { + const configs = buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config); + + expect(configs).toContain("vitest.gateway.config.ts"); + expect(configs).toContain("vitest.extension-telegram.config.ts"); + expect(configs).not.toContain("vitest.full-agentic.config.ts"); + expect(configs).not.toContain("vitest.full-core-unit-fast.config.ts"); + } finally { + if (previousLeafShards === undefined) { + delete process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS; + } else { + process.env.OPENCLAW_TEST_PROJECTS_LEAF_SHARDS = previousLeafShards; + } + if (previousParallel === undefined) { + delete process.env.OPENCLAW_TEST_PROJECTS_PARALLEL; + } else { + process.env.OPENCLAW_TEST_PROJECTS_PARALLEL = previousParallel; + } + if (previousSerial === undefined) { + delete process.env.OPENCLAW_TEST_PROJECTS_SERIAL; + } else { + process.env.OPENCLAW_TEST_PROJECTS_SERIAL = previousSerial; + } + if (previousCi === undefined) { + delete process.env.CI; + } else { + process.env.CI = previousCi; + } + if (previousActions === undefined) { + delete process.env.GITHUB_ACTIONS; + } else { + process.env.GITHUB_ACTIONS = previousActions; + } } }); it("can skip the aggregate extension shard when CI runs dedicated extension shards", () => { const previous = process.env.OPENCLAW_TEST_SKIP_FULL_EXTENSIONS_SHARD; const previousParallel = process.env.OPENCLAW_TEST_PROJECTS_PARALLEL; + const previousSerial = process.env.OPENCLAW_TEST_PROJECTS_SERIAL; delete process.env.OPENCLAW_TEST_PROJECTS_PARALLEL; + process.env.OPENCLAW_TEST_PROJECTS_SERIAL = "1"; process.env.OPENCLAW_TEST_SKIP_FULL_EXTENSIONS_SHARD = "1"; try { const configs = buildFullSuiteVitestRunPlans([], process.cwd()).map((plan) => plan.config); @@ -263,6 +319,11 @@ describe("scripts/test-projects full-suite sharding", () => { } else { process.env.OPENCLAW_TEST_PROJECTS_PARALLEL = previousParallel; } + if (previousSerial === undefined) { + delete process.env.OPENCLAW_TEST_PROJECTS_SERIAL; + } else { + process.env.OPENCLAW_TEST_PROJECTS_SERIAL = previousSerial; + } } });