name: CI phone notification demo

on:
  workflow_dispatch:
    inputs:
      fail_demo:
        description: Fail the harmless demo task
        type: boolean
        default: true

permissions: {}

jobs:
  task:
    runs-on: ubuntu-latest
    steps:
      - name: Demo task (replace with your build or test steps)
        env:
          FAIL_DEMO: ${{ inputs.fail_demo }}
        shell: bash
        run: |
          if [[ "$FAIL_DEMO" == "true" ]]; then
            echo "Intentional demo failure"
            exit 1
          fi
          echo "Demo succeeded"

      - name: Notify phone on failure
        if: ${{ failure() }}
        continue-on-error: true
        timeout-minutes: 3
        env:
          NTFYX_WEBHOOK_URL: ${{ secrets.NTFYX_WEBHOOK_URL }}
          TASK_RESULT: ${{ job.status }}
        shell: bash
        run: |
          python3 - <<'PY'
          import datetime, email.utils, hashlib, json, os, sys, time
          import urllib.error, urllib.parse, urllib.request

          def stop(message):
              print("::warning::Ntfyx: " + message)
              sys.exit(1)

          url = os.environ.get("NTFYX_WEBHOOK_URL", "")
          parsed = urllib.parse.urlsplit(url)
          if parsed.scheme != "https" or parsed.hostname != "api.ntfyx.me":
              stop("Set NTFYX_WEBHOOK_URL to the complete production HTTPS URL copied from the app.")
          run_id = os.environ["GITHUB_RUN_ID"]
          attempt = os.environ["GITHUB_RUN_ATTEMPT"]
          repository = os.environ["GITHUB_REPOSITORY"]
          run_url = f"{os.environ['GITHUB_SERVER_URL']}/{repository}/actions/runs/{run_id}"
          payload = json.dumps({
              "title": "CI " + os.environ["TASK_RESULT"],
              "text": f"{repository}\nRun {run_id}, attempt {attempt}\n{run_url}",
              "session_id": hashlib.sha256(f"github-{repository}-{run_id}".encode()).hexdigest(),
              "session_name": "GitHub Actions",
          }).encode("utf-8")
          key = hashlib.sha256(f"github-{repository}-{run_id}-{attempt}-task-result".encode()).hexdigest()
          class NoRedirect(urllib.request.HTTPRedirectHandler):
              def redirect_request(self, *args, **kwargs):
                  return None
          opener = urllib.request.build_opener(NoRedirect)
          for index in range(3):
              delay = 5 * (index + 1)
              request = urllib.request.Request(url, data=payload, method="POST", headers={
                  "Content-Type": "application/json", "Idempotency-Key": key,
              })
              try:
                  with opener.open(request, timeout=15) as response:
                      if not 200 <= response.status < 300:
                          stop("Unexpected response; inspect the sender execution.")
                  print("Ntfyx accepted the message; verify receipt separately on your phone.")
                  break
              except urllib.error.HTTPError as error:
                  if error.code not in (408, 429, 500, 502, 503, 504):
                      stop(f"HTTP {error.code}; check configuration before retrying.")
                  retry_after = error.headers.get("Retry-After")
                  if retry_after:
                      try:
                          delay = max(delay, float(retry_after))
                      except ValueError:
                          try:
                              retry_at = email.utils.parsedate_to_datetime(retry_after)
                              delay = max(delay, (retry_at - datetime.datetime.now(datetime.timezone.utc)).total_seconds())
                          except (TypeError, ValueError):
                              stop("Invalid Retry-After; inspect the response before retrying.")
              except (urllib.error.URLError, TimeoutError, OSError):
                  pass  # Outcome unknown: preserve this payload and key.
              if index == 2 or delay > 60:
                  stop("Send unconfirmed. Inspect the phone and sender before a retry; retain the original key and body.")
              time.sleep(delay)
          PY
