From 33fd59a4bbd2e247ea248c16e9433aa380cf640f Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 31 Jul 2026 18:51:00 +0800 Subject: [PATCH] fix(release): skip unavailable Buzz QA runner (#116753) --- .../workflows/qa-live-transports-convex.yml | 46 ++++++++++++++++++- .../package-acceptance-workflow.test.ts | 25 +++++++--- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/.github/workflows/qa-live-transports-convex.yml b/.github/workflows/qa-live-transports-convex.yml index ab657e69b296..943276d8d0e5 100644 --- a/.github/workflows/qa-live-transports-convex.yml +++ b/.github/workflows/qa-live-transports-convex.yml @@ -480,7 +480,47 @@ jobs: node-version: ${{ env.NODE_VERSION }} install-bun: "true" + - name: Resolve Buzz QA runner + id: resolve_buzz + env: + SELECTED_REVISION: ${{ needs.validate_selected_ref.outputs.selected_revision }} + shell: bash + run: | + set -euo pipefail + + output_dir=".artifacts/qa-e2e/buzz-live-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" + mkdir -p "${output_dir}" + echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT" + + OUTPUT_DIR="${output_dir}" node --input-type=module <<'NODE' + import fs from "node:fs"; + + const manifestPath = "extensions/buzz/openclaw.plugin.json"; + const manifest = fs.existsSync(manifestPath) + ? JSON.parse(fs.readFileSync(manifestPath, "utf8")) + : {}; + const available = + Array.isArray(manifest.qaRunners) && + manifest.qaRunners.some((runner) => runner?.commandName === "buzz"); + fs.appendFileSync(process.env.GITHUB_OUTPUT, `available=${available}\n`); + if (!available) { + fs.writeFileSync( + `${process.env.OUTPUT_DIR}/skipped.json`, + `${JSON.stringify( + { + status: "skipped", + reason: "selected ref does not declare the Buzz QA runner", + revision: process.env.SELECTED_REVISION, + }, + null, + 2, + )}\n`, + ); + } + NODE + - name: Validate required Buzz QA credential env + if: steps.resolve_buzz.outputs.available == 'true' env: OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }} OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }} @@ -496,11 +536,13 @@ jobs: done - name: Build private QA runtime + if: steps.resolve_buzz.outputs.available == 'true' env: NODE_OPTIONS: --max-old-space-size=12288 run: pnpm build - name: Run Buzz live lane + if: steps.resolve_buzz.outputs.available == 'true' id: run_lane shell: bash env: @@ -513,7 +555,7 @@ jobs: run: | set -euo pipefail - output_dir=".artifacts/qa-e2e/buzz-live-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" + output_dir="${{ steps.resolve_buzz.outputs.output_dir }}" scenario_args=() if [[ -n "${INPUT_SCENARIO// }" ]]; then @@ -541,7 +583,7 @@ jobs: uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: ${{ inputs.expected_sha != '' && format('release-qa-live-buzz-{0}-{1}', inputs.expected_sha, github.run_attempt) || format('qa-live-buzz-{0}-{1}', github.run_id, github.run_attempt) }} - path: ${{ steps.run_lane.outputs.output_dir }} + path: ${{ steps.resolve_buzz.outputs.output_dir }} retention-days: 14 if-no-files-found: error diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 34dee02c5849..bd535bba6fa3 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -2667,15 +2667,26 @@ describe("package artifact reuse", () => { expected_sha: "${{ needs.resolve_target.outputs.revision }}", run_buzz: true, }); - expect(workflowJob(QA_LIVE_TRANSPORTS_WORKFLOW, "run_live_buzz").if).toBe("inputs.run_buzz"); - expect( - workflowStep( - workflowJob(QA_LIVE_TRANSPORTS_WORKFLOW, "run_live_buzz"), - "Upload Buzz QA artifacts", - ).with?.name, - ).toBe( + const buzzJob = workflowJob(QA_LIVE_TRANSPORTS_WORKFLOW, "run_live_buzz"); + expect(buzzJob.if).toBe("inputs.run_buzz"); + const resolveBuzz = workflowStep(buzzJob, "Resolve Buzz QA runner"); + expect(resolveBuzz.run).toContain('runner?.commandName === "buzz"'); + expect(resolveBuzz.run).toContain("selected ref does not declare the Buzz QA runner"); + expect(workflowStep(buzzJob, "Validate required Buzz QA credential env").if).toBe( + "steps.resolve_buzz.outputs.available == 'true'", + ); + expect(workflowStep(buzzJob, "Build private QA runtime").if).toBe( + "steps.resolve_buzz.outputs.available == 'true'", + ); + expect(workflowStep(buzzJob, "Run Buzz live lane").if).toBe( + "steps.resolve_buzz.outputs.available == 'true'", + ); + expect(workflowStep(buzzJob, "Upload Buzz QA artifacts").with?.name).toBe( "${{ inputs.expected_sha != '' && format('release-qa-live-buzz-{0}-{1}', inputs.expected_sha, github.run_attempt) || format('qa-live-buzz-{0}-{1}', github.run_id, github.run_attempt) }}", ); + expect(workflowStep(buzzJob, "Upload Buzz QA artifacts").with?.path).toBe( + "${{ steps.resolve_buzz.outputs.output_dir }}", + ); }); it("runs live transport lanes nightly while release checks stay gated", () => {