# .github/workflows/keep-alive.yml
# Keeps a free Supabase project from pausing: one real database read a day through the REST API.
# Repository secrets: SUPABASE_URL (https://<ref>.supabase.co) and SUPABASE_ANON_KEY (anon public key).
# No marketplace action, nothing to update: plain bash and curl.
name: Keep Supabase alive

on:
  schedule:
    - cron: "17 6 * * *"   # daily, 06:17 UTC; avoid :00, GitHub's busiest minute
  workflow_dispatch:        # lets you run it by hand from the Actions tab

permissions: {}

jobs:
  ping:
    runs-on: ubuntu-latest
    steps:
      - name: Read one row through the REST API
        env:
          SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
          SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
          TABLE: keepalive   # any small table; RLS with no anon policy is fine, the read returns []
        run: |
          set -u
          url="${SUPABASE_URL%/}"
          host="${url#*://}"
          path="/rest/v1/${TABLE}?select=*&limit=1"
          attempt=0
          delay=2
          while :; do
            attempt=$((attempt + 1))
            code=$(curl -sS -o body.txt -w '%{http_code}' --max-time 20 \
              -H "apikey: $SUPABASE_ANON_KEY" \
              -H "Authorization: Bearer $SUPABASE_ANON_KEY" \
              -H "Accept: application/json" \
              "$url$path") || code=000
            echo "GET $path -> HTTP $code (attempt $attempt)"
            case "$code" in
              540) break ;;                       # paused: retrying cannot help
              000|429|5[0-9][0-9])                # network error, rate limit, server error: retry
                if [ "$attempt" -le 3 ]; then
                  echo "  transient, retrying in ${delay}s"
                  sleep "$delay"
                  delay=$((delay * 2))
                  continue
                fi
                ;;
            esac
            break
          done
          case "$code" in
            2*)  title="ok" ;;
            540) title="project is PAUSED" ;;
            *)   title="failed" ;;
          esac
          {
            echo "## Supabase keep-alive: $title"
            echo
            echo "Project: \`$host\`  "
            echo "Time: $(date -u +'%Y-%m-%d %H:%M:%S UTC')  "
            echo "Request: \`GET $path\` -> HTTP $code after $attempt attempt(s)"
            if [ "$code" = "540" ]; then
              echo
              echo "Restore it in the Supabase dashboard: open the project and click **Restore project**. Free projects can be restored for one year after pausing."
            fi
          } >> "${GITHUB_STEP_SUMMARY:-/dev/null}"
          case "$code" in
            2*)
              echo "ok: $host answered, the project is awake"
              exit 0 ;;
            540)
              echo "::error::$host answered HTTP 540: the project is paused. Restore it in the Supabase dashboard (Restore project); a workflow cannot unpause it."
              exit 1 ;;
            401|403)
              echo "::error::anon key rejected by $host (HTTP $code). Check that SUPABASE_ANON_KEY belongs to this project."
              exit 1 ;;
            404)
              echo "::error::table '$TABLE' not found through the REST API (HTTP 404). Create it (see the SQL on the page) or change TABLE."
              exit 1 ;;
            000)
              echo "::error::could not reach $host (DNS, TLS or timeout after $attempt attempts). Check SUPABASE_URL."
              exit 1 ;;
            *)
              echo "::error::$host answered HTTP $code: $(tr -d '\n' < body.txt | cut -c1-200)"
              exit 1 ;;
          esac
