name: promote-stable

# Manual operator gate that retags an existing :vX.Y.Z release as :stable on
# GHCR. Once promoted, the SFU-pool hosts (partner_nodes WHERE in_sfu_pool AND
# healthy — the registry is the source of truth, NOT a list here) auto-pull the
# new version on their next updater-timer fire. See the operator's internal
# SFU auto-update runbook for the full canon.
#
# Why a separate workflow (not auto in release.yml):
#   release.yml runs on every tag push, which means every patch release would
#   immediately become the stable rollout target. We want a deliberate human
#   step ("this version actually got prod traffic and looked OK") between
#   "shipped to GHCR" and "edges should auto-pull this".
#
# Why no rebuild: `docker buildx imagetools create` operates on registry
# manifests directly — multi-arch tag retag is a metadata-only operation,
# no images are downloaded or pushed.
#
# Security: input.version is a workflow_dispatch parameter (only callable by
# repo maintainers via gh CLI / web UI), but we still validate format and
# pass it through env: to all run: blocks rather than ${{ }} interpolation.

on:
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to promote (without v prefix), e.g. 0.12.4'
        required: true
        type: string

permissions:
  packages: write

env:
  REGISTRY: ghcr.io
  OWNER: ${{ github.repository_owner }}

jobs:
  promote:
    runs-on: ubuntu-latest
    steps:
      - name: Validate version format
        env:
          VERSION: ${{ inputs.version }}
        run: |
          if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            echo "::error::version must be MAJOR.MINOR.PATCH (got '$VERSION')"
            exit 1
          fi

      - name: Set up buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Verify source tags exist
        env:
          VERSION: ${{ inputs.version }}
        run: |
          set -euo pipefail
          for c in sfu coturn caddy xray naive; do
            ref="${REGISTRY}/${OWNER}/partner-edge-${c}:v${VERSION}"
            echo ">> inspecting $ref"
            docker buildx imagetools inspect "$ref" >/dev/null
          done

      - name: Retag to :stable
        env:
          VERSION: ${{ inputs.version }}
        run: |
          set -euo pipefail
          for c in sfu coturn caddy xray naive; do
            src="${REGISTRY}/${OWNER}/partner-edge-${c}:v${VERSION}"
            dst="${REGISTRY}/${OWNER}/partner-edge-${c}:stable"
            echo ">> $src -> $dst"
            docker buildx imagetools create --tag "$dst" "$src"
          done

      - name: Print summary
        env:
          VERSION: ${{ inputs.version }}
        run: |
          {
            echo "## Promoted to :stable"
            echo ""
            echo "Version: \`v${VERSION}\`"
            echo ""
            echo "SFU-pool hosts — \`partner_nodes WHERE in_sfu_pool = true AND"
            echo "healthy = true\` (the registry is the source of truth; this"
            echo "workflow does NOT enumerate edges) — auto-pull the new"
            echo "\`:stable\` on their next updater-timer fire. See the"
            echo "operator's internal SFU auto-update runbook for the canon."
            echo ""
            echo "Components retagged: sfu, coturn, caddy, xray, naive"
          } >> "$GITHUB_STEP_SUMMARY"
