




















@@ -70,6 +70,31 @@ function publishedUpgradeSurvivorLane(
7070};
7171}
727273+function updateMigrationLane(name: string, baselineSpec: string): ReturnType<typeof summarizeLane> {
74+return {
75+command: `OPENCLAW_UPGRADE_SURVIVOR_ARTIFACT_DIR="$PWD/.artifacts/upgrade-survivor/${name}" OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC='${baselineSpec}' OPENCLAW_UPGRADE_SURVIVOR_SCENARIO='plugin-deps-cleanup' OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:update-migration`,
76+imageKind: "bare",
77+live: false,
78+ name,
79+resources: ["docker", "npm"],
80+stateScenario: "upgrade-survivor",
81+timeoutMs: 1_800_000,
82+weight: 3,
83+};
84+}
85+86+function bundledPluginSweepLane(index: number): ReturnType<typeof summarizeLane> {
87+return {
88+command: `OPENCLAW_BUNDLED_PLUGIN_SWEEP_TOTAL=24 OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=${index} OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:bundled-plugin-install-uninstall`,
89+imageKind: "functional",
90+live: false,
91+name: `bundled-plugin-install-uninstall-${index}`,
92+resources: ["docker", "npm"],
93+stateScenario: "empty",
94+weight: 1,
95+};
96+}
97+7398describe("scripts/lib/docker-e2e-plan", () => {
7499it("plans the full release path against package-backed e2e images", () => {
75100const plan = planFor({
@@ -524,24 +549,10 @@ describe("scripts/lib/docker-e2e-plan", () => {
524549upgradeSurvivorScenarios: "plugin-deps-cleanup",
525550});
526551527-expect(plan.lanes.map((lane) => lane.name)).toEqual([
528-"update-migration-2026.4.29-plugin-deps-cleanup",
529-"update-migration-2026.4.23-plugin-deps-cleanup",
552+expect(plan.lanes.map(summarizeLane)).toEqual([
553+updateMigrationLane("update-migration-2026.4.29-plugin-deps-cleanup", "openclaw@2026.4.29"),
554+updateMigrationLane("update-migration-2026.4.23-plugin-deps-cleanup", "openclaw@2026.4.23"),
530555]);
531-expect(plan.lanes).toEqual(
532-expect.arrayContaining([
533-expect.objectContaining({
534-command: expect.stringContaining("pnpm test:docker:update-migration"),
535-imageKind: "bare",
536-stateScenario: "upgrade-survivor",
537-}),
538-expect.objectContaining({
539-command: expect.stringContaining(
540-"OPENCLAW_UPGRADE_SURVIVOR_SCENARIO='plugin-deps-cleanup'",
541-),
542-}),
543-]),
544-);
545556});
546557547558it("plans a live-only selected lane without package e2e images", () => {
@@ -561,15 +572,17 @@ describe("scripts/lib/docker-e2e-plan", () => {
561572const plan = planFor({ selectedLaneNames: ["live-codex-npm-plugin"] });
562573563574expect(plan.credentials).toEqual(["openai"]);
564-expect(plan.lanes).toEqual([
565-expect.objectContaining({
575+expect(plan.lanes.map(summarizeLane)).toEqual([
576+{
566577command: "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:live-codex-npm-plugin",
567578imageKind: "bare",
568579live: true,
569580name: "live-codex-npm-plugin",
570581resources: ["docker", "live", "live:openai", "npm"],
571582stateScenario: "empty",
572-}),
583+timeoutMs: 1_800_000,
584+weight: 3,
585+},
573586]);
574587expect(plan.needs).toEqual({
575588bareImage: true,
@@ -587,13 +600,16 @@ describe("scripts/lib/docker-e2e-plan", () => {
587600});
588601589602expect(plan.credentials).toEqual(["openai"]);
590-expect(plan.lanes).toEqual([
591-expect.objectContaining({
603+expect(plan.lanes.map(summarizeLane)).toEqual([
604+{
605+command: "OPENCLAW_SKIP_DOCKER_BUILD=1 pnpm test:docker:openwebui",
592606imageKind: "functional",
593607live: true,
594608name: "openwebui",
595-resources: expect.arrayContaining(["docker", "live", "live:openai", "service"]),
596-}),
609+resources: ["docker", "live", "live:openai", "service"],
610+timeoutMs: 1_200_000,
611+weight: 5,
612+},
597613]);
598614expect(plan.needs).toEqual({
599615bareImage: false,
@@ -637,83 +653,28 @@ describe("scripts/lib/docker-e2e-plan", () => {
637653],
638654});
639655640-expect(plan.lanes).toEqual([
641-expect.objectContaining({
642-name: "onboard",
643-stateScenario: "empty",
644-}),
645-expect.objectContaining({
646-name: "agents-delete-shared-workspace",
647-stateScenario: "empty",
648-}),
649-expect.objectContaining({
650-name: "doctor-switch",
651-stateScenario: "empty",
652-}),
653-expect.objectContaining({
654-name: "openai-image-auth",
655-stateScenario: "empty",
656-}),
657-expect.objectContaining({
658-name: "openai-web-search-minimal",
659-stateScenario: "empty",
660-}),
661-expect.objectContaining({
662-name: "mcp-channels",
663-stateScenario: "empty",
664-}),
665-expect.objectContaining({
666-name: "cron-mcp-cleanup",
667-stateScenario: "empty",
668-}),
669-expect.objectContaining({
670-name: "pi-bundle-mcp-tools",
671-stateScenario: "empty",
672-}),
673-expect.objectContaining({
674-name: "crestodian-first-run",
675-stateScenario: "empty",
676-}),
677-expect.objectContaining({
678-name: "crestodian-planner",
679-stateScenario: "empty",
680-}),
681-expect.objectContaining({
682-name: "crestodian-rescue",
683-stateScenario: "empty",
684-}),
685-expect.objectContaining({
686-name: "config-reload",
687-stateScenario: "empty",
688-}),
689-expect.objectContaining({
690-name: "plugin-update",
691-stateScenario: "empty",
692-}),
693-expect.objectContaining({
694-name: "plugins",
695-stateScenario: "empty",
696-}),
697-expect.objectContaining({
698-name: "kitchen-sink-plugin",
699-stateScenario: "empty",
700-}),
701-expect.objectContaining({
702-name: "bundled-plugin-install-uninstall-0",
703-stateScenario: "empty",
704-}),
705-expect.objectContaining({
706-name: "commitments-safety",
707-stateScenario: "empty",
708-}),
709-expect.objectContaining({
710-name: "update-channel-switch",
711-stateScenario: "update-stable",
712-}),
713-expect.objectContaining({
714-name: "upgrade-survivor",
715-stateScenario: "upgrade-survivor",
716-}),
656+expect(
657+plan.lanes.map((lane) => ({ name: lane.name, stateScenario: lane.stateScenario })),
658+).toEqual([
659+{ name: "onboard", stateScenario: "empty" },
660+{ name: "agents-delete-shared-workspace", stateScenario: "empty" },
661+{ name: "doctor-switch", stateScenario: "empty" },
662+{ name: "openai-image-auth", stateScenario: "empty" },
663+{ name: "openai-web-search-minimal", stateScenario: "empty" },
664+{ name: "mcp-channels", stateScenario: "empty" },
665+{ name: "cron-mcp-cleanup", stateScenario: "empty" },
666+{ name: "pi-bundle-mcp-tools", stateScenario: "empty" },
667+{ name: "crestodian-first-run", stateScenario: "empty" },
668+{ name: "crestodian-planner", stateScenario: "empty" },
669+{ name: "crestodian-rescue", stateScenario: "empty" },
670+{ name: "config-reload", stateScenario: "empty" },
671+{ name: "plugin-update", stateScenario: "empty" },
672+{ name: "plugins", stateScenario: "empty" },
673+{ name: "kitchen-sink-plugin", stateScenario: "empty" },
674+{ name: "bundled-plugin-install-uninstall-0", stateScenario: "empty" },
675+{ name: "commitments-safety", stateScenario: "empty" },
676+{ name: "update-channel-switch", stateScenario: "update-stable" },
677+{ name: "upgrade-survivor", stateScenario: "upgrade-survivor" },
717678]);
718679});
719680@@ -722,15 +683,25 @@ describe("scripts/lib/docker-e2e-plan", () => {
722683const plan = planFor({ selectedLaneNames });
723684724685expect(selectedLaneNames).toEqual(["install-e2e-openai", "install-e2e-anthropic"]);
725-expect(plan.lanes).toEqual([
726-expect.objectContaining({
727-command: expect.stringContaining("OPENCLAW_E2E_MODELS=openai"),
686+expect(plan.lanes.map(summarizeLane)).toEqual([
687+{
688+command:
689+"OPENCLAW_INSTALL_TAG=beta OPENCLAW_E2E_MODELS=openai OPENCLAW_INSTALL_E2E_IMAGE=openclaw-install-e2e-openai:local pnpm test:install:e2e",
690+imageKind: "bare",
691+live: false,
728692name: "install-e2e-openai",
729-}),
730-expect.objectContaining({
731-command: expect.stringContaining("OPENCLAW_E2E_MODELS=anthropic"),
693+resources: ["docker", "npm", "service"],
694+weight: 3,
695+},
696+{
697+command:
698+"OPENCLAW_INSTALL_TAG=beta OPENCLAW_E2E_MODELS=anthropic OPENCLAW_INSTALL_E2E_IMAGE=openclaw-install-e2e-anthropic:local pnpm test:install:e2e",
699+imageKind: "bare",
700+live: false,
732701name: "install-e2e-anthropic",
733-}),
702+resources: ["docker", "npm", "service"],
703+weight: 3,
704+},
734705]);
735706expect(plan.credentials).toEqual(["anthropic", "openai"]);
736707});
@@ -746,24 +717,10 @@ describe("scripts/lib/docker-e2e-plan", () => {
746717),
747718);
748719expect(plan.lanes).toHaveLength(BUNDLED_PLUGIN_INSTALL_UNINSTALL_SHARDS);
749-expect(plan.lanes[0]).toEqual(
750-expect.objectContaining({
751-command: expect.stringContaining("OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=0"),
752-imageKind: "functional",
753-live: false,
754-name: "bundled-plugin-install-uninstall-0",
755-resources: expect.arrayContaining(["docker", "npm"]),
756-}),
757-);
758-expect(plan.lanes[23]).toEqual(
759-expect.objectContaining({
760-command: expect.stringContaining("OPENCLAW_BUNDLED_PLUGIN_SWEEP_INDEX=23"),
761-imageKind: "functional",
762-live: false,
763-name: "bundled-plugin-install-uninstall-23",
764-resources: expect.arrayContaining(["docker", "npm"]),
765-}),
766-);
720+expect(plan.lanes.at(0)).toBeDefined();
721+expect(plan.lanes.at(23)).toBeDefined();
722+expect(summarizeLane(plan.lanes[0]!)).toEqual(bundledPluginSweepLane(0));
723+expect(summarizeLane(plan.lanes[23]!)).toEqual(bundledPluginSweepLane(23));
767724expect(plan.needs).toEqual({
768725bareImage: false,
769726e2eImage: true,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。