ci: shard release live validation

This commit is contained in:
Peter Steinberger
2026-04-27 14:24:00 +01:00
parent f6bda8d36b
commit 2243a68a1d
11 changed files with 324 additions and 13 deletions

View File

@@ -66,6 +66,36 @@ describe("scripts/test-docker-all scheduler", () => {
).toBe(false);
});
it("can co-schedule the split installer provider lanes", () => {
expect(
canStartSchedulerLane(
{
name: "install-e2e-anthropic",
resources: ["npm", "service"],
weight: 3,
},
activePool({
count: 1,
resources: {
docker: 3,
npm: 3,
service: 3,
},
weight: 3,
}),
10,
{
resourceLimits: {
docker: 10,
npm: 10,
service: 7,
},
weightLimit: 10,
},
),
).toBe(true);
});
it("preserves the parallelism count cap", () => {
expect(
canStartSchedulerLane(

View File

@@ -84,7 +84,10 @@ describe("docker build helper", () => {
const scenarios = readFileSync(DOCKER_E2E_SCENARIOS_PATH, "utf8");
expect(scenarios).toContain(
'"OPENCLAW_INSTALL_TAG=beta OPENCLAW_E2E_MODELS=both pnpm test:install:e2e"',
'"OPENCLAW_INSTALL_TAG=beta OPENCLAW_E2E_MODELS=openai OPENCLAW_INSTALL_E2E_IMAGE=openclaw-install-e2e-openai:local pnpm test:install:e2e"',
);
expect(scenarios).toContain(
'"OPENCLAW_INSTALL_TAG=beta OPENCLAW_E2E_MODELS=anthropic OPENCLAW_INSTALL_E2E_IMAGE=openclaw-install-e2e-anthropic:local pnpm test:install:e2e"',
);
});

View File

@@ -41,7 +41,8 @@ describe("scripts/lib/docker-e2e-plan", () => {
package: true,
});
expect(plan.credentials).toEqual(["anthropic", "openai"]);
expect(plan.lanes.map((lane) => lane.name)).toContain("install-e2e");
expect(plan.lanes.map((lane) => lane.name)).toContain("install-e2e-openai");
expect(plan.lanes.map((lane) => lane.name)).toContain("install-e2e-anthropic");
expect(plan.lanes.map((lane) => lane.name)).toContain("mcp-channels");
expect(plan.lanes.map((lane) => lane.name)).toContain("bundled-channel-feishu");
expect(plan.lanes.map((lane) => lane.name)).toContain("bundled-channel-update-acpx");
@@ -166,6 +167,24 @@ describe("scripts/lib/docker-e2e-plan", () => {
]);
});
it("maps installer E2E to provider-specific package install lanes", () => {
const selectedLaneNames = parseLaneSelection("install-e2e");
const plan = planFor({ selectedLaneNames });
expect(selectedLaneNames).toEqual(["install-e2e-openai", "install-e2e-anthropic"]);
expect(plan.lanes).toEqual([
expect.objectContaining({
command: expect.stringContaining("OPENCLAW_E2E_MODELS=openai"),
name: "install-e2e-openai",
}),
expect.objectContaining({
command: expect.stringContaining("OPENCLAW_E2E_MODELS=anthropic"),
name: "install-e2e-anthropic",
}),
]);
expect(plan.credentials).toEqual(["anthropic", "openai"]);
});
it("maps bundled plugin install/uninstall to package-backed shards", () => {
const selectedLaneNames = parseLaneSelection("bundled-plugin-install-uninstall");
const plan = planFor({ selectedLaneNames });

View File

@@ -90,6 +90,19 @@ describe("package artifact reuse", () => {
expect(workflow).not.toContain("cache-to: type=gha,mode=max,scope=docker-e2e");
});
it("shards broad native live tests instead of one serial live-all job", () => {
const workflow = readFileSync(LIVE_E2E_WORKFLOW, "utf8");
expect(workflow).not.toContain("suite_id: live-all");
expect(workflow).not.toContain("command: pnpm test:live\n");
expect(workflow).toContain("suite_id: native-live-src-agents");
expect(workflow).toContain("command: node scripts/test-live-shard.mjs native-live-src-agents");
expect(workflow).toContain("suite_id: native-live-src-gateway");
expect(workflow).toContain("suite_id: native-live-extensions-a-k");
expect(workflow).toContain("suite_id: native-live-extensions-l-z");
expect(workflow).toContain("if: matrix.needs_ffmpeg");
});
it("allows the Telegram lane to run from reusable package acceptance artifacts", () => {
const workflow = readFileSync(NPM_TELEGRAM_WORKFLOW, "utf8");

View File

@@ -0,0 +1,41 @@
import { describe, expect, it } from "vitest";
import {
LIVE_TEST_SHARDS,
collectAllLiveTestFiles,
selectLiveShardFiles,
} from "../../scripts/test-live-shard.mjs";
describe("scripts/test-live-shard", () => {
it("partitions every native live test into exactly one release shard", () => {
const allFiles = collectAllLiveTestFiles();
const selected = LIVE_TEST_SHARDS.flatMap((shard) =>
selectLiveShardFiles(shard, allFiles).map((file) => ({ file, shard })),
);
const selectedFiles = selected.map(({ file }) => file);
expect(allFiles.length).toBeGreaterThan(0);
expect(selectedFiles.toSorted()).toEqual(allFiles);
expect(new Set(selectedFiles).size).toBe(selectedFiles.length);
});
it("keeps media-capable extension and test harness files in their own shards", () => {
const allFiles = collectAllLiveTestFiles();
expect(selectLiveShardFiles("native-live-test", allFiles)).toEqual(
expect.arrayContaining([
"test/image-generation.infer-cli.live.test.ts",
"test/image-generation.runtime.live.test.ts",
]),
);
expect(selectLiveShardFiles("native-live-extensions-l-z", allFiles)).toEqual(
expect.arrayContaining([
"extensions/music-generation-providers.live.test.ts",
"extensions/video-generation-providers.live.test.ts",
]),
);
});
it("rejects unknown shard names", () => {
expect(() => selectLiveShardFiles("native-live-missing")).toThrow(/Unknown live test shard/u);
});
});