Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
927
scripts/lib/docker-e2e-scenarios.mjs
Normal file
927
scripts/lib/docker-e2e-scenarios.mjs
Normal file
@@ -0,0 +1,927 @@
|
||||
// Docker E2E scenario catalog.
|
||||
// Keep lane names, commands, image kind, timeout, resources, and release chunks
|
||||
// here. Planning and execution live in separate modules.
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
export const DEFAULT_LIVE_RETRIES = 1;
|
||||
const LIVE_DOCKER_DEFAULT_HARNESS_DIR =
|
||||
/[\\/]\\.release-harness[\\/]/u.test(fileURLToPath(import.meta.url)) &&
|
||||
process.env.OPENCLAW_DOCKER_E2E_REPO_ROOT
|
||||
? ".release-harness"
|
||||
: ".";
|
||||
const LIVE_ACP_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
const LIVE_CLI_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
const LIVE_PROFILE_TIMEOUT_MS = 30 * 60 * 1000;
|
||||
const OPENWEBUI_TIMEOUT_MS = 20 * 60 * 1000;
|
||||
const RELEASE_OPENWEBUI_COMMAND =
|
||||
"OPENCLAW_OPENWEBUI_MODEL=openai/gpt-5.4-mini OPENCLAW_OPENWEBUI_PROVIDER_TIMEOUT_SECONDS=300 OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openwebui";
|
||||
export const BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS = 24;
|
||||
const upgradeSurvivorCommand = "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:upgrade-survivor";
|
||||
const rootManagedVpsUpgradeCommand =
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:root-managed-vps-upgrade";
|
||||
const updateRestartAuthCommand =
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:update-restart-auth";
|
||||
const CODEX_HARNESS_API_KEY_ENV = "OPENCLAW_LIVE_CODEX_HARNESS_AUTH=api-key";
|
||||
|
||||
const LIVE_RETRY_PATTERNS = [
|
||||
/529\b/i,
|
||||
/overloaded/i,
|
||||
/capacity/i,
|
||||
/rate.?limit/i,
|
||||
/gateway closed \(1000 normal closure\)/i,
|
||||
/ECONNRESET|ETIMEDOUT|ENOTFOUND/i,
|
||||
];
|
||||
|
||||
function liveDockerScriptCommand(script, envPrefix = "", options = {}) {
|
||||
const prefix = envPrefix ? `${envPrefix} ` : "";
|
||||
const skipBuild = options.skipBuild === false ? "" : "OPENCLAW_SKIP_DOCKER_BUILD=1 ";
|
||||
return `${prefix}${skipBuild}bash -c 'harness="\${OPENCLAW_DOCKER_E2E_TRUSTED_HARNESS_DIR:-${LIVE_DOCKER_DEFAULT_HARNESS_DIR}}"; OPENCLAW_LIVE_DOCKER_REPO_ROOT="\${OPENCLAW_DOCKER_E2E_REPO_ROOT:-$PWD}" bash "$harness/scripts/${script}"'`;
|
||||
}
|
||||
|
||||
function lane(name, command, options = {}) {
|
||||
return {
|
||||
cacheKey: options.cacheKey,
|
||||
command,
|
||||
e2eImageKind:
|
||||
options.e2eImageKind === false
|
||||
? undefined
|
||||
: (options.e2eImageKind ?? (options.live ? undefined : "functional")),
|
||||
estimateSeconds: options.estimateSeconds,
|
||||
live: options.live === true,
|
||||
noOutputTimeoutMs: options.noOutputTimeoutMs,
|
||||
name,
|
||||
needsLiveImage: options.needsLiveImage,
|
||||
retryPatterns: options.retryPatterns ?? [],
|
||||
retries: options.retries ?? 0,
|
||||
resources: options.resources ?? [],
|
||||
stateScenario: options.stateScenario,
|
||||
timeoutMs: options.timeoutMs,
|
||||
weight: options.weight ?? 1,
|
||||
};
|
||||
}
|
||||
|
||||
function liveProviderResource(provider) {
|
||||
if (!provider) {
|
||||
return undefined;
|
||||
}
|
||||
if (provider === "claude-cli" || provider === "claude") {
|
||||
return "live:claude";
|
||||
}
|
||||
if (provider === "codex-cli" || provider === "codex") {
|
||||
return "live:codex";
|
||||
}
|
||||
if (provider === "droid") {
|
||||
return "live:droid";
|
||||
}
|
||||
if (provider === "google-gemini-cli" || provider === "gemini") {
|
||||
return "live:gemini";
|
||||
}
|
||||
if (provider === "opencode") {
|
||||
return "live:opencode";
|
||||
}
|
||||
if (provider === "openai") {
|
||||
return "live:openai";
|
||||
}
|
||||
return `live:${provider}`;
|
||||
}
|
||||
|
||||
function liveProviderResources(options) {
|
||||
const providers = options.providers ?? (options.provider ? [options.provider] : []);
|
||||
return providers.map(liveProviderResource).filter(Boolean);
|
||||
}
|
||||
|
||||
function liveLane(name, command, options = {}) {
|
||||
return lane(name, command, {
|
||||
...options,
|
||||
live: true,
|
||||
needsLiveImage: options.needsLiveImage ?? true,
|
||||
resources: ["live", ...liveProviderResources(options), ...(options.resources ?? [])],
|
||||
retryPatterns: options.retryPatterns ?? LIVE_RETRY_PATTERNS,
|
||||
retries: options.retries ?? DEFAULT_LIVE_RETRIES,
|
||||
weight: options.weight ?? 3,
|
||||
});
|
||||
}
|
||||
|
||||
function npmLane(name, command, options = {}) {
|
||||
return lane(name, command, {
|
||||
...options,
|
||||
e2eImageKind: options.e2eImageKind ?? "bare",
|
||||
resources: ["npm", ...(options.resources ?? [])],
|
||||
weight: options.weight ?? 2,
|
||||
});
|
||||
}
|
||||
|
||||
function serviceLane(name, command, options = {}) {
|
||||
return lane(name, command, {
|
||||
...options,
|
||||
resources: ["service", ...(options.resources ?? [])],
|
||||
weight: options.weight ?? 2,
|
||||
});
|
||||
}
|
||||
|
||||
function createPackageUpdateMaintenanceLanes() {
|
||||
return [
|
||||
npmLane("doctor-switch", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:doctor-switch", {
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
}),
|
||||
npmLane(
|
||||
"update-channel-switch",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:update-channel-switch",
|
||||
{
|
||||
stateScenario: "update-stable",
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
npmLane("skill-install", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:skill-install", {
|
||||
retryPatterns: LIVE_RETRY_PATTERNS,
|
||||
retries: 1,
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 10 * 60 * 1000,
|
||||
weight: 2,
|
||||
}),
|
||||
npmLane("upgrade-survivor", upgradeSurvivorCommand, {
|
||||
stateScenario: "upgrade-survivor",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
npmLane(
|
||||
"published-upgrade-survivor",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:published-upgrade-survivor",
|
||||
{
|
||||
stateScenario: "upgrade-survivor",
|
||||
timeoutMs: 25 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
npmLane("root-managed-vps-upgrade", rootManagedVpsUpgradeCommand, {
|
||||
stateScenario: "upgrade-survivor",
|
||||
timeoutMs: 25 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
npmLane("update-restart-auth", updateRestartAuthCommand, {
|
||||
stateScenario: "upgrade-survivor",
|
||||
timeoutMs: 25 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
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`,
|
||||
{
|
||||
estimateSeconds: 120,
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 1,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
function livePluginToolLane() {
|
||||
return liveLane(
|
||||
"live-plugin-tool",
|
||||
"OPENCLAW_LIVE_PLUGIN_TOOL_TIMEOUT_SECONDS=300 OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:live-plugin-tool",
|
||||
{
|
||||
cacheKey: "plugin-tool",
|
||||
e2eImageKind: "bare",
|
||||
provider: "openai",
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function liveOpenAiChatToolsLane() {
|
||||
return liveLane(
|
||||
"openai-chat-tools",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openai-chat-tools",
|
||||
{
|
||||
e2eImageKind: "functional",
|
||||
needsLiveImage: false,
|
||||
provider: "openai",
|
||||
resources: ["service"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 10 * 60 * 1000,
|
||||
weight: 2,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function liveCodexNpmPluginLane() {
|
||||
return liveLane(
|
||||
"live-codex-npm-plugin",
|
||||
liveDockerScriptCommand("e2e/codex-npm-plugin-live-docker.sh"),
|
||||
{
|
||||
cacheKey: "codex-npm-plugin",
|
||||
e2eImageKind: "bare",
|
||||
provider: "openai",
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function liveMcpCodeModeGatewayLane() {
|
||||
return liveLane(
|
||||
"live-mcp-code-mode-gateway",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:live-mcp-code-mode-gateway",
|
||||
{
|
||||
cacheKey: "mcp-code-mode-gateway",
|
||||
e2eImageKind: "functional",
|
||||
needsLiveImage: false,
|
||||
provider: "openai",
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function kitchenSinkRpcLane() {
|
||||
return serviceLane(
|
||||
"kitchen-sink-rpc",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:kitchen-sink-rpc",
|
||||
{
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 25 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export const mainLanes = [
|
||||
liveLane("live-models", liveDockerScriptCommand("test-live-models-docker.sh"), {
|
||||
providers: ["claude-cli", "google-gemini-cli"],
|
||||
timeoutMs: LIVE_PROFILE_TIMEOUT_MS,
|
||||
weight: 4,
|
||||
}),
|
||||
liveLane(
|
||||
"live-gateway",
|
||||
liveDockerScriptCommand(
|
||||
"test-live-gateway-models-docker.sh",
|
||||
"OPENCLAW_IMAGE=openclaw:local-live-gateway OPENCLAW_DOCKER_BUILD_EXTENSIONS=matrix OPENCLAW_LIVE_GATEWAY_PROVIDERS=claude-cli,google-gemini-cli",
|
||||
{ skipBuild: false },
|
||||
),
|
||||
{
|
||||
providers: ["claude-cli", "google-gemini-cli"],
|
||||
timeoutMs: LIVE_PROFILE_TIMEOUT_MS,
|
||||
weight: 4,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-cli-backend-claude",
|
||||
liveDockerScriptCommand(
|
||||
"test-live-cli-backend-docker.sh",
|
||||
"OPENCLAW_LIVE_CLI_BACKEND_MODEL=claude-cli/claude-sonnet-4-6",
|
||||
),
|
||||
{
|
||||
cacheKey: "cli-backend-claude",
|
||||
provider: "claude-cli",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_CLI_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-cli-backend-gemini",
|
||||
liveDockerScriptCommand(
|
||||
"test-live-cli-backend-docker.sh",
|
||||
"OPENCLAW_LIVE_CLI_BACKEND_ADVISORY=1 OPENCLAW_LIVE_CLI_BACKEND_ALLOW_PROVIDER_SKIP=1 OPENCLAW_LIVE_CLI_BACKEND_MODEL=google-gemini-cli/gemini-3-flash-preview",
|
||||
),
|
||||
{
|
||||
cacheKey: "cli-backend-gemini",
|
||||
provider: "google-gemini-cli",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_CLI_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane("openwebui", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openwebui", {
|
||||
e2eImageKind: "functional",
|
||||
needsLiveImage: false,
|
||||
provider: "openai",
|
||||
resources: ["service"],
|
||||
timeoutMs: OPENWEBUI_TIMEOUT_MS,
|
||||
weight: 5,
|
||||
}),
|
||||
serviceLane("onboard", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:onboard", {
|
||||
stateScenario: "empty",
|
||||
weight: 2,
|
||||
}),
|
||||
npmLane("codex-on-demand", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:codex-on-demand", {
|
||||
resources: ["service"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
}),
|
||||
serviceLane(
|
||||
"codex-media-path",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:codex-media-path",
|
||||
{
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
npmLane(
|
||||
"npm-onboard-channel-agent",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:npm-onboard-channel-agent",
|
||||
{ resources: ["service"], stateScenario: "empty", weight: 3 },
|
||||
),
|
||||
npmLane(
|
||||
"npm-onboard-discord-channel-agent",
|
||||
"OPENCLAW_NPM_ONBOARD_CHANNEL=discord OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:npm-onboard-channel-agent",
|
||||
{ resources: ["service"], stateScenario: "empty", weight: 3 },
|
||||
),
|
||||
npmLane(
|
||||
"npm-onboard-slack-channel-agent",
|
||||
"OPENCLAW_NPM_ONBOARD_CHANNEL=slack OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:npm-onboard-channel-agent",
|
||||
{ resources: ["service"], stateScenario: "empty", weight: 3 },
|
||||
),
|
||||
npmLane(
|
||||
"release-user-journey",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:release-user-journey",
|
||||
{
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 4,
|
||||
},
|
||||
),
|
||||
npmLane(
|
||||
"release-typed-onboarding",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:release-typed-onboarding",
|
||||
{
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
npmLane(
|
||||
"release-media-memory",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:release-media-memory",
|
||||
{
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
npmLane(
|
||||
"release-upgrade-user-journey",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:release-upgrade-user-journey",
|
||||
{
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
weight: 5,
|
||||
},
|
||||
),
|
||||
npmLane(
|
||||
"release-plugin-marketplace",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:release-plugin-marketplace",
|
||||
{
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
serviceLane("gateway-network", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:gateway-network"),
|
||||
serviceLane("browser-cdp-snapshot", "pnpm test:docker:browser-cdp-snapshot", {
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
serviceLane(
|
||||
"agents-delete-shared-workspace",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:agents-delete-shared-workspace",
|
||||
{ stateScenario: "empty" },
|
||||
),
|
||||
serviceLane("mcp-channels", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels", {
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
}),
|
||||
serviceLane(
|
||||
"mcp-code-mode-gateway",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-code-mode-gateway",
|
||||
{
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
lane(
|
||||
"agent-bundle-mcp-tools",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:agent-bundle-mcp-tools",
|
||||
{
|
||||
stateScenario: "empty",
|
||||
},
|
||||
),
|
||||
lane("crestodian-rescue", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:crestodian-rescue", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
lane("crestodian-planner", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:crestodian-planner", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
serviceLane(
|
||||
"cron-mcp-cleanup",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:cron-mcp-cleanup",
|
||||
{ resources: ["npm"], stateScenario: "empty", weight: 3 },
|
||||
),
|
||||
...createPackageUpdateMaintenanceLanes(),
|
||||
npmLane("update-migration", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:update-migration", {
|
||||
stateScenario: "upgrade-survivor",
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
lane("plugins", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugins", {
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
weight: 6,
|
||||
}),
|
||||
lane("kitchen-sink-plugin", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:kitchen-sink-plugin", {
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
}),
|
||||
kitchenSinkRpcLane(),
|
||||
...bundledPluginInstallUninstallLanes,
|
||||
lane(
|
||||
"plugins-offline",
|
||||
"OPENCLAW_PLUGINS_E2E_CLAWHUB=0 OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugins",
|
||||
{
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
weight: 6,
|
||||
},
|
||||
),
|
||||
npmLane("plugin-update", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugin-update", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
npmLane(
|
||||
"update-corrupt-plugin",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:update-corrupt-plugin",
|
||||
{
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
npmLane(
|
||||
"plugin-lifecycle-matrix",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugin-lifecycle-matrix",
|
||||
{
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 12 * 60 * 1000,
|
||||
},
|
||||
),
|
||||
serviceLane("config-reload", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:config-reload", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
npmLane("multi-node-update", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:multi-node-update", {
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 15 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
lane("openai-image-auth", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openai-image-auth", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
lane(
|
||||
"crestodian-first-run",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:crestodian-first-run",
|
||||
{ stateScenario: "empty" },
|
||||
),
|
||||
lane(
|
||||
"session-runtime-context",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:session-runtime-context",
|
||||
),
|
||||
lane(
|
||||
"plugin-binding-command-escape",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=0 pnpm test:docker:plugin-binding-command-escape",
|
||||
{
|
||||
e2eImageKind: false,
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
},
|
||||
),
|
||||
lane("commitments-safety", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:commitments-safety", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
liveLane("npm-telegram-live", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:npm-telegram-live", {
|
||||
e2eImageKind: "bare",
|
||||
provider: "openai",
|
||||
resources: ["live:telegram", "npm", "service"],
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
lane("qr", "pnpm test:docker:qr"),
|
||||
];
|
||||
|
||||
export const tailLanes = [
|
||||
serviceLane(
|
||||
"openai-web-search-minimal",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openai-web-search-minimal",
|
||||
{ stateScenario: "empty", timeoutMs: 8 * 60 * 1000 },
|
||||
),
|
||||
liveLane(
|
||||
"live-codex-harness",
|
||||
liveDockerScriptCommand("test-live-codex-harness-docker.sh", CODEX_HARNESS_API_KEY_ENV),
|
||||
{
|
||||
cacheKey: "codex-harness",
|
||||
provider: "openai",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-codex-media-path",
|
||||
liveDockerScriptCommand(
|
||||
"test-live-codex-harness-docker.sh",
|
||||
"OPENCLAW_LIVE_CODEX_HARNESS_AUTH=api-key OPENCLAW_LIVE_CODEX_HARNESS_CHAT_IMAGE_PROBE=1 OPENCLAW_LIVE_CODEX_HARNESS_IMAGE_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_MCP_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_SUBAGENT_PROBE=0 OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=0",
|
||||
),
|
||||
{
|
||||
cacheKey: "codex-harness",
|
||||
provider: "openai",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-subagent-announce",
|
||||
liveDockerScriptCommand("test-live-subagent-announce-docker.sh"),
|
||||
{
|
||||
cacheKey: "subagent-announce",
|
||||
provider: "openai",
|
||||
resources: ["npm"],
|
||||
timeoutMs: 25 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-codex-bind",
|
||||
liveDockerScriptCommand(
|
||||
"test-live-codex-harness-docker.sh",
|
||||
`${CODEX_HARNESS_API_KEY_ENV} OPENCLAW_LIVE_CODEX_BIND=1 OPENCLAW_LIVE_CODEX_TEST_FILES=src/gateway/gateway-codex-bind.live.test.ts`,
|
||||
),
|
||||
{
|
||||
cacheKey: "codex-harness",
|
||||
provider: "openai",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveCodexNpmPluginLane(),
|
||||
liveMcpCodeModeGatewayLane(),
|
||||
livePluginToolLane(),
|
||||
liveLane(
|
||||
"live-acp-bind-claude",
|
||||
liveDockerScriptCommand("test-live-acp-bind-docker.sh", "OPENCLAW_LIVE_ACP_BIND_AGENT=claude"),
|
||||
{
|
||||
cacheKey: "acp-bind-claude",
|
||||
provider: "claude-cli",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-acp-bind-codex",
|
||||
liveDockerScriptCommand("test-live-acp-bind-docker.sh", "OPENCLAW_LIVE_ACP_BIND_AGENT=codex"),
|
||||
{
|
||||
cacheKey: "acp-bind-codex",
|
||||
provider: "codex-cli",
|
||||
resources: ["live:openai", "npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-acp-bind-droid",
|
||||
liveDockerScriptCommand(
|
||||
"test-live-acp-bind-docker.sh",
|
||||
"OPENCLAW_LIVE_ACP_BIND_AGENT=droid OPENCLAW_LIVE_ACP_BIND_REQUIRE_TRANSCRIPT=1",
|
||||
),
|
||||
{
|
||||
cacheKey: "acp-bind-droid",
|
||||
provider: "droid",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-acp-bind-gemini",
|
||||
liveDockerScriptCommand("test-live-acp-bind-docker.sh", "OPENCLAW_LIVE_ACP_BIND_AGENT=gemini"),
|
||||
{
|
||||
cacheKey: "acp-bind-gemini",
|
||||
provider: "google-gemini-cli",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveLane(
|
||||
"live-acp-bind-opencode",
|
||||
liveDockerScriptCommand(
|
||||
"test-live-acp-bind-docker.sh",
|
||||
"OPENCLAW_LIVE_ACP_BIND_AGENT=opencode OPENCLAW_LIVE_ACP_BIND_REQUIRE_TRANSCRIPT=1",
|
||||
),
|
||||
{
|
||||
cacheKey: "acp-bind-opencode",
|
||||
provider: "opencode",
|
||||
resources: ["npm"],
|
||||
timeoutMs: LIVE_ACP_TIMEOUT_MS,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
const releasePathPluginRuntimeLanes = [
|
||||
lane("plugins", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugins", {
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
weight: 6,
|
||||
}),
|
||||
...bundledPluginInstallUninstallLanes,
|
||||
serviceLane(
|
||||
"cron-mcp-cleanup",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:cron-mcp-cleanup",
|
||||
{
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
kitchenSinkRpcLane(),
|
||||
serviceLane(
|
||||
"openai-web-search-minimal",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openai-web-search-minimal",
|
||||
{ stateScenario: "empty", timeoutMs: 8 * 60 * 1000 },
|
||||
),
|
||||
livePluginToolLane(),
|
||||
];
|
||||
|
||||
const releasePathPluginRuntimePluginLanes = [
|
||||
lane("plugins", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugins", {
|
||||
resources: ["npm", "service"],
|
||||
stateScenario: "empty",
|
||||
weight: 6,
|
||||
}),
|
||||
];
|
||||
|
||||
const releasePathPluginRuntimeServiceLanes = [
|
||||
serviceLane(
|
||||
"cron-mcp-cleanup",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:cron-mcp-cleanup",
|
||||
{
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
kitchenSinkRpcLane(),
|
||||
serviceLane(
|
||||
"openai-web-search-minimal",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openai-web-search-minimal",
|
||||
{ stateScenario: "empty", timeoutMs: 8 * 60 * 1000 },
|
||||
),
|
||||
livePluginToolLane(),
|
||||
];
|
||||
|
||||
const releasePathPluginRuntimeCoreLanes = [
|
||||
...releasePathPluginRuntimePluginLanes,
|
||||
...releasePathPluginRuntimeServiceLanes,
|
||||
];
|
||||
|
||||
const releasePathBundledChannelLanes = [
|
||||
npmLane("plugin-update", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:plugin-update", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
];
|
||||
|
||||
const releasePathPackageInstallOpenAiLanes = [
|
||||
liveLane(
|
||||
"install-e2e-openai",
|
||||
"OPENCLAW_INSTALL_TAG=beta OPENCLAW_E2E_MODELS=openai OPENCLAW_INSTALL_E2E_IMAGE=openclaw-install-e2e-openai:local OPENCLAW_INSTALL_E2E_AGENT_TOOL_SMOKE=0 OPENCLAW_INSTALL_E2E_OPENAI_MODEL=openai/gpt-5.4-mini OPENCLAW_INSTALL_E2E_AGENT_TURN_TIMEOUT_SECONDS=120 OPENCLAW_INSTALL_E2E_OPENAI_PROVIDER_TIMEOUT_SECONDS=120 pnpm test:install:e2e",
|
||||
{
|
||||
e2eImageKind: "bare",
|
||||
needsLiveImage: false,
|
||||
provider: "openai",
|
||||
resources: ["npm", "service"],
|
||||
timeoutMs: 15 * 60 * 1000,
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
liveOpenAiChatToolsLane(),
|
||||
liveCodexNpmPluginLane(),
|
||||
npmLane("codex-on-demand", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:codex-on-demand", {
|
||||
resources: ["service"],
|
||||
stateScenario: "empty",
|
||||
timeoutMs: 30 * 60 * 1000,
|
||||
weight: 3,
|
||||
}),
|
||||
];
|
||||
|
||||
const releasePathPackageInstallAnthropicLanes = [
|
||||
liveLane(
|
||||
"install-e2e-anthropic",
|
||||
"OPENCLAW_INSTALL_TAG=beta OPENCLAW_E2E_MODELS=anthropic OPENCLAW_INSTALL_E2E_IMAGE=openclaw-install-e2e-anthropic:local pnpm test:install:e2e",
|
||||
{
|
||||
e2eImageKind: "bare",
|
||||
needsLiveImage: false,
|
||||
provider: "claude",
|
||||
resources: ["npm", "service"],
|
||||
weight: 3,
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
const releasePathPackageUpdateCoreLanes = [
|
||||
npmLane(
|
||||
"npm-onboard-channel-agent",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:npm-onboard-channel-agent",
|
||||
{ resources: ["service"], stateScenario: "empty", weight: 3 },
|
||||
),
|
||||
npmLane(
|
||||
"npm-onboard-discord-channel-agent",
|
||||
"OPENCLAW_NPM_ONBOARD_CHANNEL=discord OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:npm-onboard-channel-agent",
|
||||
{ resources: ["service"], stateScenario: "empty", weight: 3 },
|
||||
),
|
||||
npmLane(
|
||||
"npm-onboard-slack-channel-agent",
|
||||
"OPENCLAW_NPM_ONBOARD_CHANNEL=slack OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:npm-onboard-channel-agent",
|
||||
{ resources: ["service"], stateScenario: "empty", weight: 3 },
|
||||
),
|
||||
...createPackageUpdateMaintenanceLanes(),
|
||||
];
|
||||
|
||||
const primaryReleasePathChunks = {
|
||||
core: [
|
||||
lane("qr", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:qr"),
|
||||
serviceLane("onboard", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:onboard", {
|
||||
stateScenario: "empty",
|
||||
weight: 2,
|
||||
}),
|
||||
serviceLane("gateway-network", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:gateway-network"),
|
||||
serviceLane("config-reload", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:config-reload", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
lane(
|
||||
"session-runtime-context",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:session-runtime-context",
|
||||
),
|
||||
lane(
|
||||
"plugin-binding-command-escape",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=0 pnpm test:docker:plugin-binding-command-escape",
|
||||
{
|
||||
e2eImageKind: false,
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
},
|
||||
),
|
||||
lane("commitments-safety", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:commitments-safety", {
|
||||
stateScenario: "empty",
|
||||
}),
|
||||
lane(
|
||||
"agent-bundle-mcp-tools",
|
||||
"OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:agent-bundle-mcp-tools",
|
||||
{ stateScenario: "empty" },
|
||||
),
|
||||
serviceLane("mcp-channels", "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:mcp-channels", {
|
||||
resources: ["npm"],
|
||||
stateScenario: "empty",
|
||||
weight: 3,
|
||||
}),
|
||||
],
|
||||
"package-update-openai": releasePathPackageInstallOpenAiLanes,
|
||||
"package-update-anthropic": releasePathPackageInstallAnthropicLanes,
|
||||
"package-update-core": releasePathPackageUpdateCoreLanes,
|
||||
"plugins-runtime-plugins": releasePathPluginRuntimePluginLanes,
|
||||
"plugins-runtime-services": releasePathPluginRuntimeServiceLanes,
|
||||
"plugins-runtime-install-a": bundledPluginInstallUninstallLanes.slice(0, 3),
|
||||
"plugins-runtime-install-b": bundledPluginInstallUninstallLanes.slice(3, 6),
|
||||
"plugins-runtime-install-c": bundledPluginInstallUninstallLanes.slice(6, 9),
|
||||
"plugins-runtime-install-d": bundledPluginInstallUninstallLanes.slice(9, 12),
|
||||
"plugins-runtime-install-e": bundledPluginInstallUninstallLanes.slice(12, 15),
|
||||
"plugins-runtime-install-f": bundledPluginInstallUninstallLanes.slice(15, 18),
|
||||
"plugins-runtime-install-g": bundledPluginInstallUninstallLanes.slice(18, 21),
|
||||
"plugins-runtime-install-h": bundledPluginInstallUninstallLanes.slice(21),
|
||||
openwebui: [],
|
||||
};
|
||||
|
||||
const primaryReleasePathChunkProfiles = {
|
||||
core: ["stable", "full"],
|
||||
"package-update-openai": ["beta", "stable", "full"],
|
||||
"package-update-anthropic": ["beta", "stable", "full"],
|
||||
"package-update-core": ["beta", "stable", "full"],
|
||||
"plugins-runtime-plugins": ["stable", "full"],
|
||||
"plugins-runtime-services": ["stable", "full"],
|
||||
"plugins-runtime-install-a": ["stable", "full"],
|
||||
"plugins-runtime-install-b": ["stable", "full"],
|
||||
"plugins-runtime-install-c": ["stable", "full"],
|
||||
"plugins-runtime-install-d": ["stable", "full"],
|
||||
"plugins-runtime-install-e": ["stable", "full"],
|
||||
"plugins-runtime-install-f": ["stable", "full"],
|
||||
"plugins-runtime-install-g": ["stable", "full"],
|
||||
"plugins-runtime-install-h": ["stable", "full"],
|
||||
openwebui: ["stable", "full"],
|
||||
};
|
||||
|
||||
const legacyReleasePathChunks = {
|
||||
"package-update": [
|
||||
...releasePathPackageInstallOpenAiLanes,
|
||||
...releasePathPackageInstallAnthropicLanes,
|
||||
...releasePathPackageUpdateCoreLanes,
|
||||
],
|
||||
"plugins-runtime-core": releasePathPluginRuntimeCoreLanes,
|
||||
"plugins-runtime": releasePathPluginRuntimeLanes,
|
||||
"plugins-integrations": [...releasePathPluginRuntimeLanes, ...releasePathBundledChannelLanes],
|
||||
"bundled-channels": releasePathBundledChannelLanes,
|
||||
};
|
||||
|
||||
export function normalizeReleaseProfile(raw) {
|
||||
const profile = String(raw ?? "stable").trim() || "stable";
|
||||
if (profile === "minimum") {
|
||||
return "beta";
|
||||
}
|
||||
if (profile === "beta" || profile === "stable" || profile === "full") {
|
||||
return profile;
|
||||
}
|
||||
throw new Error(
|
||||
`release profile must be one of: beta, stable, full. Got: ${JSON.stringify(raw)}`,
|
||||
);
|
||||
}
|
||||
|
||||
function chunkMatchesReleaseProfile(chunk, releaseProfile) {
|
||||
const profiles = primaryReleasePathChunkProfiles[chunk];
|
||||
return !profiles || profiles.includes(releaseProfile);
|
||||
}
|
||||
|
||||
function openWebUILane() {
|
||||
return liveLane("openwebui", RELEASE_OPENWEBUI_COMMAND, {
|
||||
e2eImageKind: "functional",
|
||||
needsLiveImage: false,
|
||||
provider: "openai",
|
||||
resources: ["service"],
|
||||
timeoutMs: OPENWEBUI_TIMEOUT_MS,
|
||||
weight: 5,
|
||||
});
|
||||
}
|
||||
|
||||
export function releasePathChunkLanes(chunk, options = {}) {
|
||||
const base = primaryReleasePathChunks[chunk] ?? legacyReleasePathChunks[chunk];
|
||||
if (!base) {
|
||||
throw new Error(
|
||||
`OPENCLAW_DOCKER_ALL_CHUNK must be one of: ${[
|
||||
...Object.keys(primaryReleasePathChunks),
|
||||
...Object.keys(legacyReleasePathChunks),
|
||||
].join(", ")}. Got: ${JSON.stringify(chunk)}`,
|
||||
);
|
||||
}
|
||||
const releaseProfile = normalizeReleaseProfile(options.releaseProfile);
|
||||
if (!chunkMatchesReleaseProfile(chunk, releaseProfile)) {
|
||||
return [];
|
||||
}
|
||||
if (chunk === "openwebui") {
|
||||
return options.includeOpenWebUI ? [openWebUILane()] : [];
|
||||
}
|
||||
if (
|
||||
(chunk !== "plugins-runtime-services" &&
|
||||
chunk !== "plugins-runtime-core" &&
|
||||
chunk !== "plugins-runtime" &&
|
||||
chunk !== "plugins-integrations") ||
|
||||
!options.includeOpenWebUI
|
||||
) {
|
||||
return base;
|
||||
}
|
||||
return [...base, openWebUILane()];
|
||||
}
|
||||
|
||||
export function allReleasePathLanes(options = {}) {
|
||||
const releaseProfile = normalizeReleaseProfile(options.releaseProfile);
|
||||
return Object.keys(primaryReleasePathChunks)
|
||||
.filter((chunk) => chunk !== "openwebui")
|
||||
.flatMap((chunk) =>
|
||||
releasePathChunkLanes(chunk, {
|
||||
includeOpenWebUI: options.includeOpenWebUI,
|
||||
releaseProfile,
|
||||
}),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user