name: Pre-deploy validation (8 checks)

# Цель: воспроизвести 8 проверок project-local агента `prod-deploy-validator`
# (#85) через GitHub Actions Azure runner — обход YC backbone-фильтра,
# который блокирует direct SSH с dev-IP 89.144.17.119.
#
# Запускается вручную: gh workflow run pre-deploy-checks.yml
# Read-only — ничего не меняет на проде.
#
# 8 checks (per Pravila §2.4 / agent .claude/agents/prod-deploy-validator.md):
#   1. config:cache владелец (quirk 107 — должен быть www-data:www-data, не root)
#   2. .env line endings (CRLF → артефакты)
#   3. свободное место (< 80% использовано)
#   4. свежесть бэкапа БД (≤ 24ч)
#   5. health очереди liderra-queue (active + queue length < 1000)
#   6. nginx syntax (nginx -t)
#   7. fail2ban active (service running)
#   8. pending миграции (php artisan migrate:status — для текущего deploy ожидается 0)
#
# Использует тот же LIDERRA_SSH_KEY что и deploy.yml.

on:
  workflow_dispatch:

jobs:
  preflight:
    runs-on: ubuntu-latest
    timeout-minutes: 5

    env:
      LIDERRA_HOST: 111.88.246.137
      LIDERRA_USER: ubuntu
      APP_DIR: /var/www/liderra/app

    steps:
      - name: Setup SSH key
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.LIDERRA_SSH_KEY }}" > ~/.ssh/liderra_deploy
          chmod 600 ~/.ssh/liderra_deploy
          ssh-keyscan -H ${{ env.LIDERRA_HOST }} >> ~/.ssh/known_hosts 2>/dev/null

      - name: Run 8 pre-flight checks on prod
        id: checks
        run: |
          ssh -i ~/.ssh/liderra_deploy ${{ env.LIDERRA_USER }}@${{ env.LIDERRA_HOST }} \
            "APP_DIR='${APP_DIR}' bash -s" <<'REMOTE' | tee /tmp/preflight.log
            set +e
            FAILS=0

            echo "=== Check 1: config:cache file owner (quirk 107) ==="
            CFG_FILE="${APP_DIR}/bootstrap/cache/config.php"
            if sudo test -f "$CFG_FILE"; then
              OWNER=$(sudo stat -c '%U:%G' "$CFG_FILE")
              echo "  Owner: $OWNER"
              if [ "$OWNER" = "www-data:www-data" ]; then
                echo "  ✓ PASS"
              else
                echo "  ✗ FAIL — expected www-data:www-data (quirk 107: prod incident 24.05.2026)"
                FAILS=$((FAILS+1))
              fi
            else
              echo "  ~ SKIP — config.php не существует (будет создан deploy'ем)"
            fi
            echo

            echo "=== Check 2: .env line endings (no CRLF) ==="
            ENV_FILE="${APP_DIR}/.env"
            if sudo test -f "$ENV_FILE"; then
              CRLF_COUNT=$(sudo grep -c $'\r' "$ENV_FILE" 2>/dev/null || echo "0")
              echo "  CRLF chars: $CRLF_COUNT"
              if [ "$CRLF_COUNT" = "0" ]; then
                echo "  ✓ PASS"
              else
                echo "  ✗ FAIL — .env содержит CRLF ($CRLF_COUNT строк)"
                FAILS=$((FAILS+1))
              fi
            else
              echo "  ✗ FAIL — .env not found"
              FAILS=$((FAILS+1))
            fi
            echo

            echo "=== Check 3: free disk space (< 80% used) ==="
            DF_USED=$(df / | tail -1 | awk '{print $5}' | tr -d '%')
            echo "  Used: ${DF_USED}%"
            if [ "$DF_USED" -lt 80 ]; then
              echo "  ✓ PASS"
            else
              echo "  ✗ FAIL — корневой раздел ${DF_USED}% (>=80%)"
              FAILS=$((FAILS+1))
            fi
            echo

            echo "=== Check 4: pre-deploy backup freshness (≤ 24h) ==="
            # deploy.yml saves app pre-deploy backups to /home/ubuntu/deploy-backups/
            BACKUP_DIR="/home/ubuntu/deploy-backups"
            if sudo test -d "$BACKUP_DIR"; then
              LATEST=$(sudo find "$BACKUP_DIR" -name 'app-pre-deploy-*.tgz' -mmin -1440 2>/dev/null | sort -r | head -1)
              if [ -n "$LATEST" ]; then
                MTIME=$(sudo stat -c '%y' "$LATEST" 2>/dev/null)
                echo "  Latest: $LATEST ($MTIME)"
                echo "  ✓ PASS"
              else
                ANY_LATEST=$(sudo find "$BACKUP_DIR" -name 'app-pre-deploy-*.tgz' 2>/dev/null | sort -r | head -1)
                if [ -n "$ANY_LATEST" ]; then
                  ANY_MTIME=$(sudo stat -c '%y' "$ANY_LATEST" 2>/dev/null)
                  echo "  i NOTE — backups exist но >24h ($ANY_LATEST, $ANY_MTIME). Не блокер deploy'а — deploy.yml сам делает свежий backup перед раскаткой."
                else
                  echo "  i NOTE — нет pre-deploy бэкапов в $BACKUP_DIR. Не блокер — deploy.yml создаст backup сам."
                fi
              fi
            else
              echo "  i NOTE — backup dir $BACKUP_DIR не существует (первый deploy?). deploy.yml создаст dir."
            fi
            echo

            echo "=== Check 5: queue health (liderra-queue active + depth) ==="
            QUEUE_STATUS=$(systemctl is-active liderra-queue 2>&1)
            echo "  Service: $QUEUE_STATUS"
            if [ "$QUEUE_STATUS" = "active" ]; then
              echo "  ✓ PASS (service active)"
            else
              echo "  ✗ FAIL — liderra-queue не active"
              FAILS=$((FAILS+1))
            fi
            # NB: queue depth check would need Redis access; skipped (not critical for this deploy)
            echo

            echo "=== Check 6: nginx syntax ==="
            NGINX_TEST=$(sudo nginx -t 2>&1)
            echo "$NGINX_TEST" | sed 's/^/  /'
            if echo "$NGINX_TEST" | grep -q "syntax is ok" && echo "$NGINX_TEST" | grep -q "test is successful"; then
              echo "  ✓ PASS"
            else
              echo "  ✗ FAIL — nginx syntax error"
              FAILS=$((FAILS+1))
            fi
            echo

            echo "=== Check 7: fail2ban active ==="
            F2B_STATUS=$(systemctl is-active fail2ban 2>&1)
            echo "  Service: $F2B_STATUS"
            if [ "$F2B_STATUS" = "active" ]; then
              echo "  ✓ PASS"
            else
              echo "  ✗ FAIL — fail2ban не active"
              FAILS=$((FAILS+1))
            fi
            echo

            echo "=== Check 8: pending migrations ==="
            cd "${APP_DIR}"
            MIG_STATUS=$(sudo -u www-data php artisan migrate:status 2>&1)
            PENDING=$(echo "$MIG_STATUS" | grep -c "Pending")
            echo "  Pending count: $PENDING"
            if [ "$PENDING" = "0" ]; then
              echo "  ✓ PASS — 0 pending migrations"
            else
              echo "  i NOTE — $PENDING pending migrations (deploy.yml runs them automatically)"
              # NB: Pending miграции — это НЕ FAIL для этого deploy (план не включает миграции;
              # deploy.yml выполнит их сам). Помечается как INFO, не FAIL.
            fi
            echo

            echo "=== SUMMARY ==="
            echo "Total failures: $FAILS"
            if [ "$FAILS" = "0" ]; then
              echo "VERDICT: GO"
              exit 0
            else
              echo "VERDICT: NO-GO ($FAILS check(s) failed)"
              exit 1
            fi
          REMOTE
          REMOTE_EXIT=$?
          echo "remote_exit=$REMOTE_EXIT" >> "$GITHUB_OUTPUT"

      - name: Print summary
        if: always()
        run: |
          {
            echo "## Pre-deploy 8-check validation for liderra.ru"
            echo
            echo '```'
            cat /tmp/preflight.log 2>/dev/null || echo "(no log captured)"
            echo '```'
          } >> "$GITHUB_STEP_SUMMARY"

      - name: Cleanup SSH key
        if: always()
        run: rm -f ~/.ssh/liderra_deploy
