# Announce a stable release to the Discord #releases channel.
#
# This is the deliberate "go" step for a release. Release notes live in the repo at
# docs/releases/<tag>.md and are seeded into the Gitea release body at creation by the build
# workflows (scripts/ci/gitea-release.sh), so the release is never noteless. Once every
# platform's CI is green for a tag, dispatch this workflow with that tag: it re-asserts the notes
# file over the live release and posts a formatted embed to #releases.
#
# Manual on purpose — pressing "go" is the quality gate that says "all platforms built, notes are
# final, tell the community." It is NOT wired to the tag push, so a half-built or failed release
# is never announced. Stable-only: a -rc/pre-release tag is refused unless allow_prerelease=true.
#
# Requires the repo secret DISCORD_RELEASE_WEBHOOK (the #releases channel webhook URL); GITEA auth
# reuses REGISTRY_TOKEN like the other release workflows.
name: announce

on:
  workflow_dispatch:
    inputs:
      tag:
        description: "Release tag to announce (e.g. v0.18.0)"
        required: true
      allow_prerelease:
        description: "Announce even if the tag is a pre-release (-rc)"
        required: false
        default: "false"

jobs:
  announce:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v4

      # Publish the SIGNED stable update manifest — the moment every host's update check learns
      # about this release (planning: host-update-from-web-console.md §3.3). Deliberately here in
      # announce, not on the tag: the manual "fleet is green, go" gate doubles as the gate for the
      # fleet-wide "update available". Fails the announce loudly if the key is missing (fail-closed)
      # or the installer's live bytes don't match their .sha256 sidecar. Pre-release tags are
      # ALWAYS skipped — an -rc must never enter the stable feed, even with allow_prerelease.
      - name: Publish the stable update manifest
        env:
          REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
          UPDATE_MANIFEST_KEY: ${{ secrets.UPDATE_MANIFEST_KEY }}
          # Through the ENVIRONMENT, never interpolated into the script body. A `${{ }}` expansion
          # is a raw textual substitution performed BEFORE the shell sees the line, so a
          # workflow_dispatch input containing shell syntax executes as this step — and this is the
          # step holding UPDATE_MANIFEST_KEY, the Ed25519 key every host pins to decide whether an
          # update is real (2026-08-05 review H-6). As `$INPUT_TAG` it is only ever data.
          INPUT_TAG: ${{ inputs.tag }}
        run: |
          set -euo pipefail
          TAG="$INPUT_TAG"
          # Shape-check before the value reaches a URL or a filename: tags are `vX.Y.Z[-suffix]`.
          case "$TAG" in
            v[0-9]*) ;;
            *) echo "refusing to publish for a tag that is not vX.Y.Z: $TAG" >&2; exit 1 ;;
          esac
          case "$TAG" in
            *[!A-Za-z0-9.+_-]*) echo "tag has characters no release tag has: $TAG" >&2; exit 1 ;;
          esac
          case "$TAG" in
            *-*) echo "pre-release tag $TAG — not publishing to the stable update feed"; exit 0 ;;
          esac
          VER="${TAG#v}"
          URL="https://git.unom.io/unom/punktfunk/releases/download/${TAG}/punktfunk-host-setup-${VER}.exe"
          # Re-download and re-hash the real bytes; the sidecar is a cross-check, never the truth.
          curl -fsSL "$URL" -o /tmp/installer.exe
          curl -fsSL "$URL.sha256" -o /tmp/installer.sha256
          SHA="$(sha256sum /tmp/installer.exe | awk '{print $1}')"
          grep -qi "$SHA" /tmp/installer.sha256 || {
            echo "ERROR: installer sha256 $SHA does not match the release's .sha256 sidecar" >&2
            exit 1
          }
          CHANNEL=stable VERSION="$VER" REQUIRE_KEY=1 \
            WINDOWS_URL="$URL" WINDOWS_SHA256="$SHA" \
            NOTES_URL="https://git.unom.io/unom/punktfunk/releases/tag/${TAG}" \
            bash scripts/ci/publish-update-manifest.sh

      - name: Post release announcement to Discord
        env:
          GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
          DISCORD_RELEASE_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }}
          ALLOW_PRERELEASE: ${{ inputs.allow_prerelease }}
          # Same reasoning as the publish step above: the input is data in the environment, never
          # text spliced into the command line.
          INPUT_TAG: ${{ inputs.tag }}
        run: bash scripts/ci/discord-announce.sh "$INPUT_TAG"
