mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 18:50: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`
|
The bundled-channel runtime-dependency coverage inside `plugins-integrations`
|
||||||
uses the split `bundled-channel-*` and `bundled-channel-update-*` lanes rather
|
uses the split `bundled-channel-*` and `bundled-channel-update-*` lanes rather
|
||||||
than the serial `bundled-channel-deps` lane, so failures produce cheap targeted
|
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
|
## Package Acceptance
|
||||||
|
|
||||||
|
|||||||
@@ -325,6 +325,9 @@ Release Docker coverage includes:
|
|||||||
- OpenWebUI coverage inside the `plugins-integrations` chunk when requested
|
- OpenWebUI coverage inside the `plugins-integrations` chunk when requested
|
||||||
- split bundled-channel dependency lanes inside `plugins-integrations` instead
|
- split bundled-channel dependency lanes inside `plugins-integrations` instead
|
||||||
of the serial all-in-one bundled-channel lane
|
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
|
- live/E2E provider suites and Docker live model coverage when release checks
|
||||||
include live suites
|
include live suites
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// This module turns the scenario catalog plus env-driven inputs into a concrete
|
// This module turns the scenario catalog plus env-driven inputs into a concrete
|
||||||
// lane plan. It intentionally does not define scenario commands.
|
// lane plan. It intentionally does not define scenario commands.
|
||||||
import {
|
import {
|
||||||
|
BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS,
|
||||||
DEFAULT_LIVE_RETRIES,
|
DEFAULT_LIVE_RETRIES,
|
||||||
allReleasePathLanes,
|
allReleasePathLanes,
|
||||||
mainLanes,
|
mainLanes,
|
||||||
@@ -34,14 +35,23 @@ export function parseLaneSelection(raw) {
|
|||||||
if (!raw) {
|
if (!raw) {
|
||||||
return [];
|
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 [
|
return [
|
||||||
...new Set(
|
...new Set(
|
||||||
String(raw)
|
String(raw)
|
||||||
.split(/[,\s]+/u)
|
.split(/[,\s]+/u)
|
||||||
.map((token) => token.trim())
|
.map((token) => token.trim())
|
||||||
.filter(Boolean)
|
.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_CLI_TIMEOUT_MS = 20 * 60 * 1000;
|
||||||
const LIVE_PROFILE_TIMEOUT_MS = 20 * 60 * 1000;
|
const LIVE_PROFILE_TIMEOUT_MS = 20 * 60 * 1000;
|
||||||
const OPENWEBUI_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 = [
|
export const LIVE_RETRY_PATTERNS = [
|
||||||
/529\b/i,
|
/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 = [
|
export const mainLanes = [
|
||||||
liveLane("live-models", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:live-models", {
|
liveLane("live-models", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:live-models", {
|
||||||
providers: ["claude-cli", "codex-cli", "google-gemini-cli"],
|
providers: ["claude-cli", "codex-cli", "google-gemini-cli"],
|
||||||
@@ -215,14 +229,7 @@ export const mainLanes = [
|
|||||||
resources: ["npm", "service"],
|
resources: ["npm", "service"],
|
||||||
weight: 6,
|
weight: 6,
|
||||||
}),
|
}),
|
||||||
lane(
|
...bundledPluginInstallUninstallLanes,
|
||||||
"bundled-plugin-install-uninstall",
|
|
||||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:bundled-plugin-install-uninstall",
|
|
||||||
{
|
|
||||||
resources: ["npm"],
|
|
||||||
weight: 4,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
lane(
|
lane(
|
||||||
"plugins-offline",
|
"plugins-offline",
|
||||||
"OPENCLAW_PLUGINS_E2E_CLAWHUB=0 OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugins",
|
"OPENCLAW_PLUGINS_E2E_CLAWHUB=0 OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugins",
|
||||||
@@ -395,14 +402,7 @@ const releasePathChunks = {
|
|||||||
resources: ["npm", "service"],
|
resources: ["npm", "service"],
|
||||||
weight: 6,
|
weight: 6,
|
||||||
}),
|
}),
|
||||||
lane(
|
...bundledPluginInstallUninstallLanes,
|
||||||
"bundled-plugin-install-uninstall",
|
|
||||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:bundled-plugin-install-uninstall",
|
|
||||||
{
|
|
||||||
resources: ["npm"],
|
|
||||||
weight: 4,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
npmLane("plugin-update", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugin-update"),
|
npmLane("plugin-update", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugin-update"),
|
||||||
...bundledScenarioLanes,
|
...bundledScenarioLanes,
|
||||||
serviceLane(
|
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("mcp-channels");
|
||||||
expect(plan.lanes.map((lane) => lane.name)).toContain("bundled-channel-feishu");
|
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-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("bundled-channel-deps");
|
||||||
expect(plan.lanes.map((lane) => lane.name)).not.toContain("openwebui");
|
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", () => {
|
it("maps bundled plugin install/uninstall to package-backed shards", () => {
|
||||||
const plan = planFor({ selectedLaneNames: ["bundled-plugin-install-uninstall"] });
|
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({
|
expect.objectContaining({
|
||||||
|
command: expect.stringContaining("OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=0"),
|
||||||
imageKind: "functional",
|
imageKind: "functional",
|
||||||
live: false,
|
live: false,
|
||||||
name: "bundled-plugin-install-uninstall",
|
name: "bundled-plugin-install-uninstall-0",
|
||||||
resources: expect.arrayContaining(["docker", "npm"]),
|
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({
|
expect(plan.needs).toMatchObject({
|
||||||
functionalImage: true,
|
functionalImage: true,
|
||||||
package: true,
|
package: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user