161 lines
5.8 KiB
YAML
161 lines
5.8 KiB
YAML
# 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]
|
|
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 "============================================"
|