name: 'Dynamo Graph Deployment Test'
description: 'Deploy a DynamoGraphDeployment to Kubernetes, validate it serves requests, and cleanup'

inputs:
  # Kubernetes Configuration
  kubeconfig_base64:
    description: 'Base64-encoded kubeconfig for cluster access'
    required: true
  namespace:
    description: 'Kubernetes namespace for deployment'
    required: true
  registry:
    description: 'Container registry hostname'
    required: true
  operator_tag:
    description: 'Operator image tag (default: main-operator)'
    required: false
    default: 'main-operator'
  hf_token:
    description: 'HuggingFace token for model access'
    required: false
    default: ''
  dockerhub_username:
    description: 'Docker Hub username for image pull secrets. Required for rerun self-bootstrap if private images are used.'
    required: false
    default: ''
  dockerhub_password:
    description: 'Docker Hub password for image pull secrets. Required for rerun self-bootstrap if private images are used.'
    required: false
    default: ''

  framework:
    description: 'Framework name (vllm, sglang, trtllm)'
    required: false
    default: ''
  profile:
    description: 'Deployment profile (e.g., disagg_router, agg)'
    required: false
    default: ''
  image:
    description: 'Full container image reference for the framework runtime'
    required: false
    default: ''
  platform_arch:
    description: 'Platform architecture (amd64, arm64)'
    required: false
    default: 'amd64'
  test_name:
    description: 'Name for artifact naming. Defaults to {framework}_{profile}.'
    required: false
    default: ''
  extra_pytest_args:
    description: 'Additional pytest arguments (e.g., --frontend-image=...)'
    required: false
    default: ''

runs:
  using: "composite"
  steps:
    - name: Setup Kubeconfig
      id: setup-kubeconfig
      shell: bash
      env:
        NAMESPACE: ${{ inputs.namespace }}
      run: |
        set +x
        echo "${{ inputs.kubeconfig_base64 }}" | base64 -d > ${{ github.workspace }}/.kubeconfig
        chmod 600 ${{ github.workspace }}/.kubeconfig
        echo "KUBECONFIG=${{ github.workspace }}/.kubeconfig" >> $GITHUB_ENV

        export KUBECONFIG=${{ github.workspace }}/.kubeconfig
        kubectl config set-context --current --namespace=${NAMESPACE}
        kubectl config get-contexts

    - name: Set up Python
      uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5.6.0
      with:
        python-version: '3.12'
        cache: 'pip'
        cache-dependency-path: 'container/deps/requirements.test.txt'
    - name: Install test dependencies
      shell: bash
      run: |
        python -m pip install --upgrade pip
        pip install -r container/deps/requirements.test.txt

    - name: Deploy and Test
      id: deploy
      shell: bash
      env:
        KUBECONFIG: ${{ github.workspace }}/.kubeconfig
        NAMESPACE: ${{ inputs.namespace }}
        FRAMEWORK: ${{ inputs.framework }}
        PROFILE: ${{ inputs.profile }}
        IMAGE: ${{ inputs.image }}
        DYN_TEST_OUTPUT_PATH: ${{ github.workspace }}/test-output
        TEST_NAME: ${{ inputs.test_name }}
        EXTRA_PYTEST_ARGS: ${{ inputs.extra_pytest_args }}
        DYNAMO_TEST_FRAMEWORK: ${{ inputs.framework }}
        DYNAMO_TEST_PLATFORM: ${{ inputs.platform_arch }}
        DYNAMO_TEST_TYPE: deploy_${{ inputs.profile }}
        DYNAMO_TEST_WORKFLOW: ${{ github.workflow }}
      run: |
        mkdir -p test-results

        PYTEST_ARGS=""
        if [ -n "${FRAMEWORK}" ]; then
          PYTEST_ARGS+=" --framework=${FRAMEWORK}"
        fi
        if [ -n "${PROFILE}" ]; then
          PYTEST_ARGS+=" --profile=${PROFILE}"
        fi
        if [ -n "${IMAGE}" ]; then
          PYTEST_ARGS+=" --image=${IMAGE}"
        fi

        if [ -z "${TEST_NAME}" ]; then
          TEST_NAME="${FRAMEWORK:-unknown}_${PROFILE:-unknown}"
        fi

        pytest tests/deploy/test_deploy.py \
          --namespace="${NAMESPACE}" \
          ${PYTEST_ARGS} \
          ${EXTRA_PYTEST_ARGS} \
          -v -s \
          --durations=10 \
          --junitxml=test-results/pytest_deploy_${TEST_NAME}_${{ inputs.platform_arch }}_${{ github.run_id }}_${{ job.check_run_id }}.xml \
          --alluredir=test-results/allure-results \
          --log-cli-level=INFO

    - name: Cleanup Deployment
      if: always()
      shell: bash
      env:
        NAMESPACE: ${{ inputs.namespace }}
        GRAPH_NAME: ${{ steps.deploy.outputs.graph_name }}
      run: |
        echo "::group::Cleanup Deployment"
        set -x
        export KUBECONFIG=${{ github.workspace }}/.kubeconfig

        echo "=== PRE-CLEANUP STATUS ==="
        kubectl get dynamographdeployments -n $NAMESPACE || true
        kubectl get pods -n $NAMESPACE || true

        kubectl get dynamographdeployments -n $NAMESPACE --no-headers 2>/dev/null \
          | awk '$2 == "False" {print $1}' \
          | while read -r dep_name; do
              echo ">>> DETAILED DESCRIPTION FOR FAILED DEPLOYMENT: $dep_name"
              kubectl describe dynamographdeployments "$dep_name" -n $NAMESPACE
          done || true

        if kubectl get dynamographdeployments "${GRAPH_NAME}" -n $NAMESPACE &>/dev/null; then
          echo "DGD ${GRAPH_NAME} still exists after test, deleting..."
          kubectl delete dynamographdeployments ${GRAPH_NAME} -n $NAMESPACE --timeout=60s
        else
          echo "DGD ${GRAPH_NAME} already cleaned up by test"
        fi
        echo "::endgroup::"


    - name: Determine test name for artifacts
      id: test-name
      if: always()
      shell: bash
      env:
        TEST_NAME: ${{ inputs.test_name }}
        FRAMEWORK: ${{ inputs.framework }}
        PROFILE: ${{ inputs.profile }}
      run: |
        if [ -z "${TEST_NAME}" ]; then
          TEST_NAME="${FRAMEWORK:-unknown}_${PROFILE:-unknown}"
        fi
        echo "name=${TEST_NAME}" >> $GITHUB_OUTPUT

    - name: Upload Test Results
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f #v6
      if: always()
      with:
        name: test-results-${{ steps.test-name.outputs.name }}-${{ inputs.platform_arch }}-${{ github.run_id }}-${{ job.check_run_id }}
        path: test-results/pytest_deploy_${{ steps.test-name.outputs.name }}_${{ inputs.platform_arch }}_${{ github.run_id }}_${{ job.check_run_id }}.xml
        retention-days: 7

    - name: Upload Pod Logs
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f #v6
      if: always()
      with:
        name: pod-logs-${{ steps.test-name.outputs.name }}-${{ inputs.platform_arch }}-${{ github.run_id }}-${{ job.check_run_id }}
        path: ${{ github.workspace }}/test-output/
        if-no-files-found: warn
        retention-days: 7

    - name: Upload Allure Results
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f #v6
      if: always()
      with:
        name: allure-results-${{ steps.test-name.outputs.name }}-${{ inputs.platform_arch }}-${{ github.run_id }}-${{ job.check_run_id }}
        path: test-results/allure-results/
        retention-days: 7
        if-no-files-found: ignore
