From 1b1916053f9c7692c02990a8c8f23014e77ca80b Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 14:03:17 +0100 Subject: [PATCH] ci: inline Docker release planning for old refs --- .../openclaw-live-and-e2e-checks-reusable.yml | 198 +++++++++++++++--- .../package-acceptance-workflow.test.ts | 11 +- 2 files changed, 177 insertions(+), 32 deletions(-) diff --git a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml index 2f92b9c2809..d160b3d1d70 100644 --- a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml +++ b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml @@ -519,14 +519,67 @@ jobs: - name: Hydrate live auth/profile inputs run: bash scripts/ci-hydrate-live-auth.sh - - name: Plan and hydrate Docker E2E chunk + - name: Plan Docker E2E chunk id: plan - uses: ./.github/actions/docker-e2e-plan + shell: bash + env: + CHUNK: ${{ matrix.chunk_id }} + INCLUDE_OPENWEBUI: ${{ inputs.include_openwebui }} + run: | + set -euo pipefail + if [[ -z "$CHUNK" ]]; then + echo "chunk input is required for Docker E2E chunk planning." >&2 + exit 1 + fi + + mkdir -p .artifacts/docker-tests + export OPENCLAW_DOCKER_ALL_PROFILE=release-path + export OPENCLAW_DOCKER_ALL_CHUNK="$CHUNK" + export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI" + + plan_path=".artifacts/docker-tests/release-${CHUNK}-plan.json" + node scripts/test-docker-all.mjs --plan-json > "$plan_path" + node scripts/docker-e2e.mjs github-outputs "$plan_path" >> "$GITHUB_OUTPUT" + echo "plan_json=$plan_path" >> "$GITHUB_OUTPUT" + + - name: Download OpenClaw Docker E2E package + if: steps.plan.outputs.needs_package == '1' + uses: actions/download-artifact@v8 with: - mode: chunk - chunk: ${{ matrix.chunk_id }} - include-openwebui: ${{ inputs.include_openwebui }} - package-artifact-name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }} + name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }} + path: .artifacts/docker-e2e-package + + - name: Pull shared bare Docker E2E image + if: steps.plan.outputs.needs_bare_image == '1' + shell: bash + run: | + set -euo pipefail + docker pull "${OPENCLAW_DOCKER_E2E_BARE_IMAGE}" + + - name: Pull shared functional Docker E2E image + if: steps.plan.outputs.needs_functional_image == '1' + shell: bash + run: | + set -euo pipefail + docker pull "${OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE}" + + - name: Validate Docker E2E credentials + shell: bash + env: + CREDENTIALS: ${{ steps.plan.outputs.credentials }} + run: | + set -euo pipefail + credentials=",$CREDENTIALS," + if [[ "$credentials" == *",openai,"* ]]; then + [[ -n "${OPENAI_API_KEY:-}" ]] || { + echo "OPENAI_API_KEY is required for selected Docker E2E lanes." >&2 + exit 1 + } + fi + if [[ "$credentials" == *",anthropic,"* && -z "${ANTHROPIC_API_TOKEN:-}" && -z "${ANTHROPIC_API_KEY:-}" ]]; then + echo "ANTHROPIC_API_TOKEN or ANTHROPIC_API_KEY is required for selected Docker E2E lanes." >&2 + exit 1 + fi - name: Run Docker E2E chunk shell: bash @@ -648,14 +701,66 @@ jobs: - name: Hydrate live auth/profile inputs run: bash scripts/ci-hydrate-live-auth.sh - - name: Plan and hydrate targeted Docker E2E lanes + - name: Plan targeted Docker E2E lanes id: plan - uses: ./.github/actions/docker-e2e-plan + shell: bash + env: + LANES: ${{ inputs.docker_lanes }} + INCLUDE_OPENWEBUI: ${{ inputs.include_openwebui }} + run: | + set -euo pipefail + if [[ -z "$LANES" ]]; then + echo "lanes input is required for Docker E2E targeted planning." >&2 + exit 1 + fi + + mkdir -p .artifacts/docker-tests + export OPENCLAW_DOCKER_ALL_LANES="$LANES" + export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI" + + plan_path=".artifacts/docker-tests/targeted-plan.json" + node scripts/test-docker-all.mjs --plan-json > "$plan_path" + node scripts/docker-e2e.mjs github-outputs "$plan_path" >> "$GITHUB_OUTPUT" + echo "plan_json=$plan_path" >> "$GITHUB_OUTPUT" + + - name: Download OpenClaw Docker E2E package + if: steps.plan.outputs.needs_package == '1' + uses: actions/download-artifact@v8 with: - mode: targeted - lanes: ${{ inputs.docker_lanes }} - include-openwebui: ${{ inputs.include_openwebui }} - package-artifact-name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }} + name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }} + path: .artifacts/docker-e2e-package + + - name: Pull shared bare Docker E2E image + if: steps.plan.outputs.needs_bare_image == '1' + shell: bash + run: | + set -euo pipefail + docker pull "${OPENCLAW_DOCKER_E2E_BARE_IMAGE}" + + - name: Pull shared functional Docker E2E image + if: steps.plan.outputs.needs_functional_image == '1' + shell: bash + run: | + set -euo pipefail + docker pull "${OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE}" + + - name: Validate Docker E2E credentials + shell: bash + env: + CREDENTIALS: ${{ steps.plan.outputs.credentials }} + run: | + set -euo pipefail + credentials=",$CREDENTIALS," + if [[ "$credentials" == *",openai,"* ]]; then + [[ -n "${OPENAI_API_KEY:-}" ]] || { + echo "OPENAI_API_KEY is required for selected Docker E2E lanes." >&2 + exit 1 + } + fi + if [[ "$credentials" == *",anthropic,"* && -z "${ANTHROPIC_API_TOKEN:-}" && -z "${ANTHROPIC_API_KEY:-}" ]]; then + echo "ANTHROPIC_API_TOKEN or ANTHROPIC_API_KEY is required for selected Docker E2E lanes." >&2 + exit 1 + fi - name: Run targeted Docker E2E lanes shell: bash @@ -740,14 +845,41 @@ jobs: exit 1 } - - name: Plan and hydrate Open WebUI Docker E2E chunk + - name: Plan Open WebUI Docker E2E chunk id: plan - uses: ./.github/actions/docker-e2e-plan + shell: bash + run: | + set -euo pipefail + mkdir -p .artifacts/docker-tests + export OPENCLAW_DOCKER_ALL_PROFILE=release-path + export OPENCLAW_DOCKER_ALL_CHUNK=openwebui + export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI=true + + plan_path=".artifacts/docker-tests/release-openwebui-plan.json" + node scripts/test-docker-all.mjs --plan-json > "$plan_path" + node scripts/docker-e2e.mjs github-outputs "$plan_path" >> "$GITHUB_OUTPUT" + echo "plan_json=$plan_path" >> "$GITHUB_OUTPUT" + + - name: Download OpenClaw Docker E2E package + if: steps.plan.outputs.needs_package == '1' + uses: actions/download-artifact@v8 with: - mode: chunk - chunk: openwebui - include-openwebui: "true" - package-artifact-name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }} + name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }} + path: .artifacts/docker-e2e-package + + - name: Pull shared bare Docker E2E image + if: steps.plan.outputs.needs_bare_image == '1' + shell: bash + run: | + set -euo pipefail + docker pull "${OPENCLAW_DOCKER_E2E_BARE_IMAGE}" + + - name: Pull shared functional Docker E2E image + if: steps.plan.outputs.needs_functional_image == '1' + shell: bash + run: | + set -euo pipefail + docker pull "${OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE}" - name: Run Open WebUI Docker E2E chunk shell: bash @@ -815,13 +947,29 @@ jobs: - name: Plan Docker E2E images id: plan - uses: ./.github/actions/docker-e2e-plan - with: - mode: prepare - lanes: ${{ inputs.docker_lanes }} - include-release-path-suites: ${{ inputs.include_release_path_suites }} - include-openwebui: ${{ inputs.include_openwebui }} - hydrate-artifacts: "false" + shell: bash + env: + LANES: ${{ inputs.docker_lanes }} + INCLUDE_RELEASE_PATH_SUITES: ${{ inputs.include_release_path_suites }} + INCLUDE_OPENWEBUI: ${{ inputs.include_openwebui }} + run: | + set -euo pipefail + mkdir -p .artifacts/docker-tests + + if [[ "$INCLUDE_RELEASE_PATH_SUITES" == "true" ]]; then + export OPENCLAW_DOCKER_ALL_PROFILE=release-path + export OPENCLAW_DOCKER_ALL_PLAN_RELEASE_ALL=1 + elif [[ -n "$LANES" ]]; then + export OPENCLAW_DOCKER_ALL_LANES="$LANES" + elif [[ "$INCLUDE_OPENWEBUI" == "true" ]]; then + export OPENCLAW_DOCKER_ALL_LANES=openwebui + fi + export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI" + + plan_path=".artifacts/docker-tests/plan.json" + node scripts/test-docker-all.mjs --plan-json > "$plan_path" + node scripts/docker-e2e.mjs github-outputs "$plan_path" >> "$GITHUB_OUTPUT" + echo "plan_json=$plan_path" >> "$GITHUB_OUTPUT" - name: Setup Node environment if: steps.plan.outputs.needs_package == '1' && inputs.package_artifact_name == '' && inputs.package_artifact_run_id == '' diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index 96b234b6167..5e1ed578fb4 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -3,7 +3,6 @@ import { describe, expect, it } from "vitest"; const PACKAGE_ACCEPTANCE_WORKFLOW = ".github/workflows/package-acceptance.yml"; const LIVE_E2E_WORKFLOW = ".github/workflows/openclaw-live-and-e2e-checks-reusable.yml"; -const DOCKER_E2E_PLAN_ACTION = ".github/actions/docker-e2e-plan/action.yml"; const NPM_TELEGRAM_WORKFLOW = ".github/workflows/npm-telegram-beta-e2e.yml"; const RELEASE_CHECKS_WORKFLOW = ".github/workflows/openclaw-release-checks.yml"; const FULL_RELEASE_VALIDATION_WORKFLOW = ".github/workflows/full-release-validation.yml"; @@ -58,7 +57,6 @@ describe("package acceptance workflow", () => { describe("package artifact reuse", () => { it("lets reusable Docker E2E consume an already resolved package artifact", () => { const workflow = readFileSync(LIVE_E2E_WORKFLOW, "utf8"); - const action = readFileSync(DOCKER_E2E_PLAN_ACTION, "utf8"); expect(workflow).toContain("package_artifact_name:"); expect(workflow).toContain("package_artifact_run_id:"); @@ -74,11 +72,10 @@ describe("package artifact reuse", () => { expect(workflow).toContain( 'functional_image="${PROVIDED_FUNCTIONAL_IMAGE:-ghcr.io/${repository}-docker-e2e-functional:${image_tag}}"', ); - expect(workflow).toContain( - "package-artifact-name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }}", - ); - expect(action).toContain("package-artifact-name:"); - expect(action).toContain("name: ${{ inputs.package-artifact-name }}"); + expect(workflow).toContain("name: ${{ inputs.package_artifact_name || 'docker-e2e-package' }}"); + expect(workflow).not.toContain("uses: ./.github/actions/docker-e2e-plan"); + expect(workflow).toContain("node scripts/test-docker-all.mjs --plan-json"); + expect(workflow).toContain("node scripts/docker-e2e.mjs github-outputs"); }); it("uses Blacksmith Docker build caching for prepared E2E images", () => {