diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 783144c..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: CI pipeline - -on: - push: - branches: [ 'dev-*', 'feature-*' ] - pull_request: - branches: [ 'dev-*', 'feature-*', 'main' ] - workflow_dispatch: - -jobs: - test: - runs-on: ubuntu-latest - name: Test & Code Quality - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Python 3.11 - uses: actions/setup-python@v5 - with: - python-version: '3.11' - cache: 'pip' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt - - - name: Code formatting check (Black) - run: | - echo "🔍 Checking code formatting with Black..." - black --check . || (echo "❌ Code formatting issues found. Run 'black .' to fix." && exit 1) - - - name: Import sorting check (isort) - run: | - echo "🔍 Checking import sorting with isort..." - isort --check-only . || (echo "❌ Import sorting issues found. Run 'isort .' to fix." && exit 1) - - - name: Linting (flake8) - Critical errors - run: | - echo "🔍 Running flake8 linter (critical errors only)..." - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics || true - - - name: Linting (flake8) - Warnings - run: | - echo "🔍 Running flake8 linter (warnings)..." - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics || true - continue-on-error: true - - - name: Run tests - run: | - echo "🧪 Running tests..." - python -m pytest tests/ -v --tb=short - - - name: Send test success notification - if: success() - uses: appleboy/telegram-action@v1.0.0 - with: - to: ${{ secrets.TELEGRAM_CHAT_ID }} - token: ${{ secrets.TELEGRAM_BOT_TOKEN }} - message: | - ✅ CI Tests Passed - - 📦 Repository: telegram-helper-bot - 🌿 Branch: ${{ github.ref_name }} - 📝 Commit: ${{ github.sha }} - 👤 Author: ${{ github.actor }} - - ✅ All tests passed! Code quality checks completed successfully. - - 🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - continue-on-error: true - - - name: Send test failure notification - if: failure() - uses: appleboy/telegram-action@v1.0.0 - with: - to: ${{ secrets.TELEGRAM_CHAT_ID }} - token: ${{ secrets.TELEGRAM_BOT_TOKEN }} - message: | - ❌ CI Tests Failed - - 📦 Repository: telegram-helper-bot - 🌿 Branch: ${{ github.ref_name }} - 📝 Commit: ${{ github.sha }} - 👤 Author: ${{ github.actor }} - - ❌ Tests failed! Deployment blocked. Please fix the issues and try again. - - 🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - continue-on-error: true diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index d26d3cd..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,356 +0,0 @@ -name: Deploy to Production - -on: - push: - branches: [ main ] - workflow_dispatch: - inputs: - action: - description: 'Action to perform' - required: true - type: choice - options: - - deploy - - rollback - rollback_commit: - description: 'Commit hash to rollback to (optional, uses last successful if empty)' - required: false - type: string - -jobs: - deploy: - runs-on: ubuntu-latest - name: Deploy to Production - if: | - github.event_name == 'push' || - (github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'deploy') - concurrency: - group: production-deploy-telegram-helper-bot - cancel-in-progress: false - environment: - name: production - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: main - - - name: Deploy to server - uses: appleboy/ssh-action@v1.0.0 - with: - host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }} - username: ${{ vars.SERVER_USER || secrets.SERVER_USER }} - key: ${{ secrets.SSH_PRIVATE_KEY }} - port: ${{ vars.SSH_PORT || secrets.SSH_PORT || 22 }} - script: | - set -e - export TELEGRAM_BOT_TOKEN="${{ secrets.TELEGRAM_BOT_TOKEN }}" - export TELEGRAM_TEST_BOT_TOKEN="${{ secrets.TELEGRAM_TEST_BOT_TOKEN }}" - - echo "🚀 Starting deployment to production..." - - cd /home/prod - - # Сохраняем информацию о коммите - CURRENT_COMMIT=$(git rev-parse HEAD) - COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s" || echo "Unknown") - COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an" || echo "Unknown") - TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S") - - echo "📝 Current commit: $CURRENT_COMMIT" - echo "📝 Commit message: $COMMIT_MESSAGE" - echo "📝 Author: $COMMIT_AUTHOR" - - # Записываем в историю деплоев - HISTORY_FILE="/home/prod/.deploy_history_telegram_helper_bot.txt" - HISTORY_SIZE="${DEPLOY_HISTORY_SIZE:-10}" - echo "${TIMESTAMP}|${CURRENT_COMMIT}|${COMMIT_MESSAGE}|${COMMIT_AUTHOR}|deploying" >> "$HISTORY_FILE" - tail -n "$HISTORY_SIZE" "$HISTORY_FILE" > "${HISTORY_FILE}.tmp" && mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE" - - # Обновляем код - echo "📥 Pulling latest changes from main..." - sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true - cd /home/prod/bots/telegram-helper-bot - git fetch origin main - git reset --hard origin/main - sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true - - NEW_COMMIT=$(git rev-parse HEAD) - echo "✅ Code updated: $CURRENT_COMMIT → $NEW_COMMIT" - - # Применяем миграции БД перед перезапуском контейнера - echo "🔄 Applying database migrations..." - DB_PATH="/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db" - - if [ -f "$DB_PATH" ]; then - cd /home/prod/bots/telegram-helper-bot - python3 scripts/apply_migrations.py --db "$DB_PATH" || { - echo "❌ Ошибка при применении миграций!" - exit 1 - } - echo "✅ Миграции применены успешно" - else - echo "⚠️ База данных не найдена, пропускаем миграции (будет создана при первом запуске)" - fi - - # Валидация docker-compose - echo "🔍 Validating docker-compose configuration..." - cd /home/prod - docker-compose config > /dev/null || exit 1 - echo "✅ docker-compose.yml is valid" - - # Проверка дискового пространства - MIN_FREE_GB=5 - AVAILABLE_SPACE=$(df -BG /home/prod 2>/dev/null | tail -1 | awk '{print $4}' | sed 's/G//' || echo "0") - echo "💾 Available disk space: ${AVAILABLE_SPACE}GB" - - if [ "$AVAILABLE_SPACE" -lt "$MIN_FREE_GB" ]; then - echo "⚠️ Insufficient disk space! Cleaning up Docker resources..." - docker system prune -f --volumes || true - fi - - # Пересобираем и перезапускаем контейнер бота - echo "🔨 Rebuilding and restarting telegram-bot container..." - cd /home/prod - - export TELEGRAM_BOT_TOKEN TELEGRAM_TEST_BOT_TOKEN - docker-compose stop telegram-bot || true - docker-compose build --pull telegram-bot - docker-compose up -d telegram-bot - - echo "✅ Telegram bot container rebuilt and started" - - # Ждем немного и проверяем healthcheck - echo "⏳ Waiting for container to start..." - sleep 10 - - if docker ps | grep -q bots_telegram_bot; then - echo "✅ Container is running" - else - echo "❌ Container failed to start!" - docker logs bots_telegram_bot --tail 50 || true - exit 1 - fi - - - name: Update deploy history - if: always() - uses: appleboy/ssh-action@v1.0.0 - with: - host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }} - username: ${{ vars.SERVER_USER || secrets.SERVER_USER }} - key: ${{ secrets.SSH_PRIVATE_KEY }} - port: ${{ vars.SSH_PORT || secrets.SSH_PORT || 22 }} - script: | - HISTORY_FILE="/home/prod/.deploy_history_telegram_helper_bot.txt" - - if [ -f "$HISTORY_FILE" ]; then - DEPLOY_STATUS="failed" - if [ "${{ job.status }}" = "success" ]; then - DEPLOY_STATUS="success" - fi - - sed -i '$s/|deploying$/|'"$DEPLOY_STATUS"'/' "$HISTORY_FILE" - echo "✅ Deploy history updated: $DEPLOY_STATUS" - fi - - - name: Send deployment notification - if: always() - uses: appleboy/telegram-action@v1.0.0 - with: - to: ${{ secrets.TELEGRAM_CHAT_ID }} - token: ${{ secrets.TELEGRAM_BOT_TOKEN }} - message: | - ${{ job.status == 'success' && '✅' || '❌' }} Deployment: ${{ job.status }} - - 📦 Repository: telegram-helper-bot - 🌿 Branch: main - 📝 Commit: ${{ github.sha }} - 👤 Author: ${{ github.actor }} - - ${{ job.status == 'success' && '✅ Deployment successful! Container restarted with migrations applied.' || '❌ Deployment failed! Check logs for details.' }} - - 🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - continue-on-error: true - - - name: Get PR body from merged PR - if: job.status == 'success' && github.event_name == 'push' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - echo "🔍 Searching for merged PR associated with commit ${{ github.sha }}..." - - # Находим последний мерженный PR для main ветки по merge commit SHA - COMMIT_SHA="${{ github.sha }}" - PR_NUMBER=$(gh pr list --state merged --base main --limit 10 --json number,mergeCommit --jq ".[] | select(.mergeCommit.oid == \"$COMMIT_SHA\") | .number" | head -1) - - # Если не нашли по merge commit, ищем последний мерженный PR - if [ -z "$PR_NUMBER" ]; then - echo "⚠️ PR not found by merge commit, trying to get latest merged PR..." - PR_NUMBER=$(gh pr list --state merged --base main --limit 1 --json number --jq '.[0].number') - fi - - if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then - echo "✅ Found PR #$PR_NUMBER" - PR_BODY=$(gh pr view $PR_NUMBER --json body --jq '.body // ""') - - if [ -n "$PR_BODY" ] && [ "$PR_BODY" != "null" ]; then - echo "PR_BODY<> $GITHUB_ENV - echo "$PR_BODY" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV - echo "✅ PR body extracted successfully" - else - echo "⚠️ PR body is empty" - fi - else - echo "⚠️ No merged PR found for this commit" - fi - continue-on-error: true - - - name: Send PR body to important logs - if: job.status == 'success' && github.event_name == 'push' && env.PR_BODY != '' - uses: appleboy/telegram-action@v1.0.0 - with: - to: ${{ secrets.IMPORTANT_LOGS_CHAT }} - token: ${{ secrets.TELEGRAM_BOT_TOKEN }} - message: | - 📋 Pull Request Description (PR #${{ env.PR_NUMBER }}): - - ${{ env.PR_BODY }} - - 🔗 PR: ${{ github.server_url }}/${{ github.repository }}/pull/${{ env.PR_NUMBER }} - 📝 Commit: ${{ github.sha }} - continue-on-error: true - - rollback: - runs-on: ubuntu-latest - name: Rollback to Previous Version - if: | - github.event_name == 'workflow_dispatch' && - github.event.inputs.action == 'rollback' - environment: - name: production - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: main - - - name: Rollback on server - uses: appleboy/ssh-action@v1.0.0 - with: - host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }} - username: ${{ vars.SERVER_USER || secrets.SERVER_USER }} - key: ${{ secrets.SSH_PRIVATE_KEY }} - port: ${{ vars.SSH_PORT || secrets.SSH_PORT || 22 }} - script: | - set -e - export TELEGRAM_BOT_TOKEN="${{ secrets.TELEGRAM_BOT_TOKEN }}" - export TELEGRAM_TEST_BOT_TOKEN="${{ secrets.TELEGRAM_TEST_BOT_TOKEN }}" - - echo "🔄 Starting rollback..." - - cd /home/prod - - # Определяем коммит для отката - ROLLBACK_COMMIT="${{ github.event.inputs.rollback_commit }}" - HISTORY_FILE="/home/prod/.deploy_history_telegram_helper_bot.txt" - - if [ -z "$ROLLBACK_COMMIT" ]; then - echo "📝 No commit specified, finding last successful deploy..." - if [ -f "$HISTORY_FILE" ]; then - ROLLBACK_COMMIT=$(grep "|success$" "$HISTORY_FILE" | tail -1 | cut -d'|' -f2 || echo "") - fi - - if [ -z "$ROLLBACK_COMMIT" ]; then - echo "❌ No successful deploy found in history!" - echo "💡 Please specify commit hash manually or check deploy history" - exit 1 - fi - fi - - echo "📝 Rolling back to commit: $ROLLBACK_COMMIT" - - # Проверяем, что коммит существует - cd /home/prod/bots/telegram-helper-bot - if ! git cat-file -e "$ROLLBACK_COMMIT" 2>/dev/null; then - echo "❌ Commit $ROLLBACK_COMMIT not found!" - exit 1 - fi - - # Сохраняем текущий коммит - CURRENT_COMMIT=$(git rev-parse HEAD) - COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s" "$ROLLBACK_COMMIT" || echo "Rollback") - TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S") - - echo "📝 Current commit: $CURRENT_COMMIT" - echo "📝 Target commit: $ROLLBACK_COMMIT" - echo "📝 Commit message: $COMMIT_MESSAGE" - - # Исправляем права перед откатом - sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true - - # Откатываем код - echo "🔄 Rolling back code..." - git fetch origin main - git reset --hard "$ROLLBACK_COMMIT" - - # Исправляем права после отката - sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true - - echo "✅ Code rolled back: $CURRENT_COMMIT → $ROLLBACK_COMMIT" - - # Валидация docker-compose - echo "🔍 Validating docker-compose configuration..." - cd /home/prod - docker-compose config > /dev/null || exit 1 - echo "✅ docker-compose.yml is valid" - - # Проверка дискового пространства - MIN_FREE_GB=5 - AVAILABLE_SPACE=$(df -BG /home/prod 2>/dev/null | tail -1 | awk '{print $4}' | sed 's/G//' || echo "0") - echo "💾 Available disk space: ${AVAILABLE_SPACE}GB" - - if [ "$AVAILABLE_SPACE" -lt "$MIN_FREE_GB" ]; then - echo "⚠️ Insufficient disk space! Cleaning up Docker resources..." - docker system prune -f --volumes || true - fi - - # Пересобираем и перезапускаем контейнер - echo "🔨 Rebuilding and restarting telegram-bot container..." - cd /home/prod - - export TELEGRAM_BOT_TOKEN TELEGRAM_TEST_BOT_TOKEN - docker-compose stop telegram-bot || true - docker-compose build --pull telegram-bot - docker-compose up -d telegram-bot - - echo "✅ Telegram bot container rebuilt and started" - - # Записываем в историю - echo "${TIMESTAMP}|${ROLLBACK_COMMIT}|Rollback to: ${COMMIT_MESSAGE}|github-actions|rolled_back" >> "$HISTORY_FILE" - HISTORY_SIZE="${DEPLOY_HISTORY_SIZE:-10}" - tail -n "$HISTORY_SIZE" "$HISTORY_FILE" > "${HISTORY_FILE}.tmp" && mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE" - - echo "✅ Rollback completed successfully" - - - name: Send rollback notification - if: always() - uses: appleboy/telegram-action@v1.0.0 - with: - to: ${{ secrets.TELEGRAM_CHAT_ID }} - token: ${{ secrets.TELEGRAM_BOT_TOKEN }} - message: | - ${{ job.status == 'success' && '🔄' || '❌' }} Rollback: ${{ job.status }} - - 📦 Repository: telegram-helper-bot - 🌿 Branch: main - 📝 Rolled back to: ${{ github.event.inputs.rollback_commit || 'Last successful commit' }} - 👤 Triggered by: ${{ github.actor }} - - ${{ job.status == 'success' && '✅ Rollback completed successfully! Services restored to previous version.' || '❌ Rollback failed! Check logs for details.' }} - - 🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - continue-on-error: true