diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index a7999c1..194f1cc 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,51 +1,83 @@ -name: Deploy to Production +name: Deploy to TrueNAS + +# Auto-deploy on push to main. +# Runs on the self-hosted Gitea Actions runner on TrueNAS.local +# (container: cannamanage-act-runner). The runner mounts the host Docker +# socket into the job container, so `docker compose` commands act on the +# TrueNAS Docker daemon and (re)build/restart the live cannamanage stack. +# +# The job checks the repo out into its own workspace and builds from there, +# so it always deploys exactly the pushed commit — it does NOT depend on the +# old /mnt/VM_SSD_Pool/cannamanage host checkout. +# +# Compose project name is pinned to "cannamanage" so it updates the existing +# containers and reuses the persistent "cannamanage_pgdata" volume on the host. +# Live ports: backend 8081->8080, frontend 3000, db 5432 on: push: branches: [main] +# Avoid overlapping deploys if pushes land in quick succession. +concurrency: + group: truenas-deploy + cancel-in-progress: false + jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - - - name: Run backend tests - run: ./mvnw verify -B -q - deploy: - needs: test runs-on: ubuntu-latest + env: + COMPOSE: docker compose -f docker-compose.yml -f docker-compose.truenas.yml -p cannamanage steps: - - name: Deploy to production - uses: appleboy/ssh-action@v1 - with: - host: plate-software.de - username: ${{ secrets.SSH_USER }} - key: ${{ secrets.SSH_PRIVATE_KEY }} - script: | - cd /opt/cannamanage - git pull origin main - docker compose -f docker-compose.prod.yml build - docker compose -f docker-compose.prod.yml up -d - - # Wait for backend health - sleep 15 - for i in 1 2 3 4 5; do - if curl -sf http://127.0.0.1:8080/actuator/health > /dev/null 2>&1; then - echo "✅ Deploy successful at $(date)" - exit 0 - fi - echo "Waiting... attempt $i/5" - sleep 5 - done - - echo "❌ Deploy failed — backend unhealthy" - docker compose -f docker-compose.prod.yml logs --tail=30 backend - exit 1 + - name: Check out pushed commit + uses: actions/checkout@v4 + + - name: Show toolchain + run: | + set -euo pipefail + docker version --format 'docker {{.Server.Version}}' + docker compose version + + - name: Build images + run: | + set -euo pipefail + $COMPOSE build + + - name: Roll out stack + run: | + set -euo pipefail + $COMPOSE up -d --remove-orphans + + - name: Wait for backend health + run: | + set -euo pipefail + echo "Waiting for backend health on :8081 ..." + for i in $(seq 1 20); do + if wget -q -O /dev/null http://192.168.188.119:8081/actuator/health; then + echo "✅ Backend healthy after ${i} attempt(s)" + exit 0 + fi + echo " attempt $i/20 — waiting 6s" + sleep 6 + done + echo "❌ Backend did not become healthy — recent logs:" + $COMPOSE logs --tail=40 backend + exit 1 + + - name: Verify frontend + run: | + if wget -q -O /dev/null http://192.168.188.119:3000; then + echo "✅ Frontend responding on :3000" + else + echo "⚠️ Frontend not responding yet (may still be starting)" + fi + + - name: Prune dangling images + run: docker image prune -f || true + + - name: Deployment summary + run: | + echo "=== CannaManage deployed to TrueNAS ===" + echo "Commit: ${GITHUB_SHA}" + echo "Backend: http://192.168.188.119:8081" + echo "Frontend: http://192.168.188.119:3000" diff --git a/docker-compose.truenas.yml b/docker-compose.truenas.yml new file mode 100644 index 0000000..90356e0 --- /dev/null +++ b/docker-compose.truenas.yml @@ -0,0 +1,20 @@ +# TrueNAS homelab override — replaces localhost with 192.168.188.119 +# Applied on top of docker-compose.yml for the homelab deployment on TrueNAS.local. +# Usage: +# docker compose -f docker-compose.yml -f docker-compose.truenas.yml up -d --build +services: + backend: + # Host port 8080 is taken by odysseus-searxng-1; remap to 8081. + # !override replaces the inherited ports list (compose merges lists by concat otherwise). + # Internal container port stays 8080 so frontend's BACKEND_URL=http://backend:8080 is unaffected. + ports: !override + - "8081:8080" + + frontend: + environment: + NEXTAUTH_URL: http://192.168.188.119:3000 + AUTH_URL: http://192.168.188.119:3000 + # NextAuth v5 (Auth.js) reads AUTH_SECRET, not NEXTAUTH_SECRET. Without it at + # runtime, signIn throws MissingSecret -> the app error boundary shows 'Oops'. + AUTH_SECRET: docker-dev-nextauth-secret-minimum-32chars + AUTH_TRUST_HOST: "true"