From 6261f42ac00de45e2e8f0c60af3d771e1e82a2f8 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 22 Apr 2026 20:47:46 +0100 Subject: [PATCH] ci: merge short auto-reply node shards --- docs/ci.md | 2 +- scripts/lib/ci-node-test-plan.mjs | 39 +++++++++++++------------- test/scripts/ci-node-test-plan.test.ts | 37 ++++++++---------------- 3 files changed, 32 insertions(+), 46 deletions(-) diff --git a/docs/ci.md b/docs/ci.md index 33feda79379..ed10ccf84d5 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -53,7 +53,7 @@ Local changed-lane logic lives in `scripts/changed-lanes.mjs` and is executed by On pushes, the `checks` matrix adds the push-only `compat-node22` lane. On pull requests, that lane is skipped and the matrix stays focused on the normal test/channel lanes. -The slowest Node test families are split or balanced so each job stays small: channel contracts split registry and core coverage into eight weighted shards each, auto-reply reply tests split by prefix group, and agentic gateway/plugin configs are spread across the existing source-only agentic Node jobs instead of waiting on built artifacts. `check-additional` keeps package-boundary compile/canary work together and separates it from runtime topology gateway/architecture work; the boundary guard shard runs its small independent guards concurrently inside one job, and the gateway watch regression uses the minimal `gatewayWatch` build profile instead of rebuilding the full CI artifact sidecar set. +The slowest Node test families are split or balanced so each job stays small: channel contracts split registry and core coverage into eight weighted shards each, auto-reply runs as three balanced workers instead of six tiny workers, and agentic gateway/plugin configs are spread across the existing source-only agentic Node jobs instead of waiting on built artifacts. `check-additional` keeps package-boundary compile/canary work together and separates it from runtime topology gateway/architecture work; the boundary guard shard runs its small independent guards concurrently inside one job, and the gateway watch regression uses the minimal `gatewayWatch` build profile instead of rebuilding the full CI artifact sidecar set. GitHub may mark superseded jobs as `cancelled` when a newer push lands on the same PR or `main` ref. Treat that as CI noise unless the newest run for the same ref is also failing. Aggregate shard checks use `!cancelled() && always()` so they still report normal shard failures but do not queue after the whole workflow has already been superseded. The CI concurrency key is versioned (`CI-v4-*`) so a GitHub-side zombie in an old queue group cannot indefinitely block newer main runs. diff --git a/scripts/lib/ci-node-test-plan.mjs b/scripts/lib/ci-node-test-plan.mjs index a7f4b7afa55..f4b9ab96fbc 100644 --- a/scripts/lib/ci-node-test-plan.mjs +++ b/scripts/lib/ci-node-test-plan.mjs @@ -65,22 +65,25 @@ function createAutoReplyReplySplitShards() { } } - const shardCounts = { - "auto-reply-reply-agent-runner": 1, - "auto-reply-reply-commands": 1, - "auto-reply-reply-dispatch": 1, - "auto-reply-reply-state-routing": 1, + const mergedGroups = { + "auto-reply-reply-agent-dispatch": [ + ...groups["auto-reply-reply-agent-runner"], + ...groups["auto-reply-reply-dispatch"], + ], + "auto-reply-reply-commands-state-routing": [ + ...groups["auto-reply-reply-commands"], + ...groups["auto-reply-reply-state-routing"], + ], }; - return Object.entries(groups).flatMap(([groupName, includePatterns]) => { - const shardCount = shardCounts[groupName] ?? 1; - return Array.from({ length: shardCount }, (_, index) => ({ - shardName: `${groupName}-${String.fromCharCode(97 + index)}`, + return Object.entries(mergedGroups) + .map(([groupName, includePatterns]) => ({ configs: ["test/vitest/vitest.auto-reply-reply.config.ts"], - includePatterns: includePatterns.filter((_, fileIndex) => fileIndex % shardCount === index), + includePatterns, requiresDist: false, - })).filter((shard) => shard.includePatterns.length > 0); - }); + shardName: groupName, + })) + .filter((shard) => shard.includePatterns.length > 0); } const SPLIT_NODE_SHARDS = new Map([ @@ -127,13 +130,11 @@ const SPLIT_NODE_SHARDS = new Map([ "auto-reply", [ { - shardName: "auto-reply-core", - configs: ["test/vitest/vitest.auto-reply-core.config.ts"], - requiresDist: false, - }, - { - shardName: "auto-reply-top-level", - configs: ["test/vitest/vitest.auto-reply-top-level.config.ts"], + shardName: "auto-reply-core-top-level", + configs: [ + "test/vitest/vitest.auto-reply-core.config.ts", + "test/vitest/vitest.auto-reply-top-level.config.ts", + ], requiresDist: false, }, ...createAutoReplyReplySplitShards(), diff --git a/test/scripts/ci-node-test-plan.test.ts b/test/scripts/ci-node-test-plan.test.ts index 0a1a32e9148..bbccd09594a 100644 --- a/test/scripts/ci-node-test-plan.test.ts +++ b/test/scripts/ci-node-test-plan.test.ts @@ -156,7 +156,7 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => { }); }); - it("splits auto-reply into independent core, top-level, and reply subtree shards", () => { + it("splits auto-reply into balanced core/top-level and reply subtree shards", () => { const shards = createNodeTestShards(); const autoReplyShards = shards .filter((shard) => shard.shardName.startsWith("auto-reply")) @@ -169,40 +169,25 @@ describe("scripts/lib/ci-node-test-plan.mjs", () => { expect(autoReplyShards).toEqual([ { - checkName: "checks-node-auto-reply-core", - configs: ["test/vitest/vitest.auto-reply-core.config.ts"], + checkName: "checks-node-auto-reply-core-top-level", + configs: [ + "test/vitest/vitest.auto-reply-core.config.ts", + "test/vitest/vitest.auto-reply-top-level.config.ts", + ], requiresDist: false, - shardName: "auto-reply-core", + shardName: "auto-reply-core-top-level", }, { - checkName: "checks-node-auto-reply-top-level", - configs: ["test/vitest/vitest.auto-reply-top-level.config.ts"], - requiresDist: false, - shardName: "auto-reply-top-level", - }, - { - checkName: "checks-node-auto-reply-reply-agent-runner-a", + checkName: "checks-node-auto-reply-reply-agent-dispatch", configs: ["test/vitest/vitest.auto-reply-reply.config.ts"], requiresDist: false, - shardName: "auto-reply-reply-agent-runner-a", + shardName: "auto-reply-reply-agent-dispatch", }, { - checkName: "checks-node-auto-reply-reply-commands-a", + checkName: "checks-node-auto-reply-reply-commands-state-routing", configs: ["test/vitest/vitest.auto-reply-reply.config.ts"], requiresDist: false, - shardName: "auto-reply-reply-commands-a", - }, - { - checkName: "checks-node-auto-reply-reply-dispatch-a", - configs: ["test/vitest/vitest.auto-reply-reply.config.ts"], - requiresDist: false, - shardName: "auto-reply-reply-dispatch-a", - }, - { - checkName: "checks-node-auto-reply-reply-state-routing-a", - configs: ["test/vitest/vitest.auto-reply-reply.config.ts"], - requiresDist: false, - shardName: "auto-reply-reply-state-routing-a", + shardName: "auto-reply-reply-commands-state-routing", }, ]); });