# GerbilManager CI — Gitea Actions
# =================================
# STATUS: ENTWURF — inaktiv bis Julian Gitea Actions aktiviert.
# Aktivierung: Gitea -> Repository -> Einstellungen -> Actions -> "Actions aktivieren"
# Anschliessend: Gitea Actions Runner auf der NAS installieren (siehe docs/ops.md).
#
# Was dieser Workflow tut:
#   1. dotnet test (alle xUnit-Projekte)
#   2. npm test + npm run build (Frontend)
#   3. Docker-Images bauen und in die Gitea-Registry pushen
#
# Registry: git.rismer.de  (Gitea Container Registry über HTTPS — keine insecure-registry-Konfig nötig)
# Images:
#   git.rismer.de/gulum/gerbilmanager-api:latest
#   git.rismer.de/gulum/gerbilmanager-frontend:latest

name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
  # Manueller „Run workflow"-Button in Gitea: testet, baut, pusht und deployt frisch.
  # Fuer einen Rollback auf ein altes Image stattdessen auf der NAS:
  #   TAG=<git-sha> sh /opt/gerbilmanager/deploy/truenas/scripts/deploy.sh
  workflow_dispatch:

env:
  REGISTRY: git.rismer.de
  REGISTRY_OWNER: gulum
  DOTNET_VERSION: "10.0.x"
  NODE_VERSION: "22"

jobs:
  test-backend:
    name: Backend Tests (.NET)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: .NET SDK einrichten
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: ${{ env.DOTNET_VERSION }}

      - name: Pakete wiederherstellen
        run: dotnet restore GerbilManager.slnx

      - name: Build
        run: dotnet build GerbilManager.slnx --no-restore -c Release

      - name: dotnet-ef Tool installieren
        # 'tool update' ist idempotent (installiert wenn fehlend, sonst aktualisiert) —
        # auf dem SELF-HOSTED Runner persistieren --global Tools, daher schlug 'tool install'
        # ab dem 2. Lauf mit 'already installed' fehl und kippte den Backend-Job.
        # GITHUB_PATH-Zeile: global tools landen in ~/.dotnet/tools, das auf dem Runner-Container
        # nicht im PATH ist — einmalig eintragen, damit alle Folge-Steps 'dotnet ef' finden.
        run: |
          dotnet tool update --global dotnet-ef --version 10.0.*
          echo "$HOME/.dotnet/tools" >> $GITHUB_PATH

      - name: DB-3 EF Migrations Drift-Check
        # Fails CI if the EF model diverges from the snapshot (i.e. a code change touched
        # entities/OnModelCreating without generating a matching migration). Catches exactly
        # the class of drift the SQLite/EnsureCreated test host is blind to.
        run: >
          dotnet ef migrations has-pending-model-changes
          --project GerbilManagerWebAPI
          --startup-project GerbilManagerWebAPI
          --no-build --configuration Release

      - name: Tests ausfuehren
        run: dotnet test GerbilManager.slnx --no-build -c Release --logger "console;verbosity=normal"

  test-frontend:
    name: Frontend Tests (Node/Vite)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Node.js einrichten
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"
          cache-dependency-path: gerbil-manager-web/package-lock.json

      - name: Abhaengigkeiten installieren
        run: npm ci
        working-directory: gerbil-manager-web

      - name: Tests ausfuehren
        run: npm test
        working-directory: gerbil-manager-web

      - name: Produktionsbuild pruefen
        run: npm run build
        working-directory: gerbil-manager-web

  build-and-push:
    name: Docker Build & Push
    runs-on: ubuntu-latest
    needs: [test-backend, test-frontend]
    if: github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
    steps:
      - uses: actions/checkout@v4

      - name: Bei Gitea Registry anmelden
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.REGISTRY_USER }}
          password: ${{ secrets.REGISTRY_TOKEN }}

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

      - name: API-Image bauen und pushen
        uses: docker/build-push-action@v5
        with:
          context: .
          file: GerbilManagerWebAPI/Dockerfile
          push: true
          tags: |
            ${{ env.REGISTRY }}/${{ env.REGISTRY_OWNER }}/gerbilmanager-api:latest
            ${{ env.REGISTRY }}/${{ env.REGISTRY_OWNER }}/gerbilmanager-api:${{ github.sha }}

      - name: Frontend-Image bauen und pushen
        uses: docker/build-push-action@v5
        with:
          context: .
          file: gerbil-manager-web/Dockerfile
          push: true
          tags: |
            ${{ env.REGISTRY }}/${{ env.REGISTRY_OWNER }}/gerbilmanager-frontend:latest
            ${{ env.REGISTRY }}/${{ env.REGISTRY_OWNER }}/gerbilmanager-frontend:${{ github.sha }}

  deploy:
    name: Deploy auf TrueNAS (Custom App)
    # Laeuft auf dem vorhandenen containerisierten Gitea-Runner (Label ubuntu-latest).
    # Der Runner hat KEINEN Host-Dateisystem-/midclt-Zugriff, daher: per SSH zum NAS-Host
    # verbinden, die Deploy-Dateien in das App-Home auf dem Pool kopieren und dort
    # truenas-deploy.sh ausfuehren (legt die TrueNAS "Custom App" an bzw. rollt sie neu
    # aus via `midclt` — die App bleibt unter Apps sichtbar).
    # Hinweis: / (inkl. /opt) ist auf TrueNAS Goldeye read-only -> App-Home auf dem Pool.
    #
    # Benoetigte Repo-Secrets (Gitea -> Einstellungen -> Actions -> Secrets):
    #   NAS_SSH_HOST  z. B. 192.168.2.115  (Host-LAN-IP der NAS)
    #   NAS_SSH_KEY   privater SSH-Deploy-Key (Pubkey liegt in /root/.ssh/authorized_keys)
    runs-on: ubuntu-latest
    needs: [build-and-push]
    if: github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
    env:
      APP_HOME: /mnt/JailStorage/DockerVolumes/gerbilmanager
    steps:
      - uses: actions/checkout@v4

      - name: SSH-Client + Key einrichten
        run: |
          command -v ssh >/dev/null 2>&1 || (apt-get update && apt-get install -y --no-install-recommends openssh-client rsync)
          install -m 700 -d ~/.ssh
          printf '%s\n' "${{ secrets.NAS_SSH_KEY }}" > ~/.ssh/id_deploy
          chmod 600 ~/.ssh/id_deploy
          ssh-keyscan -H "${{ secrets.NAS_SSH_HOST }}" >> ~/.ssh/known_hosts 2>/dev/null || true

      - name: Deploy-Dateien auf den NAS-Host kopieren
        run: |
          NAS="root@${{ secrets.NAS_SSH_HOST }}"
          SSH="ssh -i ~/.ssh/id_deploy -o StrictHostKeyChecking=accept-new"
          $SSH "$NAS" "mkdir -p $APP_HOME/deploy/truenas/scripts"
          rsync -az -e "$SSH" \
            deploy/truenas/custom-app.compose.yaml \
            "$NAS":"$APP_HOME"/deploy/truenas/
          rsync -az -e "$SSH" \
            deploy/truenas/scripts/ \
            "$NAS":"$APP_HOME"/deploy/truenas/scripts/

      - name: Custom App neu ausrollen (midclt create/redeploy + Health-Check)
        run: |
          NAS="root@${{ secrets.NAS_SSH_HOST }}"
          ssh -i ~/.ssh/id_deploy -o StrictHostKeyChecking=accept-new "$NAS" \
            "sh $APP_HOME/deploy/truenas/scripts/truenas-deploy.sh"
