Deploy Waters Boards to NAS / deploy (push) Canceled after 0s
Boards with groups, items, subitems and 18 column types; table, kanban, calendar, timeline, chart and files views; updates with @mentions, replies and attachments; inbox, My work, search, automations; Google sign-in restricted to company domains; live updates over SSE; a monday.com API importer; phone layout and installable PWA; Docker + Gitea Actions deploy to the NAS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
82 lines
3.3 KiB
YAML
82 lines
3.3 KiB
YAML
# 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
|