name: Update release badges

# Coeus is a PRIVATE repo, so the native shields.io GitHub-release badge
# (img.shields.io/github/v/release/...) cannot read it and renders
# "repo not found / no releases". Instead we drive shields.io ENDPOINT
# badges from a public Gist that this workflow updates on every release.
#
# Gist (public): https://gist.github.com/keithceh/9d9181a0691bac7053e355ade3e9bd01
#   - coeus-version.json        → "release"       badge (e.g. v3.2.0)
#   - coeus-release-date.json   → "released"      badge (YYYY-MM-DD)
#   - coeus-release-count.json  → "release count" badge (total Releases published)
#
# REQUIRED SECRET: GIST_TOKEN — a PAT (classic: scope `gist`; or fine-grained
# with Gists: Read and write) belonging to the gist owner (keithceh).
# Add it under: repo → Settings → Secrets and variables → Actions.
#
# Security notes:
#  - All values pulled from release events (tag_name, published_at, etc.) are
#    passed via env vars instead of being interpolated into `run:` shell. This
#    prevents code injection if a release name or tag ever contains shell
#    metacharacters. (The tag is collaborator-controlled in a private repo, so
#    blast radius is small, but the discipline is cheap.)
#  - The actions/checkout action is intentionally NOT used — this workflow
#    only reads from the GitHub API; checking out the repo would waste time
#    and broaden the token surface for no benefit.

on:
  release:
    types: [published]
  workflow_dispatch:

env:
  GIST_ID: 9d9181a0691bac7053e355ade3e9bd01

jobs:
  badge:
    runs-on: ubuntu-latest
    permissions:
      contents: read   # read-only is enough; we only fetch releases via API
    steps:
      - name: Resolve latest release version, date, and total count
        id: meta
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          EVENT_NAME: ${{ github.event_name }}
          RELEASE_TAG: ${{ github.event.release.tag_name }}
          RELEASE_DATE: ${{ github.event.release.published_at }}
          REPO_FULL: ${{ github.repository }}
        run: |
          set -eu

          if [ "${EVENT_NAME}" = "release" ]; then
            VERSION="${RELEASE_TAG}"
            DATE="${RELEASE_DATE}"
          else
            LATEST=$(curl -sSL --fail-with-body \
              -H "Authorization: Bearer ${GITHUB_TOKEN}" \
              -H "Accept: application/vnd.github+json" \
              -H "X-GitHub-Api-Version: 2022-11-28" \
              "https://api.github.com/repos/${REPO_FULL}/releases/latest" 2>/dev/null) \
              || LATEST='{}'
            VERSION=$(printf '%s' "${LATEST}" | jq -r '.tag_name // "none"')
            DATE=$(printf '%s' "${LATEST}" | jq -r '.published_at // ""')
          fi

          # Normalise date to YYYY-MM-DD (strip the time component)
          DATE_YMD="${DATE%%T*}"
          [ -z "${DATE_YMD}" ] && DATE_YMD="$(date -u +%Y-%m-%d)"

          # Count all published Releases: page through /releases?per_page=100
          # and sum lengths. Cheap (one or two pages for almost any repo).
          COUNT=0
          PAGE=1
          while :; do
            BATCH=$(curl -sSL --fail-with-body \
              -H "Authorization: Bearer ${GITHUB_TOKEN}" \
              -H "Accept: application/vnd.github+json" \
              -H "X-GitHub-Api-Version: 2022-11-28" \
              "https://api.github.com/repos/${REPO_FULL}/releases?per_page=100&page=${PAGE}")
            N=$(printf '%s' "${BATCH}" | jq 'length')
            COUNT=$((COUNT + N))
            if [ "${N}" -lt 100 ]; then break; fi
            PAGE=$((PAGE + 1))
            if [ "${PAGE}" -gt 50 ]; then
              echo "✗ Aborting at page 50 — guard against runaway pagination."
              break
            fi
          done

          {
            echo "version=${VERSION}"
            echo "date=${DATE_YMD}"
            echo "count=${COUNT}"
          } >> "${GITHUB_OUTPUT}"
          echo "Resolved: version=${VERSION} date=${DATE_YMD} count=${COUNT}"

      - name: Update badge gist
        env:
          GIST_TOKEN: ${{ secrets.GIST_TOKEN }}
          VERSION: ${{ steps.meta.outputs.version }}
          DATE: ${{ steps.meta.outputs.date }}
          COUNT: ${{ steps.meta.outputs.count }}
        run: |
          set -eu

          VJSON=$(jq -nc --arg m "${VERSION}"        '{schemaVersion:1,label:"release",       message:$m,color:"brightgreen"}')
          DJSON=$(jq -nc --arg m "${DATE}"           '{schemaVersion:1,label:"released",      message:$m,color:"blue"}')
          CJSON=$(jq -nc --arg m "${COUNT} total"    '{schemaVersion:1,label:"release count", message:$m,color:"informational"}')

          jq -nc --arg v "${VJSON}" --arg d "${DJSON}" --arg c "${CJSON}" \
            '{files:{
                "coeus-version.json":       {content:$v},
                "coeus-release-date.json":  {content:$d},
                "coeus-release-count.json": {content:$c}
            }}' > /tmp/gist-payload.json

          HTTP=$(curl -sS -o /tmp/gist-resp.json -w "%{http_code}" -X PATCH \
            -H "Authorization: Bearer ${GIST_TOKEN}" \
            -H "Accept: application/vnd.github+json" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            "https://api.github.com/gists/${GIST_ID}" \
            -d @/tmp/gist-payload.json)

          if [ "${HTTP}" != "200" ]; then
            echo "✗ Gist update failed (HTTP ${HTTP}):"
            cat /tmp/gist-resp.json
            exit 1
          fi
          echo "✅ Badge gist updated → release=${VERSION}, released=${DATE}, count=${COUNT}"
