name: "OSDC: Drain cluster"

# Manual cordon for an OSDC cluster before maintenance. Two independent
# checkboxes: drain-runners scales every AutoscalingRunnerSet to maxRunners=0
# and waits for in-flight runner pods to finish; taint-nodes applies
# deploy.osdc.io/refresh-pending:NoSchedule to runner nodes so the scheduler
# stops placing new pods on them. Default = both enabled (typical pre-maintenance
# flow). Per-cluster concurrency group serializes against the deploy and plan
# workflows on the same cluster. Reverse with `osdc-undrain.yml`.
on:
  workflow_dispatch:
    inputs:
      cluster:
        description: "Cluster to drain"
        required: true
        type: choice
        default: "-- select cluster --"
        options:
          - "-- select cluster --"
          - meta-staging-aws-uw1
          - meta-staging-aws-ue1
          - meta-staging-aws-ue2
          - meta-prod-aws-uw1
          - meta-prod-aws-ue2
          - meta-prod-aws-ue1
          - lf-prod-aws-ue1
          - lf-prod-aws-ue2
      run_drain_runners:
        description: "Patch AutoscalingRunnerSets to maxRunners=0 and wait for in-flight pods to drain"
        required: false
        type: boolean
        default: true
      run_taint_nodes:
        description: "Taint runner nodes with deploy.osdc.io/refresh-pending:NoSchedule to block new pod scheduling"
        required: false
        type: boolean
        default: true

concurrency:
  group: osdc-tofu-${{ inputs.cluster }}
  cancel-in-progress: false

permissions:
  id-token: write
  contents: read

jobs:
  drain:
    name: Drain ${{ inputs.cluster }}
    runs-on: ubuntu-latest
    environment: ${{ contains(inputs.cluster, '-staging-') && 'osdc-staging' || 'osdc-production' }}
    timeout-minutes: 90
    defaults:
      run:
        working-directory: osdc
    steps:
      - name: Validate inputs
        working-directory: ${{ github.workspace }}
        run: |
          if [ "${{ inputs.cluster }}" = "-- select cluster --" ]; then
            echo "::error::No cluster selected. Pick a cluster from the dropdown before running."
            exit 1
          fi
          if [ "${{ inputs.run_drain_runners }}" != "true" ] && [ "${{ inputs.run_taint_nodes }}" != "true" ]; then
            echo "::error::Both run_drain_runners and run_taint_nodes are disabled — nothing to do."
            exit 1
          fi

      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

      - name: Install just
        uses: extractions/setup-just@f8a3cce218d9f83db3a2ecd90e41ac3de6cdfd9b # v3.1.0

      - name: Install mise
        uses: jdx/mise-action@c37c93293d6b742fc901e1406b8f764f6fb19dac # v2.4.4
        with:
          version: "2026.5.11"
          install: true
          working_directory: osdc

      - name: Install Python dependencies
        run: uv sync

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
        with:
          role-to-assume: ${{ startsWith(inputs.cluster, 'lf-') && secrets.LF_AWS_DEPLOY_ROLE_ARN || format('arn:aws:iam::{0}:role/{1}', secrets.META_AWS_ACC_ID, secrets.META_AWS_DEPLOY_ROLE) }}
          aws-region: us-west-1
          role-duration-seconds: 7200

      - name: Drain runners (maxRunners=0 + wait for in-flight pods)
        if: ${{ inputs.run_drain_runners }}
        run: just drain-runners "${{ inputs.cluster }}"
        env:
          OSDC_TAINT_NODES: "no"

      - name: Sleep 180s for nodes to settle after drain
        if: ${{ !cancelled() && inputs.run_drain_runners && inputs.run_taint_nodes }}
        run: sleep 180

      - name: Taint runner nodes (NoSchedule)
        if: ${{ !cancelled() && inputs.run_taint_nodes }}
        run: just taint-nodes "${{ inputs.cluster }}"
