# CI Workflow — Build, deploy, and configure DNS for Reasonix # Builds Docker image → Deploys on NAS → Upserts Cloudflare DNS record # # Image name: reasonix:latest (built locally on NAS runner) name: Deploy Reasonix on: push: branches: [main] paths: - 'reasonix/**' - '.gitea/workflows/deploy-reasonix.yml' workflow_dispatch: concurrency: group: deploy-reasonix cancel-in-progress: true jobs: build-and-deploy: name: Build & Deploy Reasonix runs-on: nas steps: - name: Checkout repository run: | if [ ! -d .git ]; then git clone --depth=1 --branch "$GITHUB_REF_NAME" "http://127.0.0.1:3300/${GITHUB_REPOSITORY}.git" . fi git fetch --depth=1 origin "$GITHUB_SHA" 2>/dev/null || true git checkout "$GITHUB_SHA" 2>/dev/null || true - name: Build Docker image run: | set -euo pipefail export DOCKER_API_VERSION=1.43 echo "Building reasonix Docker image from reasonix/" DOCKER_BUILDKIT=0 docker build \ -t reasonix:latest \ -t "reasonix:$GITHUB_SHA" \ reasonix/ echo "✅ Build complete: reasonix:$GITHUB_SHA" - name: Smoke test image run: | set -euo pipefail export DOCKER_API_VERSION=1.43 # Quick test: run the container briefly and check it starts CONTAINER_ID=$(docker run -d \ -e DEEPSEEK_LOCAL_API_KEY=test \ reasonix:latest \ /bin/sh -c "reasonix --version") OUTPUT=$(docker wait "$CONTAINER_ID") LOGS=$(docker logs "$CONTAINER_ID" 2>&1 || true) docker rm -f "$CONTAINER_ID" 2>/dev/null || true echo "reasonix version: $LOGS" echo "✅ Image is functional" - name: Prepare deploy directory run: | set -euo pipefail export DOCKER_API_VERSION=1.43 TARGET="/volume1/docker/reasonix" mkdir -p "$TARGET" # Sync compose and config files cp reasonix/docker-compose.yml "$TARGET/docker-compose.yml" cp reasonix/reasonix.toml "$TARGET/reasonix.toml" # Write target tag for compose reference printf '%s\n' "$GITHUB_SHA" > "$TARGET/target-tag.txt" echo "✅ Deploy directory ready: $TARGET" - name: Deploy Reasonix env: DEEPSEEK_LOCAL_API_KEY: ${{ secrets.DEEPSEEK_LOCAL_API_KEY }} run: | set -euo pipefail export DOCKER_API_VERSION=1.43 TARGET="/volume1/docker/reasonix" cd "$TARGET" # Create .env if it doesn't exist if [ ! -f .env ]; then echo "DEEPSEEK_LOCAL_API_KEY=$DEEPSEEK_LOCAL_API_KEY" > .env fi # Ensure network exists docker network inspect nas-dashboard_internal >/dev/null 2>&1 || \ docker network create nas-dashboard_internal # Stop old container docker rm -f reasonix 2>/dev/null || true echo "Old container removed" # Deploy docker compose -f docker-compose.yml up -d --pull never echo "✅ Container deployed" - name: Wait for healthy run: | set -euo pipefail export DOCKER_API_VERSION=1.43 echo "Waiting for reasonix to be healthy..." for i in {1..30}; do STATUS=$(docker inspect --format='{{.State.Health.Status}}' reasonix 2>/dev/null || echo "starting") if [ "$STATUS" = "healthy" ]; then echo "✅ Container is healthy" break fi echo "Waiting... ($i/30) Status: $STATUS" sleep 2 done STATUS=$(docker inspect --format='{{.State.Health.Status}}' reasonix 2>/dev/null || echo "unknown") if [ "$STATUS" != "healthy" ]; then echo "❌ Container failed to become healthy: $STATUS" docker logs reasonix --tail 50 exit 1 fi - name: Verify health endpoint run: | set -euo pipefail export DOCKER_API_VERSION=1.43 echo "Testing health endpoint..." # Use wget from inside another container or via docker exec docker exec reasonix wget -q --spider http://localhost:8787 && \ echo "✅ Health endpoint OK" || { echo "❌ Health endpoint failed" docker logs reasonix --tail 20 exit 1 } - name: Upsert Cloudflare DNS record env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} run: | set -euo pipefail chmod +x scripts/cloudflare-dns.sh scripts/cloudflare-dns.sh jimmygan.com A code 161.33.182.109 echo "✅ Cloudflare DNS record for code.jimmygan.com → 161.33.182.109" - name: Reload VPS Caddy env: CADDY_VPS_SSH_HOST: 161.33.182.109 CADDY_VPS_SSH_USER: ubuntu run: | set -euo pipefail echo "Reloading VPS Caddy..." # Reload via SSH (Caddy reloads config gracefully with SIGUSR2 or systemctl) ssh -o StrictHostKeyChecking=no \ "$CADDY_VPS_SSH_USER@$CADDY_VPS_SSH_HOST" \ "sudo systemctl reload caddy 2>/dev/null || sudo caddy reload --config /etc/caddy/Caddyfile 2>/dev/null || echo 'Caddy reload skipped (manual reload may be needed)'" && \ echo "✅ VPS Caddy reload triggered" || \ echo "⚠️ Caddy reload not automatically available. Reload manually on VPS if needed." - name: Notify completion run: | echo "" echo "============================================" echo "✅ Reasonix deployment complete!" echo " Container: reasonix (port 8787)" echo " DNS: code.jimmygan.com → 161.33.182.109" echo " Caddy: VPS/NAS configs in tmp_remote/" echo "============================================"