name: Release Container

on:
  push:
    branches:
      - main

env:
  APP_NAME: maintainarr

jobs:
  publish-container:
    name: Build And Publish Container
    runs-on: ubuntu-latest

    env:
      GITEA_SERVER_URL: ${{ gitea.server_url }}
      GITEA_REPOSITORY: ${{ gitea.repository }}
      GITEA_SHA: ${{ gitea.sha }}
      GITEA_ACTOR: ${{ gitea.actor }}
      GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
      GITEA_REGISTRY: ${{ secrets.GITEA_REGISTRY }}
      GITEA_REGISTRY_USERNAME: ${{ secrets.GITEA_REGISTRY_USERNAME }}
      GITEA_PACKAGE_NAMESPACE: ${{ secrets.GITEA_PACKAGE_NAMESPACE }}

    steps:
      - name: Check out repository
        uses: https://dock-it.dev/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
        with:
          fetch-depth: 0

      - name: Prepare release metadata
        shell: bash
        run: |
          set -euo pipefail

          short_sha="$(printf '%s' "$GITEA_SHA" | cut -c1-7)"
          repo_owner="${GITEA_REPOSITORY%%/*}"
          registry_host="${GITEA_REGISTRY}"
          app_name="$(printf '%s' "$APP_NAME" | tr '[:upper:]' '[:lower:]')"

          if [ -z "$registry_host" ]; then
            registry_host="$(printf '%s' "$GITEA_SERVER_URL" | sed -E 's#^https?://##; s#/$##')"
          fi
          registry_host="$(printf '%s' "$registry_host" | tr '[:upper:]' '[:lower:]')"

          package_namespace="${GITEA_PACKAGE_NAMESPACE}"
          if [ -z "$package_namespace" ]; then
            package_namespace="${repo_owner}"
          fi
          package_namespace="$(printf '%s' "$package_namespace" | tr '[:upper:]' '[:lower:]')"

          registry_username="${GITEA_REGISTRY_USERNAME}"
          if [ -z "$registry_username" ]; then
            registry_username="${GITEA_ACTOR}"
          fi

          image_ref="${registry_host}/${package_namespace}/${app_name}"

          echo "SHORT_SHA=${short_sha}" >> "$GITHUB_ENV"
          echo "RELEASE_TAG=release-${short_sha}" >> "$GITHUB_ENV"
          echo "RELEASE_NAME=Release ${short_sha}" >> "$GITHUB_ENV"
          echo "REGISTRY_HOST=${registry_host}" >> "$GITHUB_ENV"
          echo "REGISTRY_USERNAME=${registry_username}" >> "$GITHUB_ENV"
          echo "PACKAGE_NAMESPACE=${package_namespace}" >> "$GITHUB_ENV"
          echo "IMAGE_REF=${image_ref}" >> "$GITHUB_ENV"

      - name: Verify release token
        shell: bash
        run: |
          set -euo pipefail

          if [ -z "$GITEA_TOKEN" ]; then
            echo "The repository secret GITEA_TOKEN is required to publish releases and packages."
            exit 1
          fi

      - name: Install release dependencies
        shell: bash
        run: |
          set -euo pipefail
          sudo apt-get update
          sudo apt-get install -y curl jq

      - name: Log in to Gitea container registry
        shell: bash
        run: |
          set -euo pipefail
          printf '%s' "$GITEA_TOKEN" | docker login "$REGISTRY_HOST" --username "$REGISTRY_USERNAME" --password-stdin

      - name: Build container image
        shell: bash
        run: |
          set -euo pipefail
          docker build \
            --tag "${IMAGE_REF}:${SHORT_SHA}" \
            --tag "${IMAGE_REF}:main" \
            --tag "${IMAGE_REF}:latest" \
            .

      - name: Push container image
        shell: bash
        run: |
          set -euo pipefail
          docker push "${IMAGE_REF}:${SHORT_SHA}"
          docker push "${IMAGE_REF}:main"
          docker push "${IMAGE_REF}:latest"

      - name: Create release notes
        shell: bash
        run: |
          set -euo pipefail

          git fetch --tags --force

          api="${GITEA_SERVER_URL%/}/api/v1/repos/${GITEA_REPOSITORY}"
          repo_url="${GITEA_SERVER_URL%/}/${GITEA_REPOSITORY}"

          previous_tag="$(
            curl --fail-with-body --silent --show-error \
              -H "Authorization: token ${GITEA_TOKEN}" \
              "${api}/releases?limit=50" |
            jq -r '[.[] | select(.tag_name | startswith("release-"))][0].tag_name // empty'
          )"

          if [ -n "$previous_tag" ]; then
            range="${previous_tag}..${GITEA_SHA}"
          else
            range="${GITEA_SHA}"
          fi

          {
            if [ -n "$previous_tag" ]; then
              echo "## Changes since ${previous_tag}"
            else
              echo "## Changes"
            fi

            echo

            commit_count="$(git rev-list --count "$range")"

            if [ "$commit_count" -eq 0 ]; then
              echo "- No commits found since the previous release."
            else
              git log "$range" \
                --reverse \
                --pretty=format:'%H%x1f%s' |
              while IFS="$(printf '\037')" read -r hash subject; do
                short="$(printf '%s' "$hash" | cut -c1-7)"
                echo "- ([${short}](${repo_url}/commit/${hash})) ${subject}"
              done
            fi

            echo
            echo "## Container Images"
            echo
            echo "- \`${IMAGE_REF}:${SHORT_SHA}\`"
            echo "- \`${IMAGE_REF}:main\`"
            echo "- \`${IMAGE_REF}:latest\`"

            echo
            echo "## Authors"
            echo
            echo "Sorted by total lines added or removed."
            echo

            git log "$range" --numstat --format='author:%an <%ae>' |
            awk '
              /^author:/ {
                author = substr($0, 8)
                next
              }

              NF >= 3 {
                added = ($1 == "-" ? 0 : $1)
                removed = ($2 == "-" ? 0 : $2)

                adds[author] += added
                dels[author] += removed
                churn[author] += added + removed
              }

              END {
                for (a in churn) {
                  printf "%d\t%d\t%d\t%s\n", churn[a], adds[a], dels[a], a
                }
              }
            ' |
            sort -nr |
            while IFS="$(printf '\t')" read -r total added removed author; do
              echo "- ${author} - ${total} lines changed (+${added} / -${removed})"
            done
          } > release-notes.md

      - name: Create Gitea release
        shell: bash
        run: |
          set -euo pipefail

          api="${GITEA_SERVER_URL%/}/api/v1/repos/${GITEA_REPOSITORY}"

          existing_release_id="$(
            curl --fail-with-body --silent --show-error \
              -H "Authorization: token ${GITEA_TOKEN}" \
              "${api}/releases/tags/${RELEASE_TAG}" |
            jq -r '.id // empty' 2>/dev/null || true
          )"

          payload="$(jq -n \
            --arg tag "$RELEASE_TAG" \
            --arg sha "$GITEA_SHA" \
            --arg name "$RELEASE_NAME" \
            --rawfile body release-notes.md \
            '{
              tag_name: $tag,
              target_commitish: $sha,
              name: $name,
              body: $body,
              draft: false,
              prerelease: false
            }')"

          if [ -n "$existing_release_id" ]; then
            curl --fail-with-body --silent --show-error \
              -X PATCH \
              -H "Authorization: token ${GITEA_TOKEN}" \
              -H "Content-Type: application/json" \
              --data "$payload" \
              "${api}/releases/${existing_release_id}" >/dev/null
          else
            curl --fail-with-body --silent --show-error \
              -X POST \
              -H "Authorization: token ${GITEA_TOKEN}" \
              -H "Content-Type: application/json" \
              --data "$payload" \
              "${api}/releases" >/dev/null
          fi
