# Push to main -> the NAS rebuilds Waters Boards. # # Same shape as the checklist app's deploy: runs on the "nas" act_runner (in Docker on the # NAS itself), copies server/ over the live directory, then recreates the container in place. # # ONE-TIME NAS SETUP before the first run (see README.md › Deploy): # 1. mkdir /volume2/docker/waters-boards and put a filled-in .env there # 2. add "/volume2/docker/waters-boards" to container.valid_volumes in the act_runner # config.yaml on the NAS, and restart the runner # 3. point a reverse-proxy hostname (https) at port 3100 — Google sign-in needs https # 4. set the repository variable DEPLOY_ENABLED=true (Settings ▸ Actions ▸ Variables). # Until then this job is skipped, so pushes don't fail before the NAS is ready. name: Deploy Waters Boards to NAS on: push: branches: [main] paths: - 'server/**' - '.gitea/workflows/deploy.yml' workflow_dispatch: jobs: deploy: if: ${{ vars.DEPLOY_ENABLED == 'true' }} runs-on: nas container: image: node:22-alpine volumes: # Mounted at the SAME path as on the host: docker-compose.yml binds ./data relative to # the compose file and the daemon resolves that as a host path. (The docker socket is # already mounted by act_runner — declaring it again breaks the job.) - /volume2/docker/waters-boards:/volume2/docker/waters-boards steps: - name: Install tools run: apk add --no-cache docker-cli docker-cli-compose rsync - name: Checkout uses: actions/checkout@v4 - name: Check the deploy directory is set up run: | set -eu DEST=/volume2/docker/waters-boards test -f "$DEST/.env" || { echo "REFUSING: $DEST/.env is missing — see README.md › Deploy"; exit 1; } - name: Copy server files over the live directory run: | set -eu # data/ holds the live database, uploads and backups; .env holds the secrets. # Neither is in git and neither may ever be written here. No --delete. rsync -a \ --exclude 'data/' \ --exclude '.env' \ --exclude 'node_modules/' \ server/ /volume2/docker/waters-boards/ - name: Verify the live data and credentials survived run: | set -eu test -f /volume2/docker/waters-boards/.env || { echo "ABORT: .env is gone"; exit 1; } echo ".env intact"; ls -la /volume2/docker/waters-boards/data 2>/dev/null || echo "(no data/ yet — first deploy)" - name: Rebuild the container in place # No 'down' first: an interrupted deploy then leaves the old container serving. run: docker compose -f /volume2/docker/waters-boards/docker-compose.yml up -d --build --remove-orphans - name: Healthcheck run: | set -eu for i in $(seq 1 20); do S=$(docker inspect --format '{{.State.Health.Status}}' waters-boards 2>/dev/null || echo starting) [ "$S" = "healthy" ] && { echo "container healthy"; exit 0; } sleep 3 done echo "container did not report healthy in time:" docker ps --filter name=waters-boards --format '{{.Names}} {{.Status}}' docker logs --tail 30 waters-boards exit 1