From fdd2ff02c6ba056e83ea9f4da43ecf0cb3bdc3ee Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 28 Apr 2026 01:30:52 +0100 Subject: [PATCH] ci: stabilize release validation lanes --- .../openclaw-live-and-e2e-checks-reusable.yml | 30 +++++++++++++++++-- .github/workflows/openclaw-release-checks.yml | 1 + .github/workflows/package-acceptance.yml | 11 +++++++ .../telegram/telegram-live.runtime.ts | 21 ++++++++++++- .../package-acceptance-workflow.test.ts | 13 ++++++++ 5 files changed, 72 insertions(+), 4 deletions(-) diff --git a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml index 0a5dd9b983e..d0515fd9db3 100644 --- a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml +++ b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml @@ -1521,9 +1521,33 @@ jobs: timeout_minutes: 90 needs_ffmpeg: false profile_env_only: false - - suite_id: native-live-src-gateway-profiles-other - label: Native live gateway profiles other providers - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek,opencode-go,openrouter,xai,zai node scripts/test-live-shard.mjs native-live-src-gateway-profiles + - suite_id: native-live-src-gateway-profiles-deepseek + label: Native live gateway profiles DeepSeek + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek node scripts/test-live-shard.mjs native-live-src-gateway-profiles + timeout_minutes: 90 + needs_ffmpeg: false + profile_env_only: false + - suite_id: native-live-src-gateway-profiles-opencode-go + label: Native live gateway profiles OpenCode Go + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go node scripts/test-live-shard.mjs native-live-src-gateway-profiles + timeout_minutes: 90 + needs_ffmpeg: false + profile_env_only: false + - suite_id: native-live-src-gateway-profiles-openrouter + label: Native live gateway profiles OpenRouter + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=openrouter node scripts/test-live-shard.mjs native-live-src-gateway-profiles + timeout_minutes: 90 + needs_ffmpeg: false + profile_env_only: false + - suite_id: native-live-src-gateway-profiles-xai + label: Native live gateway profiles xAI + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=xai node scripts/test-live-shard.mjs native-live-src-gateway-profiles + timeout_minutes: 90 + needs_ffmpeg: false + profile_env_only: false + - suite_id: native-live-src-gateway-profiles-zai + label: Native live gateway profiles Z.ai + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=zai node scripts/test-live-shard.mjs native-live-src-gateway-profiles timeout_minutes: 90 needs_ffmpeg: false profile_env_only: false diff --git a/.github/workflows/openclaw-release-checks.yml b/.github/workflows/openclaw-release-checks.yml index 6374a99c568..98e0b81330b 100644 --- a/.github/workflows/openclaw-release-checks.yml +++ b/.github/workflows/openclaw-release-checks.yml @@ -254,6 +254,7 @@ jobs: suite_profile: custom docker_lanes: bundled-channel-deps-compat plugins-offline telegram_mode: mock-openai + telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-mention-gating secrets: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }} diff --git a/.github/workflows/package-acceptance.yml b/.github/workflows/package-acceptance.yml index 73c5fa6db98..80572185386 100644 --- a/.github/workflows/package-acceptance.yml +++ b/.github/workflows/package-acceptance.yml @@ -73,6 +73,11 @@ on: - none - mock-openai - live-frontier + telegram_scenarios: + description: Optional comma-separated Telegram scenario ids + required: false + default: "" + type: string workflow_call: inputs: workflow_ref: @@ -129,6 +134,11 @@ on: required: false default: none type: string + telegram_scenarios: + description: Optional comma-separated Telegram scenario ids + required: false + default: "" + type: string secrets: OPENAI_API_KEY: required: false @@ -482,6 +492,7 @@ jobs: package_label: openclaw@${{ needs.resolve_package.outputs.package_version }} harness_ref: ${{ inputs.source == 'ref' && inputs.package_ref || inputs.workflow_ref }} provider_mode: ${{ needs.resolve_package.outputs.telegram_mode }} + scenario: ${{ inputs.telegram_scenarios }} secrets: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }} diff --git a/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts b/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts index 18c60e683b6..d84a13a72b0 100644 --- a/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts +++ b/extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts @@ -118,6 +118,7 @@ export type TelegramQaRunResult = { reportPath: string; summaryPath: string; observedMessagesPath: string; + gatewayDebugDirPath?: string; scenarios: TelegramQaScenarioResult[]; }; @@ -664,6 +665,7 @@ function renderTelegramQaMarkdown(params: { credentialSource: "convex" | "env"; redactMetadata: boolean; groupId: string; + gatewayDebugDirPath?: string; startedAt: string; finishedAt: string; scenarios: TelegramQaScenarioResult[]; @@ -690,6 +692,12 @@ function renderTelegramQaMarkdown(params: { } lines.push(""); } + if (params.gatewayDebugDirPath) { + lines.push("## Gateway Debug"); + lines.push(""); + lines.push(`- Preserved at: \`${params.gatewayDebugDirPath}\``); + lines.push(""); + } if (params.cleanupIssues.length > 0) { lines.push("## Cleanup"); lines.push(""); @@ -1094,6 +1102,8 @@ export async function runTelegramQaLive(params: { const startedAt = new Date().toISOString(); const scenarioResults: TelegramQaScenarioResult[] = []; const cleanupIssues: string[] = []; + const gatewayDebugDirPath = path.join(outputDir, "gateway-debug"); + let preservedGatewayDebugArtifacts = false; let canaryFailure: string | null = null; try { if (params.sutOpenClawCommand && params.preflightInstalledOnboarding === true) { @@ -1296,7 +1306,13 @@ export async function runTelegramQaLive(params: { } } finally { try { - await gatewayHarness.stop(); + const shouldPreserveGatewayDebugArtifacts = scenarioResults.some( + (scenario) => scenario.status === "fail", + ); + await gatewayHarness.stop( + shouldPreserveGatewayDebugArtifacts ? { preserveToDir: gatewayDebugDirPath } : undefined, + ); + preservedGatewayDebugArtifacts = shouldPreserveGatewayDebugArtifacts; } catch (error) { appendLiveLaneIssue(cleanupIssues, "live gateway cleanup", error); } @@ -1352,6 +1368,7 @@ export async function runTelegramQaLive(params: { credentialSource: credentialLease.source, redactMetadata: redactPublicMetadata, groupId: redactPublicMetadata ? "" : runtimeEnv.groupId, + gatewayDebugDirPath: preservedGatewayDebugArtifacts ? gatewayDebugDirPath : undefined, startedAt, finishedAt, scenarios: scenarioResults, @@ -1379,6 +1396,7 @@ export async function runTelegramQaLive(params: { report: reportPath, summary: summaryPath, observedMessages: observedMessagesPath, + ...(preservedGatewayDebugArtifacts ? { gatewayDebug: gatewayDebugDirPath } : {}), }; if (canaryFailure) { throw new Error( @@ -1403,6 +1421,7 @@ export async function runTelegramQaLive(params: { reportPath, summaryPath, observedMessagesPath, + ...(preservedGatewayDebugArtifacts ? { gatewayDebugDirPath } : {}), scenarios: scenarioResults, }; } diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 1586fe0ccde..0759c30b10e 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -48,6 +48,8 @@ describe("package acceptance workflow", () => { expect(workflow).toContain( "package_artifact_name: ${{ needs.resolve_package.outputs.package_artifact_name }}", ); + expect(workflow).toContain("telegram_scenarios:"); + expect(workflow).toContain("scenario: ${{ inputs.telegram_scenarios }}"); expect(workflow).toContain( "package_label: openclaw@${{ needs.resolve_package.outputs.package_version }}", ); @@ -103,6 +105,14 @@ describe("package artifact reuse", () => { expect(workflow).toContain("command: node scripts/test-live-shard.mjs native-live-src-agents"); expect(workflow).toContain("suite_id: native-live-src-gateway-core"); expect(workflow).toContain("suite_id: native-live-src-gateway-backends"); + expect(workflow).toContain("suite_id: native-live-src-gateway-profiles-deepseek"); + expect(workflow).toContain("suite_id: native-live-src-gateway-profiles-opencode-go"); + expect(workflow).toContain("suite_id: native-live-src-gateway-profiles-openrouter"); + expect(workflow).toContain("suite_id: native-live-src-gateway-profiles-xai"); + expect(workflow).toContain("suite_id: native-live-src-gateway-profiles-zai"); + expect(workflow).not.toContain( + "OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek,opencode-go,openrouter,xai,zai", + ); expect(workflow).toContain("suite_id: native-live-extensions-a-k"); expect(workflow).toContain("suite_id: native-live-extensions-l-n"); expect(workflow).toContain("suite_id: native-live-extensions-openai"); @@ -140,6 +150,9 @@ describe("package artifact reuse", () => { expect(workflow).toContain("suite_profile: custom"); expect(workflow).toContain("docker_lanes: bundled-channel-deps-compat plugins-offline"); expect(workflow).toContain("telegram_mode: mock-openai"); + expect(workflow).toContain( + "telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-mention-gating", + ); expect(workflow).toContain("ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}"); expect(workflow).toContain("ANTHROPIC_API_TOKEN: ${{ secrets.ANTHROPIC_API_TOKEN }}"); expect(workflow).toContain(