name: CI/CD on: push: pull_request: workflow_dispatch: jobs: test: name: Test runs-on: ubuntu-latest steps: - name: Checkout uses: https://github.com/actions/checkout@v4 - name: Set up Python uses: https://github.com/actions/setup-python@v5 with: python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pytest - name: Run tests run: python -m pytest tests - name: Check syntax run: python -m compileall -q config core services utils main.py start.py tests - name: Optional Docker build check run: | if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then docker build -t vk-sales-bot:ci . else echo "Docker is not available on this Gitea runner, skipping local image build." fi deploy: name: Deploy runs-on: ubuntu-latest needs: - test if: ${{ gitea.ref == 'refs/heads/main' && (gitea.event_name == 'push' || gitea.event_name == 'workflow_dispatch') }} env: DEPLOY_PATH: /opt/vk-sales-bot SSH_HOST: infocyber.pro SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }} SSH_PORT: "22" SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} SSH_USER: root steps: - name: Checkout uses: https://github.com/actions/checkout@v4 - name: Validate deploy settings run: | set -eu : "${SSH_PRIVATE_KEY:?Missing SSH_PRIVATE_KEY secret}" echo "Deploy path: ${DEPLOY_PATH}" - name: Install deploy tools run: | set -eu if command -v rsync >/dev/null 2>&1 && command -v ssh >/dev/null 2>&1; then exit 0 fi if ! command -v apt-get >/dev/null 2>&1; then echo "apt-get is not available on this runner. Install rsync and openssh-client manually." exit 1 fi SUDO="" if command -v sudo >/dev/null 2>&1; then SUDO="sudo" fi $SUDO apt-get update $SUDO apt-get install -y openssh-client rsync - name: Configure SSH run: | set -eu mkdir -p "$HOME/.ssh" chmod 700 "$HOME/.ssh" printf '%s\n' "$SSH_PRIVATE_KEY" > "$HOME/.ssh/id_ed25519" chmod 600 "$HOME/.ssh/id_ed25519" SSH_PORT="${SSH_PORT:-22}" if [ -n "${SSH_KNOWN_HOSTS:-}" ]; then printf '%s\n' "$SSH_KNOWN_HOSTS" > "$HOME/.ssh/known_hosts" else ssh-keyscan -p "$SSH_PORT" "$SSH_HOST" > "$HOME/.ssh/known_hosts" fi chmod 644 "$HOME/.ssh/known_hosts" - name: Prepare remote directory run: | set -eu SSH_PORT="${SSH_PORT:-22}" ssh -i "$HOME/.ssh/id_ed25519" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" \ "mkdir -p '$DEPLOY_PATH' '$DEPLOY_PATH/data' '$DEPLOY_PATH/data/backups' '$DEPLOY_PATH/logs' && test -w '$DEPLOY_PATH'" - name: Sync project to server run: | set -eu SSH_PORT="${SSH_PORT:-22}" rsync -az --delete \ --exclude '.env' \ --exclude '.git/' \ --exclude '.gitea/' \ --exclude '.kilo/' \ --exclude '.vscode/' \ --exclude '.venv/' \ --exclude '__pycache__/' \ --exclude '*.pyc' \ --exclude 'data/' \ --exclude 'docs/' \ --exclude 'logs/' \ --exclude 'tests/' \ -e "ssh -i $HOME/.ssh/id_ed25519 -p $SSH_PORT" \ ./ "$SSH_USER@$SSH_HOST:$DEPLOY_PATH/" - name: Restart application run: | set -eu SSH_PORT="${SSH_PORT:-22}" ssh -i "$HOME/.ssh/id_ed25519" -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" \ "cd '$DEPLOY_PATH' && test -f .env && docker compose up -d --build --remove-orphans && docker compose ps"