name: test-build-publish

on:
  push:
    branches:
      - main
    tags:
      - 'v*'
  workflow_dispatch:

jobs:
  docker:
    runs-on: ubuntu-latest
    container:
      image: catthehacker/ubuntu:act-latest
    env:
      RUNNER_TOOL_CACHE: /toolcache
      PACKAGE_OWNER: space
      PACKAGE_NAME: evil-wordle
      REPO_NAME: evil-wordle
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Build app
        run: npm run build

      - name: Validate compose file
        run: docker compose config

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

      - name: Resolve registry settings
        id: registry
        shell: bash
        env:
          SECRET_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
          SECRET_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
          SECRET_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
          SECRET_IMAGE: ${{ secrets.REGISTRY_IMAGE }}
        run: |
          set -euo pipefail
          username="${SECRET_USERNAME:-}"
          password="${SECRET_PASSWORD:-${SECRET_TOKEN:-}}"
          image="${SECRET_IMAGE:-gitea.reversed.dev/space/evil-wordle}"

          if [ -z "$username" ]; then
            echo "::error::Registry username is empty. Set REGISTRY_USERNAME to the Gitea user that owns the token."
            exit 1
          fi

          if [ -z "$password" ]; then
            echo "::error::Registry password is empty. Set REGISTRY_PASSWORD to a Gitea token with package read/write access."
            exit 1
          fi

          {
            echo "username=$username"
            echo "image=$image"
          } >> "$GITHUB_OUTPUT"

          echo "::add-mask::$password"

      - name: Log in to Gitea registry
        shell: bash
        env:
          REGISTRY_USERNAME: ${{ steps.registry.outputs.username }}
          REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
          REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
        run: |
          set -euo pipefail
          password="${REGISTRY_PASSWORD:-${REGISTRY_TOKEN:-}}"
          echo "::add-mask::$password"
          echo "$password" | docker login gitea.reversed.dev -u "$REGISTRY_USERNAME" --password-stdin

      - name: Compute image tags
        id: meta
        shell: bash
        run: |
          set -euo pipefail
          short_sha="${GITHUB_SHA::7}"
          image="${{ steps.registry.outputs.image }}"
          tags="${image}:${short_sha}"
          if [ "${GITHUB_REF_NAME}" = "main" ]; then
            tags="${tags}\n${image}:latest"
          fi
          if [[ "${GITHUB_REF_TYPE}" = "tag" ]]; then
            clean_tag="${GITHUB_REF_NAME#v}"
            tags="${tags}\n${image}:${clean_tag}"
          fi
          {
            echo 'tags<<EOF'
            printf '%b\n' "$tags"
            echo EOF
          } >> "$GITHUB_OUTPUT"

      - name: Build and push image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ steps.meta.outputs.tags }}

      - name: Link package to repository
        shell: bash
        run: |
          set -euo pipefail
          token="${REGISTRY_PASSWORD:-${REGISTRY_TOKEN:-}}"
          export REGISTRY_PASSWORD="$token"
          python3 - <<'PY'
          import json
          import os
          import sys
          import urllib.error
          import urllib.request

          owner = os.environ['PACKAGE_OWNER']
          package = os.environ['PACKAGE_NAME']
          repo = os.environ['REPO_NAME']
          token = os.environ['REGISTRY_PASSWORD']
          base = 'https://gitea.reversed.dev/api/v1'
          headers = {
              'Authorization': f'token {token}',
              'Accept': 'application/json',
          }

          req = urllib.request.Request(
              f'{base}/packages/{owner}/container/{package}/-/latest',
              headers=headers,
          )
          with urllib.request.urlopen(req) as resp:
              current = json.load(resp)

          linked_repo = (current.get('repository') or {}).get('name')
          if linked_repo == repo:
              print(f'package already linked to {owner}/{repo}')
              sys.exit(0)

          link_req = urllib.request.Request(
              f'{base}/packages/{owner}/container/{package}/-/link/{repo}',
              data=b'',
              method='POST',
              headers=headers,
          )
          try:
              with urllib.request.urlopen(link_req) as resp:
                  print(f'linked package to {owner}/{repo}, status={resp.status}')
          except urllib.error.HTTPError as exc:
              body = exc.read().decode(errors='replace')
              print(f'link failed: status={exc.code} body={body}')
              raise
          PY
        env:
          REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
          REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
