name: Build & Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deployment target'
        required: true
        default: 'development'
        type: choice
        options:
          - development
          - production

env:
  HUGO_VERSION: '0.164.0'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0   # Hugo reads git info for lastmod

      - name: Install Hugo ${{ env.HUGO_VERSION }}
        run: |
          set -euo pipefail
          curl -sSL -o /tmp/hugo.deb \
            "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-amd64.deb"
          sudo dpkg -i /tmp/hugo.deb
          hugo version

      - name: Resolve target
        id: target
        run: |
          set -euo pipefail
          if [ "${{ github.event_name }}" = "workflow_dispatch" ] \
             && [ "${{ inputs.environment }}" = "production" ]; then
            echo "base_url=https://motorradclub-giebelwald.de/" >> "$GITHUB_OUTPUT"
            echo "deploy_path=${{ secrets.DEPLOY_PATH_PROD }}" >> "$GITHUB_OUTPUT"
            echo "name=production" >> "$GITHUB_OUTPUT"
          else
            echo "base_url=https://mcg.luxick.de/" >> "$GITHUB_OUTPUT"
            echo "deploy_path=${{ secrets.DEPLOY_PATH_DEV }}" >> "$GITHUB_OUTPUT"
            echo "name=development" >> "$GITHUB_OUTPUT"
          fi

      - name: Build
        run: |
          set -euo pipefail
          hugo --gc --minify --baseURL "${{ steps.target.outputs.base_url }}"

      # Pull requests are built to catch breakage, but never published.
      - name: Deploy to ${{ steps.target.outputs.name }}
        if: github.event_name != 'pull_request'
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
          SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
          DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
          DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
          DEPLOY_PATH: ${{ steps.target.outputs.deploy_path }}
        run: |
          set -euo pipefail

          # rsync runs with --delete, so the destination becomes an exact mirror
          # of public/. Refuse to run against an unset, root or shallow path.
          case "${DEPLOY_PATH:-}" in
            ""|"/"|"/root"|"/home"|"/var"|"/etc"|"/usr"|"/srv"|"/opt")
              echo "::error::DEPLOY_PATH is unset or unsafe: '${DEPLOY_PATH:-}'" >&2
              exit 1
              ;;
          esac
          if [ "$(printf '%s' "$DEPLOY_PATH" | tr -cd '/' | wc -c)" -lt 2 ]; then
            echo "::error::DEPLOY_PATH '$DEPLOY_PATH' is too shallow to delete into" >&2
            exit 1
          fi
          if [ ! -f public/index.html ]; then
            echo "::error::public/index.html missing - refusing to deploy an empty build" >&2
            exit 1
          fi

          sudo apt-get update -qq && sudo apt-get install -y -qq rsync openssh-client

          mkdir -p ~/.ssh
          chmod 700 ~/.ssh
          printf '%s\n' "$SSH_PRIVATE_KEY" > ~/.ssh/id_deploy
          chmod 600 ~/.ssh/id_deploy
          printf '%s\n' "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
          chmod 644 ~/.ssh/known_hosts

          rsync -az --delete --checksum \
            -e "ssh -i ~/.ssh/id_deploy -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes" \
            public/ "${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/"

          rm -f ~/.ssh/id_deploy
