mirror of
https://github.com/myronblair/novacpx
synced 2026-06-30 17:50:41 -05:00
483ab8a002
deploy-runner.sh was rsyncing panel/public/ but VERSION lives at repo root — web root /srv/novacpx/public/VERSION was perpetually stale. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
122 lines
4.6 KiB
Bash
122 lines
4.6 KiB
Bash
#!/usr/bin/env bash
|
|
# NovaCPX Deploy Runner — runs every minute via cron
|
|
# Processes /tmp/novacpx-deploy-queue.txt
|
|
# Each line: repo_path|web_root|commit
|
|
|
|
QUEUE="/tmp/novacpx-deploy-queue.txt"
|
|
LOG="/var/log/novacpx/deploy.log"
|
|
LOCK="/tmp/novacpx-deploy.lock"
|
|
|
|
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG"; }
|
|
|
|
[[ ! -s "$QUEUE" ]] && exit 0
|
|
|
|
# Prevent concurrent runs
|
|
exec 9>"$LOCK"
|
|
flock -n 9 || { log "Deploy already running, skipping"; exit 0; }
|
|
|
|
# Read DB path and channel once before processing the queue
|
|
DB_PATH=$(python3 -c "import configparser; c=configparser.ConfigParser(); c.read('/etc/novacpx/config.ini'); print(c.get('database','path',fallback='/var/lib/novacpx/panel.db'))" 2>/dev/null || echo "/var/lib/novacpx/panel.db")
|
|
CHANNEL=$(sqlite3 "$DB_PATH" "SELECT value FROM settings WHERE key='update_channel'" 2>/dev/null || echo "stable")
|
|
[[ "$CHANNEL" != "beta" ]] && CHANNEL="stable"
|
|
|
|
while IFS='|' read -r REPO_PATH WEB_ROOT COMMIT QUEUED_BRANCH; do
|
|
[[ -z "$REPO_PATH" ]] && continue
|
|
|
|
# Use branch recorded in queue entry (from webhook); fall back to DB channel
|
|
TARGET_BRANCH="main"
|
|
if [[ "$QUEUED_BRANCH" == "beta" || ("$QUEUED_BRANCH" != "main" && "$CHANNEL" == "beta") ]]; then
|
|
TARGET_BRANCH="beta"
|
|
fi
|
|
|
|
log "--- Deploying commit $COMMIT (branch: $TARGET_BRANCH) ---"
|
|
|
|
# Validate PHP syntax before applying
|
|
cd "$REPO_PATH" || continue
|
|
git fetch origin >> "$LOG" 2>&1
|
|
|
|
# Check PHP syntax on changed .php files
|
|
CHANGED_PHP=$(git diff HEAD..origin/${TARGET_BRANCH} --name-only 2>/dev/null | grep '\.php$' || true)
|
|
SYNTAX_OK=true
|
|
for f in $CHANGED_PHP; do
|
|
[[ -f "$REPO_PATH/$f" ]] || continue
|
|
if ! php8.3 -l "$REPO_PATH/$f" >> "$LOG" 2>&1; then
|
|
log "SYNTAX ERROR in $f — aborting deploy"
|
|
SYNTAX_OK=false
|
|
break
|
|
fi
|
|
done
|
|
|
|
if ! $SYNTAX_OK; then
|
|
log "Deploy aborted due to PHP syntax errors"
|
|
continue
|
|
fi
|
|
|
|
# Pull from channel branch
|
|
BEFORE=$(git rev-parse HEAD | tr -cd 'a-f0-9A-F')
|
|
git pull origin "${TARGET_BRANCH}" >> "$LOG" 2>&1
|
|
AFTER=$(git rev-parse HEAD | tr -cd 'a-f0-9A-F')
|
|
|
|
if [[ "$BEFORE" == "$AFTER" ]]; then
|
|
log "Nothing new to deploy (already at $AFTER)"
|
|
continue
|
|
fi
|
|
|
|
log "Updated: $BEFORE → $AFTER"
|
|
|
|
# Sync panel files to web root
|
|
rsync -av --delete \
|
|
--exclude='.git' \
|
|
--exclude='api/config.php' \
|
|
--exclude='*.log' \
|
|
"$REPO_PATH/panel/public/" "$WEB_ROOT/" >> "$LOG" 2>&1
|
|
|
|
# Sync backend API and lib (not in panel/public, deployed separately)
|
|
rsync -av --delete --exclude='config.php' "$REPO_PATH/panel/api/" "$WEB_ROOT/api/" >> "$LOG" 2>&1
|
|
rsync -av --delete "$REPO_PATH/panel/lib/" "$WEB_ROOT/lib/" >> "$LOG" 2>&1
|
|
|
|
# Sync cron scripts to bin directory
|
|
rsync -av "$REPO_PATH/panel/bin/" /opt/novacpx/bin/ >> "$LOG" 2>&1
|
|
chmod +x /opt/novacpx/bin/*.php 2>/dev/null || true
|
|
|
|
# Copy VERSION to web root so /VERSION endpoint stays current
|
|
[[ -f "$REPO_PATH/VERSION" ]] && cp "$REPO_PATH/VERSION" "$WEB_ROOT/VERSION"
|
|
|
|
# Run pending DB migrations (SQLite)
|
|
MIGR_DIR="$REPO_PATH/db/migrations"
|
|
if [[ -d "$MIGR_DIR" && -f "$DB_PATH" ]]; then
|
|
for SQL in "$MIGR_DIR"/*.sql; do
|
|
[[ -f "$SQL" ]] || continue
|
|
MIGR_NAME=$(basename "$SQL" .sql)
|
|
ALREADY=$(sqlite3 "$DB_PATH" "SELECT value FROM settings WHERE key='migration_$MIGR_NAME'" 2>/dev/null)
|
|
if [[ -z "$ALREADY" ]]; then
|
|
log "Running migration: $MIGR_NAME"
|
|
sqlite3 "$DB_PATH" < "$SQL" >> "$LOG" 2>&1
|
|
sqlite3 "$DB_PATH" "INSERT OR REPLACE INTO settings (key,value,updated_at) VALUES ('migration_$MIGR_NAME','$(date)',datetime('now'))" 2>/dev/null
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Record new version in DB — sanitize values before interpolating into SQL
|
|
NEW_VERSION=$(cat "$REPO_PATH/VERSION" 2>/dev/null | tr -d '[:space:]' | tr -cd 'a-zA-Z0-9.-' || true)
|
|
if [[ -n "$NEW_VERSION" && -f "$DB_PATH" ]]; then
|
|
sqlite3 "$DB_PATH" "INSERT INTO novacpx_version (version, installed_at, notes, git_commit) VALUES ('$NEW_VERSION', datetime('now'), 'Auto-deployed via webhook ($CHANNEL channel)', '$AFTER')" 2>/dev/null || true
|
|
sqlite3 "$DB_PATH" "INSERT INTO settings (key, value, updated_at) VALUES ('panel_version', '$NEW_VERSION', datetime('now')) ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at" 2>/dev/null || true
|
|
log "Version updated to $NEW_VERSION"
|
|
fi
|
|
|
|
# Ensure deploy webhook is accessible from web root
|
|
mkdir -p "$WEB_ROOT/deploy"
|
|
ln -sf "$REPO_PATH/deploy/webhook.php" "$WEB_ROOT/deploy/webhook.php"
|
|
|
|
# Restart PHP-FPM to pick up code changes
|
|
systemctl reload php8.3-fpm 2>/dev/null || true
|
|
systemctl reload php8.2-fpm 2>/dev/null || true
|
|
|
|
log "Deploy complete: $AFTER"
|
|
|
|
done < "$QUEUE"
|
|
|
|
# Clear queue
|
|
> "$QUEUE"
|