#!/bin/bash set -euo pipefail REPO_URL="https://github.com/anomalyco/voidea.git" INSTALL_DIR="/opt/voidea" BRANCH="main" echo "=== VoIdeaAI Deploy ===" # Create user if not exists if ! id -u voidea &>/dev/null; then sudo useradd -r -s /bin/bash -m -d "$INSTALL_DIR" voidea fi # Install system dependencies sudo apt-get update sudo apt-get install -y git python3 python3-venv python3-pip postgresql postgresql-client nginx # Clone / pull if [ -d "$INSTALL_DIR/.git" ]; then cd "$INSTALL_DIR" sudo -u voidea git pull origin "$BRANCH" else sudo -u voidea git clone -b "$BRANCH" "$REPO_URL" "$INSTALL_DIR" fi # ── Auto version bump ── LAST_COMMIT_FILE="$INSTALL_DIR/.last_deploy_commit" VERSION_FILE="$INSTALL_DIR/VERSION" AGENT_VERSIONS_FILE="$INSTALL_DIR/AGENT_VERSIONS.json" if [ -f "$LAST_COMMIT_FILE" ]; then LAST_COMMIT=$(cat "$LAST_COMMIT_FILE") CURRENT_COMMIT=$(git rev-parse HEAD) if [ "$LAST_COMMIT" != "$CURRENT_COMMIT" ]; then # Get changed files since last deploy CHANGED_FILES=$(git diff --name-only "$LAST_COMMIT" HEAD) # ── Project version bump ── HAS_PROJECT_CHANGES=false while IFS= read -r file; do case "$file" in app/agents/*) ;; AGENT_VERSIONS.json) ;; *) HAS_PROJECT_CHANGES=true ;; esac done <<< "$CHANGED_FILES" if [ "$HAS_PROJECT_CHANGES" = true ]; then CURRENT_VER=$(cat "$VERSION_FILE") MAJOR=$(echo "$CURRENT_VER" | cut -d. -f1) MINOR=$(echo "$CURRENT_VER" | cut -d. -f2) PATCH=$(echo "$CURRENT_VER" | cut -d. -f3) # Check commit messages for feat/fix hints COMMIT_MSGS=$(git log "$LAST_COMMIT..HEAD" --format=%s) if echo "$COMMIT_MSGS" | grep -q "^feat:"; then MINOR=$((MINOR + 1)) PATCH=0 else PATCH=$((PATCH + 1)) fi NEW_VER="${MAJOR}.${MINOR}.${PATCH}" echo "$NEW_VER" > "$VERSION_FILE" echo ">>> Project version: $CURRENT_VER → $NEW_VER" fi # ── Agent version bump ── # Mapping: agent file → agent name in AGENT_VERSIONS.json AGENT_FILE_MAP() { echo "$1" | sed -n 's|^app/agents/\(.*\)\.py$|\1|p' } while IFS= read -r file; do AGENT_NAME="" case "$file" in app/agents/role_agents.py) AGENT_NAME="role_agents" ;; app/agents/conductor_agent.py) AGENT_NAME="conductor" ;; app/agents/*.py) BASE=$(basename "$file" .py) # Map filename to agent name (e.g. qa_tester_agent.py → qa_tester_agent) if grep -q "\"$BASE\"" "$AGENT_VERSIONS_FILE" 2>/dev/null; then AGENT_NAME="$BASE" fi ;; esac if [ -n "$AGENT_NAME" ] && [ -f "$AGENT_VERSIONS_FILE" ]; then CURRENT_AGENT_VER=$(python3 -c "import json; d=json.load(open('$AGENT_VERSIONS_FILE')); print(d.get('$AGENT_NAME','1.0.0'))") MAJOR=$(echo "$CURRENT_AGENT_VER" | cut -d. -f1) MINOR=$(echo "$CURRENT_AGENT_VER" | cut -d. -f2) PATCH=$(echo "$CURRENT_AGENT_VER" | cut -d. -f3) # Check if commit has agent-feat for this agent if git log "$LAST_COMMIT..HEAD" --format=%s | grep -iq "agent-feat:.*$AGENT_NAME"; then MINOR=$((MINOR + 1)) PATCH=0 else PATCH=$((PATCH + 1)) fi NEW_AGENT_VER="${MAJOR}.${MINOR}.${PATCH}" python3 -c " import json d = json.load(open('$AGENT_VERSIONS_FILE')) d['$AGENT_NAME'] = '$NEW_AGENT_VER' with open('$AGENT_VERSIONS_FILE', 'w', encoding='utf-8') as f: json.dump(d, f, ensure_ascii=False, indent=2) " echo ">>> Agent $AGENT_NAME: $CURRENT_AGENT_VER → $NEW_AGENT_VER" fi done <<< "$CHANGED_FILES" # Commit version bumps if [ "$HAS_PROJECT_CHANGES" = true ] || grep -q "^app/agents/" <<< "$CHANGED_FILES"; then git add "$VERSION_FILE" "$AGENT_VERSIONS_FILE" git commit -m "chore: auto-bump versions [skip ci]" git push origin "$BRANCH" || echo "Warning: push failed (might be already pushed)" fi fi fi # Save current commit for next deploy git rev-parse HEAD > "$LAST_COMMIT_FILE" # Python venv if [ ! -d "$INSTALL_DIR/venv" ]; then sudo -u voidea python3 -m venv "$INSTALL_DIR/venv" fi sudo -u voidea "$INSTALL_DIR/venv/bin/pip" install --upgrade pip sudo -u voidea "$INSTALL_DIR/venv/bin/pip" install -e "$INSTALL_DIR" # Install Playwright for QATesterAgent sudo -u voidea "$INSTALL_DIR/venv/bin/pip" install playwright sudo -u voidea "$INSTALL_DIR/venv/bin/playwright" install chromium # .env if [ ! -f "$INSTALL_DIR/.env" ]; then sudo -u voidea cp "$INSTALL_DIR/.env.example" "$INSTALL_DIR/.env" echo ">>> Заполните $INSTALL_DIR/.env и запустите deploy.sh снова" exit 1 fi # Build frontend cd "$INSTALL_DIR/webui" npm ci npm run build # Run migrations sudo -u voidea "$INSTALL_DIR/venv/bin/alembic" -c "$INSTALL_DIR/alembic.ini" upgrade head # Install nginx config if [ -d /etc/nginx/sites-available ]; then sudo cp "$INSTALL_DIR/deploy/voidea.nginx.conf" /etc/nginx/sites-available/voidea if [ ! -f /etc/nginx/sites-enabled/voidea ]; then sudo ln -sf /etc/nginx/sites-available/voidea /etc/nginx/sites-enabled/ fi fi # Install systemd units sudo cp "$INSTALL_DIR/deploy/voidea-api.service" /etc/systemd/system/ sudo cp "$INSTALL_DIR/deploy/voidea-worker.service" /etc/systemd/system/ sudo cp "$INSTALL_DIR/deploy/voidea-beat.service" /etc/systemd/system/ sudo systemctl daemon-reload # Write deploy timestamp for debug mode auto-enable (48h) date +%s | sudo -u voidea tee "$INSTALL_DIR/.last_deploy" > /dev/null # Enable and start sudo systemctl enable voidea-api sudo systemctl enable voidea-worker sudo systemctl enable voidea-beat sudo systemctl restart voidea-api sudo systemctl restart voidea-worker sudo systemctl restart voidea-beat # Restart nginx if config exists if [ -f /etc/nginx/sites-enabled/voidea ]; then sudo systemctl reload nginx || true fi echo "=== Deploy complete ===" echo "Check status: sudo systemctl status voidea-api"