mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:30:42 +00:00
ci: shard bundled plugin release sweep
This commit is contained in:
@@ -295,7 +295,11 @@ and keeps a standalone `openwebui` chunk only for OpenWebUI-only dispatches.
|
||||
The bundled-channel runtime-dependency coverage inside `plugins-integrations`
|
||||
uses the split `bundled-channel-*` and `bundled-channel-update-*` lanes rather
|
||||
than the serial `bundled-channel-deps` lane, so failures produce cheap targeted
|
||||
reruns for the exact channel/update scenario.
|
||||
reruns for the exact channel/update scenario. The bundled plugin
|
||||
install/uninstall sweep is also split into
|
||||
`bundled-plugin-install-uninstall-0` through
|
||||
`bundled-plugin-install-uninstall-7`; selecting the legacy
|
||||
`bundled-plugin-install-uninstall` lane expands to all eight shards.
|
||||
|
||||
## Package Acceptance
|
||||
|
||||
|
||||
@@ -325,6 +325,9 @@ Release Docker coverage includes:
|
||||
- OpenWebUI coverage inside the `plugins-integrations` chunk when requested
|
||||
- split bundled-channel dependency lanes inside `plugins-integrations` instead
|
||||
of the serial all-in-one bundled-channel lane
|
||||
- split bundled plugin install/uninstall lanes
|
||||
`bundled-plugin-install-uninstall-0` through
|
||||
`bundled-plugin-install-uninstall-7`
|
||||
- live/E2E provider suites and Docker live model coverage when release checks
|
||||
include live suites
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// This module turns the scenario catalog plus env-driven inputs into a concrete
|
||||
// lane plan. It intentionally does not define scenario commands.
|
||||
import {
|
||||
BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS,
|
||||
DEFAULT_LIVE_RETRIES,
|
||||
allReleasePathLanes,
|
||||
mainLanes,
|
||||
@@ -34,14 +35,23 @@ export function parseLaneSelection(raw) {
|
||||
if (!raw) {
|
||||
return [];
|
||||
}
|
||||
const laneAliases = new Map([["bundled-channel-deps", "bundled-channel-deps-compat"]]);
|
||||
const laneAliases = new Map([
|
||||
["bundled-channel-deps", ["bundled-channel-deps-compat"]],
|
||||
[
|
||||
"bundled-plugin-install-uninstall",
|
||||
Array.from(
|
||||
{ length: BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS },
|
||||
(_, index) => `bundled-plugin-install-uninstall-${index}`,
|
||||
),
|
||||
],
|
||||
]);
|
||||
return [
|
||||
...new Set(
|
||||
String(raw)
|
||||
.split(/[,\s]+/u)
|
||||
.map((token) => token.trim())
|
||||
.filter(Boolean)
|
||||
.map((token) => laneAliases.get(token) ?? token),
|
||||
.flatMap((token) => laneAliases.get(token) ?? [token]),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ const LIVE_ACP_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
const LIVE_CLI_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
const LIVE_PROFILE_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
const OPENWEBUI_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
export const BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS = 8;
|
||||
|
||||
export const LIVE_RETRY_PATTERNS = [
|
||||
/529\b/i,
|
||||
@@ -138,6 +139,19 @@ const bundledScenarioLanes = [
|
||||
),
|
||||
];
|
||||
|
||||
const bundledPluginInstallUninstallLanes = Array.from(
|
||||
{ length: BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS },
|
||||
(_, index) =>
|
||||
lane(
|
||||
`bundled-plugin-install-uninstall-${index}`,
|
||||
`OPENCLAW_BUNDLED_PLUGIN_SWEEP_TOTAL=${BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS} OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=${index} OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:bundled-plugin-install-uninstall`,
|
||||
{
|
||||
resources: ["npm"],
|
||||
weight: 2,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
export const mainLanes = [
|
||||
liveLane("live-models", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:live-models", {
|
||||
providers: ["claude-cli", "codex-cli", "google-gemini-cli"],
|
||||
@@ -215,14 +229,7 @@ export const mainLanes = [
|
||||
resources: ["npm", "service"],
|
||||
weight: 6,
|
||||
}),
|
||||
lane(
|
||||
"bundled-plugin-install-uninstall",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:bundled-plugin-install-uninstall",
|
||||
{
|
||||
resources: ["npm"],
|
||||
weight: 4,
|
||||
},
|
||||
),
|
||||
...bundledPluginInstallUninstallLanes,
|
||||
lane(
|
||||
"plugins-offline",
|
||||
"OPENCLAW_PLUGINS_E2E_CLAWHUB=0 OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugins",
|
||||
@@ -395,14 +402,7 @@ const releasePathChunks = {
|
||||
resources: ["npm", "service"],
|
||||
weight: 6,
|
||||
}),
|
||||
lane(
|
||||
"bundled-plugin-install-uninstall",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:bundled-plugin-install-uninstall",
|
||||
{
|
||||
resources: ["npm"],
|
||||
weight: 4,
|
||||
},
|
||||
),
|
||||
...bundledPluginInstallUninstallLanes,
|
||||
npmLane("plugin-update", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugin-update"),
|
||||
...bundledScenarioLanes,
|
||||
serviceLane(
|
||||
|
||||
@@ -45,6 +45,9 @@ describe("scripts/lib/docker-e2e-plan", () => {
|
||||
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");
|
||||
expect(plan.lanes.map((lane) => lane.name)).toContain("bundled-plugin-install-uninstall-0");
|
||||
expect(plan.lanes.map((lane) => lane.name)).toContain("bundled-plugin-install-uninstall-7");
|
||||
expect(plan.lanes.map((lane) => lane.name)).not.toContain("bundled-plugin-install-uninstall");
|
||||
expect(plan.lanes.map((lane) => lane.name)).not.toContain("bundled-channel-deps");
|
||||
expect(plan.lanes.map((lane) => lane.name)).not.toContain("openwebui");
|
||||
});
|
||||
@@ -111,17 +114,32 @@ describe("scripts/lib/docker-e2e-plan", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("plans bundled plugin install/uninstall as package-backed plugin coverage", () => {
|
||||
const plan = planFor({ selectedLaneNames: ["bundled-plugin-install-uninstall"] });
|
||||
it("maps bundled plugin install/uninstall to package-backed shards", () => {
|
||||
const selectedLaneNames = parseLaneSelection("bundled-plugin-install-uninstall");
|
||||
const plan = planFor({ selectedLaneNames });
|
||||
|
||||
expect(plan.lanes).toEqual([
|
||||
expect(selectedLaneNames).toEqual(
|
||||
Array.from({ length: 8 }, (_, index) => `bundled-plugin-install-uninstall-${index}`),
|
||||
);
|
||||
expect(plan.lanes).toHaveLength(8);
|
||||
expect(plan.lanes[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
command: expect.stringContaining("OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=0"),
|
||||
imageKind: "functional",
|
||||
live: false,
|
||||
name: "bundled-plugin-install-uninstall",
|
||||
name: "bundled-plugin-install-uninstall-0",
|
||||
resources: expect.arrayContaining(["docker", "npm"]),
|
||||
}),
|
||||
]);
|
||||
);
|
||||
expect(plan.lanes[7]).toEqual(
|
||||
expect.objectContaining({
|
||||
command: expect.stringContaining("OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=7"),
|
||||
imageKind: "functional",
|
||||
live: false,
|
||||
name: "bundled-plugin-install-uninstall-7",
|
||||
resources: expect.arrayContaining(["docker", "npm"]),
|
||||
}),
|
||||
);
|
||||
expect(plan.needs).toMatchObject({
|
||||
functionalImage: true,
|
||||
package: true,
|
||||
|
||||
Reference in New Issue
Block a user