mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 12:10:42 +00:00
test(ci): add plugin prerelease suite to CI (#73741)
* test(ci): route plugin prerelease coverage to plugin shard * test(ci): add plugin prerelease suite to CI * fix(ci): preserve pnpm path in plugin prerelease shard * fix(ci): avoid inheriting secrets for plugin prerelease suite
This commit is contained in:
122
scripts/lib/plugin-prerelease-test-plan.mjs
Normal file
122
scripts/lib/plugin-prerelease-test-plan.mjs
Normal file
@@ -0,0 +1,122 @@
|
||||
import { BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS } from "./docker-e2e-scenarios.mjs";
|
||||
|
||||
export const PLUGIN_PRERELEASE_REQUIRED_SURFACES = Object.freeze([
|
||||
"package-artifact",
|
||||
"bundled-lifecycle",
|
||||
"external-plugins",
|
||||
"update-no-op",
|
||||
"channel-runtime-deps",
|
||||
"doctor-fix",
|
||||
"config-round-trip",
|
||||
"gateway-bootstrap",
|
||||
"sdk-compatibility",
|
||||
"status-diagnostics",
|
||||
"live-ish-availability",
|
||||
]);
|
||||
|
||||
const pluginPrereleaseDockerLanes = Object.freeze([
|
||||
{
|
||||
lane: "npm-onboard-channel-agent",
|
||||
surfaces: ["package-artifact", "gateway-bootstrap", "status-diagnostics"],
|
||||
},
|
||||
{
|
||||
lane: "doctor-switch",
|
||||
surfaces: ["package-artifact", "doctor-fix"],
|
||||
},
|
||||
{
|
||||
lane: "update-channel-switch",
|
||||
surfaces: ["package-artifact", "channel-runtime-deps", "update-no-op"],
|
||||
},
|
||||
{
|
||||
lane: "bundled-channel-deps-compat",
|
||||
surfaces: ["package-artifact", "channel-runtime-deps", "gateway-bootstrap"],
|
||||
},
|
||||
{
|
||||
lane: "plugins-offline",
|
||||
surfaces: ["external-plugins", "sdk-compatibility", "status-diagnostics"],
|
||||
},
|
||||
{
|
||||
lane: "plugins",
|
||||
surfaces: ["external-plugins", "sdk-compatibility", "status-diagnostics"],
|
||||
},
|
||||
{
|
||||
lane: "plugin-update",
|
||||
surfaces: ["package-artifact", "update-no-op"],
|
||||
},
|
||||
{
|
||||
lane: "config-reload",
|
||||
surfaces: ["config-round-trip", "gateway-bootstrap"],
|
||||
},
|
||||
{
|
||||
lane: "gateway-network",
|
||||
surfaces: ["gateway-bootstrap", "status-diagnostics"],
|
||||
},
|
||||
{
|
||||
lane: "mcp-channels",
|
||||
surfaces: ["gateway-bootstrap", "status-diagnostics"],
|
||||
},
|
||||
{
|
||||
lane: "cron-mcp-cleanup",
|
||||
surfaces: ["gateway-bootstrap", "status-diagnostics"],
|
||||
},
|
||||
...Array.from({ length: BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS }, (_, index) => ({
|
||||
lane: `bundled-plugin-install-uninstall-${index}`,
|
||||
surfaces: ["bundled-lifecycle", "package-artifact", "status-diagnostics"],
|
||||
})),
|
||||
]);
|
||||
|
||||
const staticChecks = Object.freeze([
|
||||
{
|
||||
check: "test:extensions:package-boundary:compile",
|
||||
checkName: "checks-plugin-prerelease-package-boundary-compile",
|
||||
command: "pnpm run test:extensions:package-boundary:compile",
|
||||
surfaces: ["package-artifact", "sdk-compatibility"],
|
||||
},
|
||||
{
|
||||
check: "test:extensions:package-boundary:canary",
|
||||
checkName: "checks-plugin-prerelease-package-boundary-canary",
|
||||
command: "pnpm run test:extensions:package-boundary:canary",
|
||||
surfaces: ["package-artifact", "sdk-compatibility"],
|
||||
},
|
||||
{
|
||||
check: "live-ish-availability",
|
||||
checkName: "checks-plugin-prerelease-live-ish-availability",
|
||||
command: "node scripts/plugin-prerelease-liveish-matrix.mjs",
|
||||
surfaces: ["live-ish-availability"],
|
||||
},
|
||||
]);
|
||||
|
||||
function coveredSurfaces(entries) {
|
||||
return [
|
||||
...new Set(
|
||||
entries
|
||||
.flatMap((entry) => entry.surfaces)
|
||||
.filter((surface) => typeof surface === "string" && surface.length > 0),
|
||||
),
|
||||
].toSorted((a, b) => a.localeCompare(b));
|
||||
}
|
||||
|
||||
export function createPluginPrereleaseTestPlan() {
|
||||
const dockerLanes = pluginPrereleaseDockerLanes.map((entry) => entry.lane);
|
||||
const allEntries = [...pluginPrereleaseDockerLanes, ...staticChecks];
|
||||
return {
|
||||
dockerLanes,
|
||||
staticChecks: staticChecks.map((entry) => ({
|
||||
check: entry.check,
|
||||
checkName: entry.checkName,
|
||||
command: entry.command,
|
||||
surfaces: entry.surfaces.slice(),
|
||||
})),
|
||||
surfaces: coveredSurfaces(allEntries),
|
||||
};
|
||||
}
|
||||
|
||||
export function assertPluginPrereleaseTestPlanComplete(plan = createPluginPrereleaseTestPlan()) {
|
||||
const missing = PLUGIN_PRERELEASE_REQUIRED_SURFACES.filter(
|
||||
(surface) => !plan.surfaces.includes(surface),
|
||||
);
|
||||
if (missing.length > 0) {
|
||||
throw new Error(`Plugin prerelease test plan is missing surfaces: ${missing.join(", ")}`);
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
54
scripts/plugin-prerelease-liveish-matrix.mjs
Normal file
54
scripts/plugin-prerelease-liveish-matrix.mjs
Normal file
@@ -0,0 +1,54 @@
|
||||
const LIVEISH_INPUTS = Object.freeze([
|
||||
{
|
||||
probe: "provider-openai",
|
||||
env: ["OPENAI_API_KEY", "OPENAI_BASE_URL"],
|
||||
},
|
||||
{
|
||||
probe: "provider-anthropic",
|
||||
env: ["ANTHROPIC_API_KEY", "ANTHROPIC_API_TOKEN"],
|
||||
},
|
||||
{
|
||||
probe: "provider-mistral",
|
||||
env: ["MISTRAL_API_KEY"],
|
||||
},
|
||||
{
|
||||
probe: "provider-openrouter",
|
||||
env: ["OPENROUTER_API_KEY"],
|
||||
},
|
||||
{
|
||||
probe: "channel-telegram",
|
||||
env: ["TELEGRAM_BOT_TOKEN", "OPENCLAW_TELEGRAM_BOT_TOKEN"],
|
||||
},
|
||||
{
|
||||
probe: "channel-discord",
|
||||
env: ["DISCORD_TOKEN", "OPENCLAW_DISCORD_TOKEN"],
|
||||
},
|
||||
{
|
||||
probe: "channel-slack",
|
||||
env: ["SLACK_BOT_TOKEN", "OPENCLAW_SLACK_BOT_TOKEN"],
|
||||
},
|
||||
{
|
||||
probe: "channel-whatsapp",
|
||||
env: ["WHATSAPP_ACCESS_TOKEN", "OPENCLAW_WHATSAPP_ACCESS_TOKEN"],
|
||||
},
|
||||
]);
|
||||
|
||||
function hasValue(name) {
|
||||
return typeof process.env[name] === "string" && process.env[name].trim().length > 0;
|
||||
}
|
||||
|
||||
const rows = LIVEISH_INPUTS.map((entry) => ({
|
||||
available: entry.env.some(hasValue),
|
||||
env: entry.env,
|
||||
probe: entry.probe,
|
||||
}));
|
||||
|
||||
console.log("Plugin prerelease live-ish availability matrix:");
|
||||
for (const row of rows) {
|
||||
const status = row.available ? "present" : "missing";
|
||||
console.log(`- ${row.probe}: ${status} (${row.env.join(", ")})`);
|
||||
}
|
||||
|
||||
if (!rows.some((row) => row.available)) {
|
||||
console.log("No live-ish credentials present; skipping external probes by design.");
|
||||
}
|
||||
@@ -247,7 +247,15 @@ const TOOLING_SOURCE_TEST_TARGETS = new Map([
|
||||
["scripts/lib/extension-test-plan.mjs", ["test/scripts/test-extension.test.ts"]],
|
||||
["scripts/lib/vitest-batch-runner.mjs", ["test/scripts/test-extension.test.ts"]],
|
||||
["scripts/lib/ci-node-test-plan.mjs", ["test/scripts/ci-node-test-plan.test.ts"]],
|
||||
[
|
||||
"scripts/lib/plugin-prerelease-test-plan.mjs",
|
||||
["test/scripts/plugin-prerelease-test-plan.test.ts"],
|
||||
],
|
||||
["scripts/lib/vitest-shard-timings.mjs", ["test/scripts/vitest-shard-timings.test.ts"]],
|
||||
[
|
||||
"scripts/plugin-prerelease-liveish-matrix.mjs",
|
||||
["test/scripts/plugin-prerelease-test-plan.test.ts"],
|
||||
],
|
||||
["scripts/test-projects.mjs", ["test/scripts/test-projects.test.ts"]],
|
||||
["scripts/test-projects.test-support.d.mts", ["test/scripts/test-projects.test.ts"]],
|
||||
["scripts/test-projects.test-support.mjs", ["test/scripts/test-projects.test.ts"]],
|
||||
@@ -258,6 +266,10 @@ const TOOLING_TEST_TARGETS = new Map([
|
||||
["test/scripts/changed-lanes.test.ts", ["test/scripts/changed-lanes.test.ts"]],
|
||||
["test/scripts/live-docker-stage.test.ts", ["test/scripts/live-docker-stage.test.ts"]],
|
||||
["test/scripts/openclaw-test-state.test.ts", ["test/scripts/openclaw-test-state.test.ts"]],
|
||||
[
|
||||
"test/scripts/plugin-prerelease-test-plan.test.ts",
|
||||
["test/scripts/plugin-prerelease-test-plan.test.ts"],
|
||||
],
|
||||
["test/scripts/test-projects.test.ts", ["test/scripts/test-projects.test.ts"]],
|
||||
["test/scripts/testbox-sync-sanity.test.ts", ["test/scripts/testbox-sync-sanity.test.ts"]],
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user