name: Docker E2E plan and hydrate
description: >
  Create a Docker E2E lane plan, expose GitHub outputs, and optionally hydrate
  the prebuilt package artifact plus shared Docker images needed by the plan.
inputs:
  mode:
    description: prepare, chunk, or targeted.
    required: true
  chunk:
    description: Release-path chunk for mode=chunk.
    required: false
    default: ""
  lanes:
    description: Comma/space separated lane names for targeted or prepare mode.
    required: false
    default: ""
  include-openwebui:
    description: Whether Open WebUI is included when planning release/prepare coverage.
    required: false
    default: "true"
  include-release-path-suites:
    description: Whether prepare mode should plan all release-path suites.
    required: false
    default: "false"
  hydrate-artifacts:
    description: Whether to download/pull artifacts required by the plan.
    required: false
    default: "true"
  package-artifact-name:
    description: Workflow artifact name containing openclaw-current.tgz.
    required: false
    default: docker-e2e-package
outputs:
  credentials:
    description: Comma-separated credential groups required by selected lanes.
    value: ${{ steps.plan.outputs.credentials }}
  needs_bare_image:
    description: "1 when selected lanes require the bare Docker E2E image."
    value: ${{ steps.plan.outputs.needs_bare_image }}
  needs_e2e_image:
    description: "1 when selected lanes require any Docker E2E image."
    value: ${{ steps.plan.outputs.needs_e2e_image }}
  needs_functional_image:
    description: "1 when selected lanes require the functional Docker E2E image."
    value: ${{ steps.plan.outputs.needs_functional_image }}
  needs_live_image:
    description: "1 when selected lanes require building the live Docker image."
    value: ${{ steps.plan.outputs.needs_live_image }}
  needs_package:
    description: "1 when selected lanes require the OpenClaw package tarball."
    value: ${{ steps.plan.outputs.needs_package }}
  plan_json:
    description: Path to the generated plan JSON.
    value: ${{ steps.plan.outputs.plan_json }}
runs:
  using: composite
  steps:
    - name: Plan Docker E2E lanes
      id: plan
      shell: bash
      env:
        MODE: ${{ inputs.mode }}
        CHUNK: ${{ inputs.chunk }}
        LANES: ${{ inputs.lanes }}
        INCLUDE_OPENWEBUI: ${{ inputs.include-openwebui }}
        INCLUDE_RELEASE_PATH_SUITES: ${{ inputs.include-release-path-suites }}
      run: |
        set -euo pipefail
        mkdir -p .artifacts/docker-tests

        case "$MODE" in
          prepare)
            plan_path=".artifacts/docker-tests/plan.json"
            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
            ;;
          chunk)
            if [[ -z "$CHUNK" ]]; then
              echo "chunk input is required for Docker E2E chunk planning." >&2
              exit 1
            fi
            export OPENCLAW_DOCKER_ALL_PROFILE=release-path
            export OPENCLAW_DOCKER_ALL_CHUNK="$CHUNK"
            plan_path=".artifacts/docker-tests/release-${CHUNK}-plan.json"
            ;;
          targeted)
            if [[ -z "$LANES" ]]; then
              echo "lanes input is required for Docker E2E targeted planning." >&2
              exit 1
            fi
            if [[ "$INCLUDE_RELEASE_PATH_SUITES" == "true" ]]; then
              export OPENCLAW_DOCKER_ALL_PROFILE=release-path
            fi
            export OPENCLAW_DOCKER_ALL_LANES="$LANES"
            plan_path=".artifacts/docker-tests/targeted-plan.json"
            ;;
          *)
            echo "mode must be prepare, chunk, or targeted. Got: $MODE" >&2
            exit 1
            ;;
        esac

        export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI"
        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: inputs.hydrate-artifacts == 'true' && steps.plan.outputs.needs_package == '1'
      uses: actions/download-artifact@v8
      with:
        name: ${{ inputs.package-artifact-name }}
        path: .artifacts/docker-e2e-package

    - name: Pull shared bare Docker E2E image
      if: inputs.hydrate-artifacts == 'true' && steps.plan.outputs.needs_bare_image == '1'
      shell: bash
      run: |
        set -euo pipefail
        bash scripts/ci-docker-pull-retry.sh "${OPENCLAW_DOCKER_E2E_BARE_IMAGE}"

    - name: Pull shared functional Docker E2E image
      if: inputs.hydrate-artifacts == 'true' && steps.plan.outputs.needs_functional_image == '1'
      shell: bash
      run: |
        set -euo pipefail
        bash scripts/ci-docker-pull-retry.sh "${OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE}"

    - name: Validate Docker E2E credentials
      if: inputs.hydrate-artifacts == 'true'
      shell: bash
      env:
        CREDENTIALS: ${{ steps.plan.outputs.credentials }}
      run: |
        set -euo pipefail
        credentials=",$CREDENTIALS,"
        require_any() {
          local label="$1"
          shift
          local key
          for key in "$@"; do
            if [[ -n "${!key:-}" ]]; then
              return 0
            fi
          done
          echo "Missing credential for ${label}: expected one of $*" >&2
          exit 1
        }
        if [[ "$credentials" == *",openai,"* ]]; then
          require_any OpenAI OPENAI_API_KEY
        fi
        if [[ "$credentials" == *",codex,"* ]]; then
          require_any Codex OPENCLAW_CODEX_AUTH_JSON
        fi
        if [[ "$credentials" == *",anthropic,"* ]]; then
          require_any Anthropic ANTHROPIC_API_TOKEN ANTHROPIC_API_KEY OPENCLAW_CLAUDE_CREDENTIALS_JSON OPENCLAW_CLAUDE_JSON
        fi
        if [[ "$credentials" == *",factory,"* ]]; then
          require_any Factory FACTORY_API_KEY
        fi
        if [[ "$credentials" == *",gemini,"* ]]; then
          require_any Gemini GEMINI_API_KEY GOOGLE_API_KEY OPENCLAW_GEMINI_SETTINGS_JSON
        fi
        if [[ "$credentials" == *",opencode,"* ]]; then
          require_any OpenCode OPENCODE_API_KEY OPENCODE_ZEN_API_KEY
        fi
