Skip to content

Commit f1401b2

Browse files
committed
perf(ci): isolate Docker tooling tests
1 parent 0c4fc0a commit f1401b2

13 files changed

Lines changed: 149 additions & 14 deletions

scripts/lib/ci-node-test-plan.mjs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,24 @@ const SPLIT_NODE_SHARDS = new Map([
717717
],
718718
],
719719
["core-unit-security", []],
720+
[
721+
"core-tooling",
722+
[
723+
{
724+
shardName: "core-tooling",
725+
configs: [
726+
"test/vitest/vitest.tooling.config.ts",
727+
"test/vitest/vitest.tooling-isolated.config.ts",
728+
],
729+
requiresDist: false,
730+
},
731+
{
732+
shardName: "core-tooling-docker",
733+
configs: ["test/vitest/vitest.tooling-docker.config.ts"],
734+
requiresDist: false,
735+
},
736+
],
737+
],
720738
[
721739
"core-unit-support",
722740
[

scripts/run-vitest.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const VITEST_NO_OUTPUT_TIMEOUT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS";
2929
const VITEST_NO_OUTPUT_HEARTBEAT_ENV_KEY = "OPENCLAW_VITEST_NO_OUTPUT_HEARTBEAT_MS";
3030
const UI_VITEST_CONFIG = "test/vitest/vitest.ui.config.ts";
3131
const UNIT_UI_VITEST_CONFIG = "test/vitest/vitest.unit-ui.config.ts";
32+
const TOOLING_DOCKER_VITEST_CONFIG = "test/vitest/vitest.tooling-docker.config.ts";
3233
const TOOLING_VITEST_CONFIG = "test/vitest/vitest.tooling.config.ts";
3334
const GATEWAY_VITEST_CONFIG = "test/vitest/vitest.gateway.config.ts";
3435
const LONG_RUNNING_VITEST_CONFIGS = new Set([
@@ -40,6 +41,7 @@ const LONG_RUNNING_VITEST_CONFIGS = new Set([
4041
]);
4142
const TOOLING_EXCLUDED_TESTS = new Set([
4243
...boundaryTestFiles,
44+
"test/scripts/docker-build-helper.test.ts",
4345
"test/scripts/openclaw-e2e-instance.test.ts",
4446
]);
4547
const EXPLICIT_FILE_TARGET_RE = /\.(?:[cm]?[jt]sx?)$/u;
@@ -677,6 +679,10 @@ function isToolingTestTarget(target) {
677679
);
678680
}
679681

682+
function isToolingDockerTestTarget(target) {
683+
return target === "test/scripts/docker-build-helper.test.ts";
684+
}
685+
680686
/**
681687
* Resolves config defaults and explicit-file handling for wrapper-inferred runs.
682688
*/
@@ -687,6 +693,9 @@ export function resolveImplicitVitestArgs(argv, cwd = process.cwd()) {
687693
const testTargets = argv
688694
.filter((arg) => !arg.startsWith("-") && arg.endsWith(".test.ts"))
689695
.map((arg) => toRepoRelativeArg(arg, cwd));
696+
if (testTargets.length > 0 && testTargets.every(isToolingDockerTestTarget)) {
697+
return withImplicitVitestConfig(argv, TOOLING_DOCKER_VITEST_CONFIG);
698+
}
690699
if (testTargets.length > 0 && testTargets.every(isToolingTestTarget)) {
691700
return withImplicitVitestConfig(argv, TOOLING_VITEST_CONFIG);
692701
}

scripts/test-projects.test-support.mjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,10 @@ const RUNTIME_CONFIG_VITEST_CONFIG = "test/vitest/vitest.runtime-config.config.t
273273
const SECRETS_VITEST_CONFIG = "test/vitest/vitest.secrets.config.ts";
274274
const SHARED_CORE_VITEST_CONFIG = "test/vitest/vitest.shared-core.config.ts";
275275
const TASKS_VITEST_CONFIG = "test/vitest/vitest.tasks.config.ts";
276+
const TOOLING_DOCKER_VITEST_CONFIG = "test/vitest/vitest.tooling-docker.config.ts";
276277
const TOOLING_ISOLATED_VITEST_CONFIG = "test/vitest/vitest.tooling-isolated.config.ts";
277278
const TOOLING_VITEST_CONFIG = "test/vitest/vitest.tooling.config.ts";
279+
const TOOLING_DOCKER_TEST_TARGET = "test/scripts/docker-build-helper.test.ts";
278280
const TOOLING_ISOLATED_TEST_TARGET = "test/scripts/openclaw-e2e-instance.test.ts";
279281
const TUI_VITEST_CONFIG = "test/vitest/vitest.tui.config.ts";
280282
const TUI_PTY_VITEST_CONFIG = "test/vitest/vitest.tui-pty.config.ts";
@@ -367,6 +369,7 @@ const VITEST_CONFIG_BY_KIND = {
367369
secrets: SECRETS_VITEST_CONFIG,
368370
sharedCore: SHARED_CORE_VITEST_CONFIG,
369371
tasks: TASKS_VITEST_CONFIG,
372+
toolingDocker: TOOLING_DOCKER_VITEST_CONFIG,
370373
toolingIsolated: TOOLING_ISOLATED_VITEST_CONFIG,
371374
tooling: TOOLING_VITEST_CONFIG,
372375
tui: TUI_VITEST_CONFIG,
@@ -2011,6 +2014,9 @@ function classifyTarget(arg, cwd) {
20112014
if (relative === TOOLING_ISOLATED_TEST_TARGET) {
20122015
return "toolingIsolated";
20132016
}
2017+
if (relative === TOOLING_DOCKER_TEST_TARGET) {
2018+
return "toolingDocker";
2019+
}
20142020
if (
20152021
relative.startsWith("test/") ||
20162022
relative.startsWith("src/scripts/") ||
@@ -2237,6 +2243,20 @@ export function buildVitestRunPlans(
22372243
groupedTargets.set(kind, current);
22382244
}
22392245
const toolingTargets = groupedTargets.get("tooling") ?? [];
2246+
if (
2247+
!watchMode &&
2248+
toolingTargets.some((targetArg) =>
2249+
includePatternMatchesAnyFile(toScopedIncludePattern(targetArg, cwd), [
2250+
TOOLING_DOCKER_TEST_TARGET,
2251+
]),
2252+
)
2253+
) {
2254+
const current = groupedTargets.get("toolingDocker") ?? [];
2255+
if (!current.includes(TOOLING_DOCKER_TEST_TARGET)) {
2256+
current.push(TOOLING_DOCKER_TEST_TARGET);
2257+
groupedTargets.set("toolingDocker", current);
2258+
}
2259+
}
22402260
if (
22412261
!watchMode &&
22422262
toolingTargets.some((targetArg) =>
@@ -2263,6 +2283,7 @@ export function buildVitestRunPlans(
22632283
"unitFastFakeTimers",
22642284
"default",
22652285
"boundary",
2286+
"toolingDocker",
22662287
"toolingIsolated",
22672288
"tooling",
22682289
"contractsChannelSurface",

test/scripts/ci-node-test-plan.test.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,19 +177,30 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => {
177177
expect(requiresDistShardNames).toEqual(["core-support-boundary"]);
178178
});
179179

180-
it("keeps tooling checks independent from built artifacts", () => {
181-
const toolingShard = createNodeTestShards().find((shard) => shard.shardName === "core-tooling");
180+
it("splits tooling checks independently from built artifacts", () => {
181+
const toolingShards = createNodeTestShards().filter((shard) =>
182+
shard.shardName.startsWith("core-tooling"),
183+
);
182184

183-
expect(toolingShard).toEqual({
184-
checkName: "checks-node-core-tooling",
185-
configs: [
186-
"test/vitest/vitest.tooling.config.ts",
187-
"test/vitest/vitest.tooling-isolated.config.ts",
188-
],
189-
requiresDist: false,
190-
runner: "blacksmith-8vcpu-ubuntu-2404",
191-
shardName: "core-tooling",
192-
});
185+
expect(toolingShards).toEqual([
186+
{
187+
checkName: "checks-node-core-tooling",
188+
configs: [
189+
"test/vitest/vitest.tooling.config.ts",
190+
"test/vitest/vitest.tooling-isolated.config.ts",
191+
],
192+
requiresDist: false,
193+
runner: "blacksmith-8vcpu-ubuntu-2404",
194+
shardName: "core-tooling",
195+
},
196+
{
197+
checkName: "checks-node-core-tooling-docker",
198+
configs: ["test/vitest/vitest.tooling-docker.config.ts"],
199+
requiresDist: false,
200+
runner: "blacksmith-8vcpu-ubuntu-2404",
201+
shardName: "core-tooling-docker",
202+
},
203+
]);
193204
});
194205

195206
it("assigns Blacksmith runners to every core node shard", () => {

test/scripts/run-vitest.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,15 @@ describe("scripts/run-vitest", () => {
180180
]);
181181
});
182182

183+
it("routes explicit Docker helper tests through the Docker tooling config", () => {
184+
expect(resolveImplicitVitestArgs(["run", "test/scripts/docker-build-helper.test.ts"])).toEqual([
185+
"run",
186+
"--config",
187+
"test/vitest/vitest.tooling-docker.config.ts",
188+
"test/scripts/docker-build-helper.test.ts",
189+
]);
190+
});
191+
183192
it("keeps tooling-excluded explicit tests on existing routing", () => {
184193
const argv = ["run", "test/scripts/openclaw-e2e-instance.test.ts"];
185194
expect(resolveImplicitVitestArgs(argv)).toBe(argv);

test/scripts/test-projects.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,11 +835,16 @@ describe("scripts/test-projects changed-target routing", () => {
835835

836836
expect(findUnmatchedExplicitTestTargets(targets)).toEqual([]);
837837
expect(buildVitestRunPlans(targets, process.cwd())).toEqual([
838+
{
839+
config: "test/vitest/vitest.tooling-docker.config.ts",
840+
forwardedArgs: [],
841+
includePatterns: ["test/scripts/docker-build-helper.test.ts"],
842+
watchMode: false,
843+
},
838844
{
839845
config: "test/vitest/vitest.tooling.config.ts",
840846
forwardedArgs: [],
841847
includePatterns: [
842-
"test/scripts/docker-build-helper.test.ts",
843848
"test/scripts/plugin-prerelease-test-plan.test.ts",
844849
"test/scripts/kitchen-sink-rpc-walk.test.ts",
845850
"test/scripts/openclaw-test-state.test.ts",
@@ -911,6 +916,12 @@ describe("scripts/test-projects changed-target routing", () => {
911916

912917
it("includes the isolated tooling shard for broad shell helper targets", () => {
913918
expect(buildVitestRunPlans(["test/scripts"], process.cwd())).toEqual([
919+
{
920+
config: "test/vitest/vitest.tooling-docker.config.ts",
921+
forwardedArgs: [],
922+
includePatterns: ["test/scripts/docker-build-helper.test.ts"],
923+
watchMode: false,
924+
},
914925
{
915926
config: "test/vitest/vitest.tooling-isolated.config.ts",
916927
forwardedArgs: [],
@@ -928,6 +939,12 @@ describe("scripts/test-projects changed-target routing", () => {
928939

929940
it("includes the isolated tooling shard for broad shell helper globs", () => {
930941
expect(buildVitestRunPlans(["test/scripts/*.test.ts"], process.cwd())).toEqual([
942+
{
943+
config: "test/vitest/vitest.tooling-docker.config.ts",
944+
forwardedArgs: [],
945+
includePatterns: ["test/scripts/docker-build-helper.test.ts"],
946+
watchMode: false,
947+
},
931948
{
932949
config: "test/vitest/vitest.tooling-isolated.config.ts",
933950
forwardedArgs: [],
@@ -2271,6 +2288,7 @@ describe("scripts/test-projects full-suite sharding", () => {
22712288
"test/vitest/vitest.unit-support.config.ts",
22722289
"test/vitest/vitest.boundary.config.ts",
22732290
"test/vitest/vitest.tooling.config.ts",
2291+
"test/vitest/vitest.tooling-docker.config.ts",
22742292
"test/vitest/vitest.tooling-isolated.config.ts",
22752293
"test/vitest/vitest.contracts-channel-surface.config.ts",
22762294
"test/vitest/vitest.contracts-channel-config.config.ts",

test/vitest-projects-config.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ describe("projects vitest config", () => {
8585
);
8686
});
8787

88+
it("keeps root watch projects aligned with dedicated tooling shard lanes", () => {
89+
const toolingShard = fullSuiteVitestShards.find(
90+
(shard) => shard.config === "test/vitest/vitest.full-core-tooling.config.ts",
91+
);
92+
93+
expect(toolingShard?.projects).toEqual(
94+
expect.arrayContaining(["test/vitest/vitest.tooling-docker.config.ts"]),
95+
);
96+
expect(rootVitestProjects).toEqual(
97+
expect.arrayContaining(["test/vitest/vitest.tooling-docker.config.ts"]),
98+
);
99+
});
100+
88101
it("disables vite env-file loading for vitest lanes", () => {
89102
expect(baseConfig.envFile).toBe(false);
90103
expect(sharedVitestConfig.envFile).toBe(false);

test/vitest-scoped-config.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ import { createSecretsVitestConfig } from "./vitest/vitest.secrets.config.ts";
6161
import { createSharedCoreVitestConfig } from "./vitest/vitest.shared-core.config.ts";
6262
import { sharedVitestConfig } from "./vitest/vitest.shared.config.ts";
6363
import { createTasksVitestConfig } from "./vitest/vitest.tasks.config.ts";
64+
import {
65+
createToolingDockerVitestConfig,
66+
toolingDockerTestFiles,
67+
} from "./vitest/vitest.tooling-docker.config.ts";
6468
import { createToolingIsolatedVitestConfig } from "./vitest/vitest.tooling-isolated.config.ts";
6569
import { createToolingVitestConfig } from "./vitest/vitest.tooling.config.ts";
6670
import { createTuiVitestConfig } from "./vitest/vitest.tui.config.ts";
@@ -454,6 +458,7 @@ describe("scoped vitest configs", () => {
454458
const defaultAgentsConfig = createAgentsVitestConfig({});
455459
const defaultPluginsConfig = createPluginsVitestConfig({});
456460
const defaultProcessConfig = createProcessVitestConfig({});
461+
const defaultToolingDockerConfig = createToolingDockerVitestConfig({});
457462
const defaultToolingConfig = createToolingVitestConfig({});
458463
const defaultTuiConfig = createTuiVitestConfig({});
459464
const defaultUiConfig = createUiVitestConfig({});
@@ -475,6 +480,7 @@ describe("scoped vitest configs", () => {
475480
defaultAutoReplyCoreConfig,
476481
defaultAutoReplyTopLevelConfig,
477482
defaultAutoReplyReplyConfig,
483+
defaultToolingDockerConfig,
478484
defaultToolingConfig,
479485
]) {
480486
expectThreadedNonIsolatedRunner(config);
@@ -974,10 +980,17 @@ describe("scoped vitest configs", () => {
974980
it("keeps tooling tests in their own lane", () => {
975981
const testConfig = requireTestConfig(defaultToolingConfig);
976982
expect(testConfig.include).toEqual(["test/**/*.test.ts", "src/scripts/**/*.test.ts"]);
983+
expect(testConfig.exclude).toEqual(expect.arrayContaining(toolingDockerTestFiles));
977984
expect(testConfig.exclude).toContain("test/scripts/openclaw-e2e-instance.test.ts");
978985
expect(testConfig.include).not.toContain("src/config/doc-baseline.integration.test.ts");
979986
});
980987

988+
it("keeps Docker helper tooling tests in their own lane", () => {
989+
const testConfig = requireTestConfig(defaultToolingDockerConfig);
990+
expect(testConfig.include).toEqual(toolingDockerTestFiles);
991+
expect(testConfig.fileParallelism).toBe(false);
992+
});
993+
981994
it("runs shell helper tooling tests isolated from shared mocks", () => {
982995
const testConfig = requireTestConfig(createToolingIsolatedVitestConfig({}));
983996
expect(testConfig.include).toEqual(["test/scripts/openclaw-e2e-instance.test.ts"]);

test/vitest/vitest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const rootVitestProjects = [
5050
"test/vitest/vitest.media-understanding.config.ts",
5151
"test/vitest/vitest.shared-core.config.ts",
5252
"test/vitest/vitest.tasks.config.ts",
53+
"test/vitest/vitest.tooling-docker.config.ts",
5354
"test/vitest/vitest.tooling-isolated.config.ts",
5455
"test/vitest/vitest.tooling.config.ts",
5556
"test/vitest/vitest.tui.config.ts",

test/vitest/vitest.scoped-config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ const SCOPED_PROJECT_GROUP_ORDER_BY_NAME = new Map(
150150
"secrets",
151151
"shared-core",
152152
"tasks",
153+
"tooling-docker",
153154
"tooling-isolated",
154155
"tooling",
155156
"tui",

0 commit comments

Comments
 (0)