name: Docker Build & Publish

on:
  push:
    branches: [master]
  workflow_dispatch:

env:
  # Number of tagged (non-latest) versions to keep per image name.
  KEEP_VERSIONS: "5"

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      host:  ${{ steps.meta.outputs.host }}
      image: ${{ steps.meta.outputs.image }}
      sha:   ${{ steps.meta.outputs.sha }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Resolve registry metadata
        id: meta
        run: |
          host=$(echo "${{ gitea.server_url }}" | sed 's|https\?://||; s|/$||')
          repo_lc=$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]')
          echo "host=$host"            >> "$GITHUB_OUTPUT"
          echo "image=$host/$repo_lc" >> "$GITHUB_OUTPUT"
          echo "sha=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"

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

      - name: Build image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: dockerfiles/Dockerfile.prod
          push: false
          tags: |
            ${{ steps.meta.outputs.image }}:latest
            ${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.sha }}
          outputs: type=docker,dest=/tmp/image.tar

      - name: Upload image artifact
        uses: actions/upload-artifact@v3
        with:
          name: docker-image
          path: /tmp/image.tar
          retention-days: 1

  push:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download image artifact
        uses: actions/download-artifact@v3
        with:
          name: docker-image
          path: /tmp

      - name: Load image
        run: docker load < /tmp/image.tar

      - name: Log in to Gitea registry
        uses: docker/login-action@v3
        with:
          registry: ${{ needs.build.outputs.host }}
          username: ${{ gitea.actor }}
          password: ${{ secrets.PACKAGE_REGISTRY_TOKEN }}

      - name: Push image
        run: |
          docker push ${{ needs.build.outputs.image }}:latest
          docker push ${{ needs.build.outputs.image }}:${{ needs.build.outputs.sha }}

  cleanup:
    name: Prune old image versions
    needs: push
    runs-on: ubuntu-latest
    steps:
      - name: Delete versions beyond KEEP_VERSIONS
        env:
          GITEA_URL: ${{ gitea.server_url }}
          OWNER: ${{ gitea.repository_owner }}
          IMAGE: ${{ gitea.event.repository.name }}
          TOKEN: ${{ secrets.PACKAGE_REGISTRY_TOKEN }}
        run: |
          image=$(echo "$IMAGE" | tr '[:upper:]' '[:lower:]')

          response=$(curl -sf \
            -H "Authorization: token $TOKEN" \
            -H "Accept: application/json" \
            "${GITEA_URL}/api/v1/packages/${OWNER}?type=container&limit=50&q=${image}")

          to_delete=$(printf '%s' "$response" \
            | jq -r \
                --arg  name "$image" \
                --argjson keep "$KEEP_VERSIONS" \
                '[.[] | select(.name == $name and .version != "latest")]
                 | sort_by(.created) | reverse
                 | .[$keep:][].version')

          if [ -z "$to_delete" ]; then
            echo "Nothing to prune."
            exit 0
          fi

          while IFS= read -r version; do
            echo "Deleting ${image}:${version}"
            curl -sf -X DELETE \
              -H "Authorization: token $TOKEN" \
              "${GITEA_URL}/api/v1/packages/${OWNER}/container/${image}/${version}" \
            && echo "  ok" || echo "  failed (may already be gone, continuing)"
          done <<< "$to_delete"
