diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0935ac44813..8a4dc8b182e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,9 +139,6 @@ jobs: import { createNodeTestShards, } from "./scripts/lib/ci-node-test-plan.mjs"; - import { - assertPluginPrereleaseTestPlanComplete, - } from "./scripts/lib/plugin-prerelease-test-plan.mjs"; import { createChannelContractTestShards, } from "./scripts/lib/channel-contract-test-plan.mjs"; @@ -184,7 +181,6 @@ jobs: const runSkillsPython = parseBoolean(process.env.OPENCLAW_CI_RUN_SKILLS_PYTHON) && !docsOnly; const runControlUiI18n = parseBoolean(process.env.OPENCLAW_CI_RUN_CONTROL_UI_I18N) && !docsOnly; - const pluginPrereleasePlan = assertPluginPrereleaseTestPlanComplete(); const isMegaCiRun = process.env.OPENCLAW_CI_EVENT_NAME === "workflow_dispatch"; const trustedPluginPrereleaseRef = process.env.OPENCLAW_CI_EVENT_NAME !== "pull_request" || @@ -193,8 +189,33 @@ jobs: process.env.OPENCLAW_CI_EVENT_NAME === "pull_request" && trustedPluginPrereleaseRef ? process.env.OPENCLAW_CI_PR_HEAD_SHA : process.env.OPENCLAW_CI_CHECKOUT_REVISION; - const runPluginPrereleaseSuite = + let runPluginPrereleaseSuite = isMegaCiRun && runNodeFull && isCanonicalRepository; + let pluginPrereleasePlan = { staticChecks: [], dockerLanes: [] }; + if (runPluginPrereleaseSuite) { + try { + const { assertPluginPrereleaseTestPlanComplete } = await import( + "./scripts/lib/plugin-prerelease-test-plan.mjs" + ); + pluginPrereleasePlan = assertPluginPrereleaseTestPlanComplete(); + } catch (error) { + const errorCode = + error && typeof error === "object" && "code" in error ? error.code : ""; + const moduleUrl = + error && typeof error === "object" && "url" in error ? String(error.url) : ""; + if ( + errorCode === "ERR_MODULE_NOT_FOUND" && + moduleUrl.endsWith("/scripts/lib/plugin-prerelease-test-plan.mjs") + ) { + console.warn( + "Plugin prerelease plan unavailable in target ref; skipping plugin prerelease suite.", + ); + runPluginPrereleaseSuite = false; + } else { + throw error; + } + } + } const extensionTestShardCount = isCanonicalRepository ? DEFAULT_EXTENSION_TEST_SHARD_COUNT : Math.max(DEFAULT_EXTENSION_TEST_SHARD_COUNT, 36); diff --git a/test/scripts/plugin-prerelease-test-plan.test.ts b/test/scripts/plugin-prerelease-test-plan.test.ts index a1e0cba3fe4..040b668a143 100644 --- a/test/scripts/plugin-prerelease-test-plan.test.ts +++ b/test/scripts/plugin-prerelease-test-plan.test.ts @@ -127,7 +127,13 @@ describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => { 'const isMegaCiRun = process.env.OPENCLAW_CI_EVENT_NAME === "workflow_dispatch";', ); expect(manifestScript).toContain( - "const runPluginPrereleaseSuite =\n isMegaCiRun && runNodeFull && isCanonicalRepository;", + "let runPluginPrereleaseSuite =\n isMegaCiRun && runNodeFull && isCanonicalRepository;", + ); + expect(manifestScript).toContain("await import("); + expect(manifestScript).toContain('"./scripts/lib/plugin-prerelease-test-plan.mjs"'); + expect(manifestScript).not.toContain('} from "./scripts/lib/plugin-prerelease-test-plan.mjs";'); + expect(manifestScript).toContain( + "Plugin prerelease plan unavailable in target ref; skipping plugin prerelease suite.", ); expect(staticShard.strategy.matrix).toBe( "${{ fromJson(needs.preflight.outputs.plugin_prerelease_static_matrix) }}",