From 5f4fd05074ce70878d5f552b9be7f2d3f20a32b5 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 3 May 2026 12:24:19 +0100 Subject: [PATCH] ci: speed up full release validation --- .github/workflows/full-release-validation.yml | 88 +++++++++++++++++-- .../openclaw-live-and-e2e-checks-reusable.yml | 38 +++++--- docs/reference/RELEASING.md | 5 +- docs/reference/full-release-validation.md | 38 ++++---- .../package-acceptance-workflow.test.ts | 37 ++++++-- .../plugin-prerelease-test-plan.test.ts | 1 + 6 files changed, 166 insertions(+), 41 deletions(-) diff --git a/.github/workflows/full-release-validation.yml b/.github/workflows/full-release-validation.yml index 708b822ffbe..3f91e8e25f2 100644 --- a/.github/workflows/full-release-validation.yml +++ b/.github/workflows/full-release-validation.yml @@ -98,6 +98,8 @@ concurrency: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" GH_REPO: ${{ github.repository }} + NODE_VERSION: "24.x" + PNPM_VERSION: "10.32.1" jobs: resolve_target: @@ -165,7 +167,7 @@ jobs: if [[ -n "${NPM_TELEGRAM_PACKAGE_SPEC// }" ]]; then echo "- Published-package Telegram E2E: \`${NPM_TELEGRAM_PACKAGE_SPEC}\`" elif [[ "$RERUN_GROUP" == "all" && "$RELEASE_PROFILE" == "full" ]]; then - echo "- Package Telegram E2E: release package artifact from \`OpenClaw Release Checks\`" + echo "- Package Telegram E2E: parent \`release-package-under-test\` artifact" else echo "- Package Telegram E2E: skipped unless \`release_profile=full\` or \`npm_telegram_package_spec\` is provided" fi @@ -494,9 +496,80 @@ jobs: dispatch_and_wait openclaw-release-checks.yml "${args[@]}" + prepare_release_package: + name: Prepare release package artifact + needs: [resolve_target] + if: ${{ inputs.npm_telegram_package_spec == '' && inputs.rerun_group == 'all' && inputs.release_profile == 'full' }} + runs-on: ubuntu-24.04 + timeout-minutes: 60 + permissions: + contents: read + packages: write + outputs: + artifact_name: ${{ steps.artifact.outputs.name }} + package_sha256: ${{ steps.package.outputs.sha256 }} + package_version: ${{ steps.package.outputs.package_version }} + source_sha: ${{ steps.package.outputs.source_sha }} + steps: + - name: Checkout trusted workflow ref + uses: actions/checkout@v6 + with: + persist-credentials: false + ref: ${{ github.ref_name }} + fetch-depth: 0 + + - name: Set artifact metadata + id: artifact + run: echo "name=release-package-under-test" >> "$GITHUB_OUTPUT" + + - name: Setup Node environment + uses: ./.github/actions/setup-node-env + with: + node-version: ${{ env.NODE_VERSION }} + pnpm-version: ${{ env.PNPM_VERSION }} + install-bun: "true" + install-deps: "false" + + - name: Resolve release package artifact + id: package + shell: bash + env: + PACKAGE_REF: ${{ needs.resolve_target.outputs.sha }} + run: | + set -euo pipefail + node scripts/resolve-openclaw-package-candidate.mjs \ + --source ref \ + --package-ref "$PACKAGE_REF" \ + --output-dir .artifacts/docker-e2e-package \ + --output-name openclaw-current.tgz \ + --metadata .artifacts/docker-e2e-package/package-candidate.json \ + --github-output "$GITHUB_OUTPUT" + digest="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).sha256")" + version="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).version")" + source_sha="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).packageSourceSha")" + echo "source_sha=$source_sha" >> "$GITHUB_OUTPUT" + { + echo "## Release package artifact" + echo + echo "- Artifact: \`release-package-under-test\`" + echo "- Package ref: \`$PACKAGE_REF\`" + echo "- SHA-256: \`$digest\`" + echo "- Version: \`$version\`" + echo "- Source SHA: \`$source_sha\`" + } >> "$GITHUB_STEP_SUMMARY" + + - name: Upload release package artifact + uses: actions/upload-artifact@v7 + with: + name: release-package-under-test + path: | + .artifacts/docker-e2e-package/openclaw-current.tgz + .artifacts/docker-e2e-package/package-candidate.json + if-no-files-found: error + npm_telegram: name: Run package Telegram E2E - needs: [resolve_target, release_checks] + needs: [resolve_target, prepare_release_package] if: ${{ always() && contains(fromJSON('["all","npm-telegram"]'), inputs.rerun_group) && (inputs.npm_telegram_package_spec != '' || (inputs.rerun_group == 'all' && inputs.release_profile == 'full')) }} runs-on: ubuntu-24.04 timeout-minutes: 120 @@ -512,7 +585,8 @@ jobs: CHILD_WORKFLOW_REF: ${{ github.ref_name }} TARGET_SHA: ${{ needs.resolve_target.outputs.sha }} PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }} - RELEASE_CHECKS_RUN_ID: ${{ needs.release_checks.outputs.run_id }} + PACKAGE_ARTIFACT_NAME: ${{ needs.prepare_release_package.outputs.artifact_name }} + PREPARE_PACKAGE_RESULT: ${{ needs.prepare_release_package.result }} PROVIDER_MODE: ${{ inputs.npm_telegram_provider_mode }} SCENARIO: ${{ inputs.npm_telegram_scenario }} run: | @@ -522,13 +596,13 @@ jobs: args=(-f package_spec="${PACKAGE_SPEC:-openclaw@beta}" -f harness_ref="$TARGET_SHA" -f provider_mode="$PROVIDER_MODE") if [[ -z "${PACKAGE_SPEC// }" ]]; then - if [[ -z "${RELEASE_CHECKS_RUN_ID// }" ]]; then - echo "Full release Telegram requires either npm_telegram_package_spec or a release_checks child run with the release-package-under-test artifact." >&2 + if [[ "$PREPARE_PACKAGE_RESULT" != "success" || -z "${PACKAGE_ARTIFACT_NAME// }" ]]; then + echo "Full release Telegram requires either npm_telegram_package_spec or a prepared release-package-under-test artifact." >&2 exit 1 fi args+=( - -f package_artifact_name=release-package-under-test - -f package_artifact_run_id="$RELEASE_CHECKS_RUN_ID" + -f package_artifact_name="$PACKAGE_ARTIFACT_NAME" + -f package_artifact_run_id="${GITHUB_RUN_ID}" -f package_label="full-release-${TARGET_SHA:0:12}" ) fi diff --git a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml index f68ade6b501..702f2bdb036 100644 --- a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml +++ b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml @@ -395,6 +395,9 @@ jobs: add_profile_suite native-live-src-agents "stable full" add_profile_suite native-live-src-gateway-core "minimum stable full" add_profile_suite native-live-src-gateway-profiles-anthropic "stable full" + add_profile_suite native-live-src-gateway-profiles-anthropic-smoke "stable" + add_profile_suite native-live-src-gateway-profiles-anthropic-opus "full" + add_profile_suite native-live-src-gateway-profiles-anthropic-sonnet-haiku "full" add_profile_suite native-live-src-gateway-profiles-google "stable full" add_profile_suite native-live-src-gateway-profiles-minimax "stable full" add_profile_suite native-live-src-gateway-profiles-openai "minimum stable full" @@ -1868,12 +1871,27 @@ jobs: timeout_minutes: 90 profile_env_only: false profiles: minimum stable full - - suite_id: native-live-src-gateway-profiles-anthropic - label: Native live gateway profiles Anthropic - command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles + - suite_id: native-live-src-gateway-profiles-anthropic-smoke + suite_group: native-live-src-gateway-profiles-anthropic + label: Native live gateway profiles Anthropic smoke + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_SMOKE=1 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles + timeout_minutes: 45 + profile_env_only: false + profiles: stable + - suite_id: native-live-src-gateway-profiles-anthropic-opus + suite_group: native-live-src-gateway-profiles-anthropic + label: Native live gateway profiles Anthropic Opus + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MODELS=anthropic/claude-opus-4-7,anthropic/claude-opus-4-6 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles timeout_minutes: 90 profile_env_only: false - profiles: stable full + profiles: full + - suite_id: native-live-src-gateway-profiles-anthropic-sonnet-haiku + suite_group: native-live-src-gateway-profiles-anthropic + label: Native live gateway profiles Anthropic Sonnet/Haiku + command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MODELS=anthropic/claude-sonnet-4-6,anthropic/claude-haiku-4-5 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles + timeout_minutes: 90 + profile_env_only: false + profiles: full - suite_id: native-live-src-gateway-profiles-google label: Native live gateway profiles Google command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=google OPENCLAW_LIVE_GATEWAY_MODELS=google/gemini-3.1-pro-preview,google/gemini-3-flash-preview node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles @@ -2050,14 +2068,14 @@ jobs: OPENCLAW_VITEST_MAX_WORKERS: "2" steps: - name: Checkout selected ref - if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) + if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) uses: actions/checkout@v6 with: ref: ${{ needs.validate_selected_ref.outputs.selected_sha }} fetch-depth: 1 - name: Checkout trusted live shard harness - if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) + if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) uses: actions/checkout@v6 with: ref: ${{ github.sha }} @@ -2065,7 +2083,7 @@ jobs: path: .release-harness - name: Setup Node environment - if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) + if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) uses: ./.github/actions/setup-node-env with: node-version: ${{ env.NODE_VERSION }} @@ -2073,11 +2091,11 @@ jobs: install-bun: "true" - name: Hydrate live auth/profile inputs - if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) + if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) run: bash scripts/ci-hydrate-live-auth.sh - name: Configure suite-specific env - if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) + if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) shell: bash run: | set -euo pipefail @@ -2130,7 +2148,7 @@ jobs: esac - name: Run ${{ matrix.label }} - if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) + if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-'))) env: OPENCLAW_LIVE_COMMAND: ${{ matrix.command }} OPENCLAW_LIVE_SUITE_ADVISORY: ${{ matrix.advisory }} diff --git a/docs/reference/RELEASING.md b/docs/reference/RELEASING.md index c48110076db..d67151cf3ae 100644 --- a/docs/reference/RELEASING.md +++ b/docs/reference/RELEASING.md @@ -286,8 +286,9 @@ gh workflow run full-release-validation.yml \ ``` The workflow resolves the target ref, dispatches manual `CI` with -`target_ref=`, dispatches `OpenClaw Release Checks`, and dispatches -standalone package Telegram E2E when `release_profile=full` with +`target_ref=`, dispatches `OpenClaw Release Checks`, prepares a +parent `release-package-under-test` artifact for package-facing checks, and +dispatches standalone package Telegram E2E when `release_profile=full` with `rerun_group=all` or when `npm_telegram_package_spec` is set. `OpenClaw Release Checks` then fans out install smoke, cross-OS release checks, live/E2E Docker release-path coverage, Package Acceptance with Telegram package QA, QA Lab diff --git a/docs/reference/full-release-validation.md b/docs/reference/full-release-validation.md index 25198b2d298..df12c70afb5 100644 --- a/docs/reference/full-release-validation.md +++ b/docs/reference/full-release-validation.md @@ -41,7 +41,8 @@ the shipped npm package instead. | Vitest and normal CI | **Job:** `Run normal full CI`
**Child workflow:** `CI`
**Proves:** manual full CI graph against the target ref, including Linux Node lanes, bundled plugin shards, channel contracts, Node 22 compatibility, `check`, `check-additional`, build smoke, docs checks, Python skills, Windows, macOS, Control UI i18n, and Android via the umbrella.
**Rerun:** `rerun_group=ci`. | | Plugin prerelease | **Job:** `Run plugin prerelease validation`
**Child workflow:** `Plugin Prerelease`
**Proves:** release-only plugin static checks, agentic plugin coverage, full extension batch shards, and plugin prerelease Docker lanes.
**Rerun:** `rerun_group=plugin-prerelease`. | | Release checks | **Job:** `Run release/live/Docker/QA validation`
**Child workflow:** `OpenClaw Release Checks`
**Proves:** install smoke, cross-OS package checks, live/E2E suites, Docker release-path chunks, Package Acceptance, QA Lab parity, live Matrix, and live Telegram.
**Rerun:** `rerun_group=release-checks` or a narrower release-checks handle. | -| Package Telegram | **Job:** `Run package Telegram E2E`
**Child workflow:** `NPM Telegram Beta E2E`
**Proves:** artifact-backed Telegram package proof for `rerun_group=all` with `release_profile=full`, or published-package Telegram proof when `npm_telegram_package_spec` is set.
**Rerun:** `rerun_group=npm-telegram` with `npm_telegram_package_spec`. | +| Package artifact | **Job:** `Prepare release package artifact`
**Child workflow:** none
**Proves:** creates the parent `release-package-under-test` tarball early enough for package-facing checks that do not need to wait for `OpenClaw Release Checks`.
**Rerun:** rerun the umbrella or provide `npm_telegram_package_spec` for `rerun_group=npm-telegram`. | +| Package Telegram | **Job:** `Run package Telegram E2E`
**Child workflow:** `NPM Telegram Beta E2E`
**Proves:** parent-artifact-backed Telegram package proof for `rerun_group=all` with `release_profile=full`, or published-package Telegram proof when `npm_telegram_package_spec` is set.
**Rerun:** `rerun_group=npm-telegram` with `npm_telegram_package_spec`. | | Umbrella verifier | **Job:** `Verify full validation`
**Child workflow:** none
**Proves:** re-checks recorded child run conclusions and appends slowest-job tables from child workflows.
**Rerun:** rerun only this job after rerunning a failed child to green. | For `ref=main` and `rerun_group=all`, a newer umbrella supersedes an older one. @@ -93,30 +94,33 @@ commands with package artifact and image reuse inputs when available. `release_profile` mostly controls live/provider breadth inside release checks. It does not remove normal full CI, Plugin Prerelease, install smoke, package acceptance, QA Lab, or Docker release-path chunks. `full` also makes the -umbrella run package Telegram E2E against the release package artifact when +umbrella run package Telegram E2E against the parent release package artifact when `rerun_group=all`, so a full pre-publish candidate does not silently skip that Telegram package lane. -| Profile | Intended use | Included live/provider coverage | -| --------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `minimum` | Fastest release-critical smoke. | OpenAI/core live path, Docker live models for OpenAI, native gateway core, native OpenAI gateway profile, native OpenAI plugin, and Docker live gateway OpenAI. | -| `stable` | Default release approval profile. | `minimum` plus Anthropic, Google, MiniMax, backend, native live test harness, Docker live CLI backend, Docker ACP bind, Docker Codex harness, and an OpenCode Go smoke shard. | -| `full` | Broad advisory sweep. | `stable` plus advisory providers, plugin live shards, and media live shards. | +| Profile | Intended use | Included live/provider coverage | +| --------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `minimum` | Fastest release-critical smoke. | OpenAI/core live path, Docker live models for OpenAI, native gateway core, native OpenAI gateway profile, native OpenAI plugin, and Docker live gateway OpenAI. | +| `stable` | Default release approval profile. | `minimum` plus Anthropic smoke, Google, MiniMax, backend, native live test harness, Docker live CLI backend, Docker ACP bind, Docker Codex harness, and an OpenCode Go smoke shard. | +| `full` | Broad advisory sweep. | `stable` plus advisory providers, plugin live shards, and media live shards. | ## Full-only additions These suites are skipped by `stable` and included by `full`: -| Area | Full-only coverage | -| -------------------------------- | ------------------------------------------------------------------------------- | -| Docker live models | OpenCode Go, OpenRouter, xAI, Z.ai, and Fireworks. | -| Docker live gateway | Advisory shard for DeepSeek, Fireworks, OpenCode Go, OpenRouter, xAI, and Z.ai. | -| Native gateway provider profiles | Fireworks, DeepSeek, full OpenCode Go model shards, OpenRouter, xAI, and Z.ai. | -| Native plugin live shards | Plugins A-K, L-N, O-Z other, Moonshot, and xAI. | -| Native media live shards | Audio, Google music, MiniMax music, and video groups A-D. | +| Area | Full-only coverage | +| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| Docker live models | OpenCode Go, OpenRouter, xAI, Z.ai, and Fireworks. | +| Docker live gateway | Advisory shard for DeepSeek, Fireworks, OpenCode Go, OpenRouter, xAI, and Z.ai. | +| Native gateway provider profiles | Full Anthropic Opus and Sonnet/Haiku shards, Fireworks, DeepSeek, full OpenCode Go model shards, OpenRouter, xAI, and Z.ai. | +| Native plugin live shards | Plugins A-K, L-N, O-Z other, Moonshot, and xAI. | +| Native media live shards | Audio, Google music, MiniMax music, and video groups A-D. | -`stable` includes `native-live-src-gateway-profiles-opencode-go-smoke`; `full` -uses the broader OpenCode Go model shards instead. +`stable` includes `native-live-src-gateway-profiles-anthropic-smoke` and +`native-live-src-gateway-profiles-opencode-go-smoke`; `full` uses the broader +Anthropic and OpenCode Go model shards instead. Focused reruns can still use the +aggregate `native-live-src-gateway-profiles-anthropic` or +`native-live-src-gateway-profiles-opencode-go` handles. ## Focused reruns @@ -153,7 +157,7 @@ workflow first, then rerun the smallest matching handle above. Useful artifacts: -- `release-package-under-test` from `OpenClaw Release Checks` +- `release-package-under-test` from the Full Release Validation parent and `OpenClaw Release Checks` - Docker release-path artifacts under `.artifacts/docker-tests/` - Package Acceptance `package-under-test` and Docker acceptance artifacts - Cross-OS release-check artifacts for each OS and suite diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 0e6ada7d37a..db7103e2f7d 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -331,6 +331,12 @@ describe("package artifact reuse", () => { ); 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-anthropic-smoke"); + expect(workflow).toContain("suite_id: native-live-src-gateway-profiles-anthropic-opus"); + expect(workflow).toContain("suite_id: native-live-src-gateway-profiles-anthropic-sonnet-haiku"); + expect(workflow).toContain("suite_group: native-live-src-gateway-profiles-anthropic"); + expect(workflow).toContain("anthropic/claude-opus-4-7,anthropic/claude-opus-4-6"); + expect(workflow).toContain("anthropic/claude-sonnet-4-6,anthropic/claude-haiku-4-5"); 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"); @@ -366,6 +372,9 @@ describe("package artifact reuse", () => { expect(workflow).toContain("OPENCLAW_LIVE_VIDEO_GENERATION_PROVIDERS=openai,openrouter,xai"); expect(workflow).toContain("suite_group: native-live-src-gateway-profiles-opencode-go"); expect(workflow).toContain("opencode-go/mimo-v2-omni"); + expect(workflow).toContain( + "inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic'", + ); expect(workflow).toContain( "inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go'", ); @@ -558,18 +567,36 @@ describe("package artifact reuse", () => { it("runs full release children from the trusted workflow ref", () => { const workflow = readFileSync(FULL_RELEASE_VALIDATION_WORKFLOW, "utf8"); + const preparePackageJob = workflowJob( + FULL_RELEASE_VALIDATION_WORKFLOW, + "prepare_release_package", + ); const npmTelegramJob = workflowJob(FULL_RELEASE_VALIDATION_WORKFLOW, "npm_telegram"); const dispatchStep = workflowStep(npmTelegramJob, "Dispatch and monitor npm Telegram E2E"); expect(workflow).toContain("CHILD_WORKFLOW_REF: ${{ github.ref_name }}"); expect(workflow).toContain('gh workflow run "$workflow" --ref "$CHILD_WORKFLOW_REF" "$@"'); + expect(preparePackageJob.name).toBe("Prepare release package artifact"); + expect(preparePackageJob.needs).toEqual(["resolve_target"]); + expect(preparePackageJob.if).toContain("inputs.rerun_group == 'all'"); + expect(preparePackageJob.if).toContain("inputs.release_profile == 'full'"); + expectTextToIncludeAll( + workflowStep(preparePackageJob, "Resolve release package artifact").run, + [ + "scripts/resolve-openclaw-package-candidate.mjs", + "--source ref", + '--package-ref "$PACKAGE_REF"', + "release-package-under-test", + ], + ); expect(npmTelegramJob.name).toBe("Run package Telegram E2E"); - expect(npmTelegramJob.needs).toEqual(["resolve_target", "release_checks"]); + expect(npmTelegramJob.needs).toEqual(["resolve_target", "prepare_release_package"]); expect(npmTelegramJob.if).toContain( "inputs.rerun_group == 'all' && inputs.release_profile == 'full'", ); expect(dispatchStep.env).toMatchObject({ - RELEASE_CHECKS_RUN_ID: "${{ needs.release_checks.outputs.run_id }}", + PACKAGE_ARTIFACT_NAME: "${{ needs.prepare_release_package.outputs.artifact_name }}", + PREPARE_PACKAGE_RESULT: "${{ needs.prepare_release_package.result }}", TARGET_SHA: "${{ needs.resolve_target.outputs.sha }}", }); expectTextToIncludeAll(dispatchStep.run, [ @@ -577,8 +604,8 @@ describe("package artifact reuse", () => { '-f harness_ref="$TARGET_SHA"', 'args=(-f package_spec="${PACKAGE_SPEC:-openclaw@beta}"', 'if [[ -z "${PACKAGE_SPEC// }" ]]; then', - "-f package_artifact_name=release-package-under-test", - '-f package_artifact_run_id="$RELEASE_CHECKS_RUN_ID"', + '-f package_artifact_name="$PACKAGE_ARTIFACT_NAME"', + '-f package_artifact_run_id="${GITHUB_RUN_ID}"', '-f package_label="full-release-${TARGET_SHA:0:12}"', 'args+=(-f scenario="$SCENARIO")', ]); @@ -602,7 +629,7 @@ describe("package artifact reuse", () => { expectTextToIncludeAll(workflow, [ "Published-package Telegram E2E:", - "Package Telegram E2E: release package artifact from \\`OpenClaw Release Checks\\`", + "Package Telegram E2E: parent \\`release-package-under-test\\` artifact", "Package Telegram E2E: skipped unless \\`release_profile=full\\` or \\`npm_telegram_package_spec\\` is provided", ]); expect(releaseDocs).toContain( diff --git a/test/scripts/plugin-prerelease-test-plan.test.ts b/test/scripts/plugin-prerelease-test-plan.test.ts index 884f8ee0b92..c7172358bac 100644 --- a/test/scripts/plugin-prerelease-test-plan.test.ts +++ b/test/scripts/plugin-prerelease-test-plan.test.ts @@ -344,6 +344,7 @@ describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => { "normal_ci", "plugin_prerelease", "release_checks", + "prepare_release_package", "npm_telegram", "summary", ]) {