Merge pull request 'dev-15' (#19) from dev-15 into master
Reviewed-on: #19
This commit was merged in pull request #19.
This commit is contained in:
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [ 'dev-*', 'feature-*', 'fix-*' ]
|
branches: [ 'dev-*', 'feature-*', 'fix-*' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ 'dev-*', 'feature-*', 'fix-*', 'main' ]
|
branches: [ 'dev-*', 'feature-*', 'fix-*', 'master' ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
|
|
||||||
✅ All tests passed! Code quality checks completed successfully.
|
✅ All tests passed! Code quality checks completed successfully.
|
||||||
|
|
||||||
🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
🔗 View details: ${{ vars.GITEA_PUBLIC_URL || github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Send test failure notification
|
- name: Send test failure notification
|
||||||
@@ -91,5 +91,5 @@ jobs:
|
|||||||
|
|
||||||
❌ Tests failed! Deployment blocked. Please fix the issues and try again.
|
❌ Tests failed! Deployment blocked. Please fix the issues and try again.
|
||||||
|
|
||||||
🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
🔗 View details: ${{ vars.GITEA_PUBLIC_URL || github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
94
.github/workflows/deploy.yml
vendored
94
.github/workflows/deploy.yml
vendored
@@ -2,7 +2,7 @@ name: Deploy to Production
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [ master ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
action:
|
action:
|
||||||
@@ -16,6 +16,14 @@ on:
|
|||||||
description: 'Commit hash to rollback to (optional, uses last successful if empty)'
|
description: 'Commit hash to rollback to (optional, uses last successful if empty)'
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
dry_run:
|
||||||
|
description: 'Dry run (only for deploy — no SSH, only show planned steps)'
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
default: no
|
||||||
|
options:
|
||||||
|
- no
|
||||||
|
- yes
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
@@ -24,6 +32,8 @@ jobs:
|
|||||||
if: |
|
if: |
|
||||||
github.event_name == 'push' ||
|
github.event_name == 'push' ||
|
||||||
(github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'deploy')
|
(github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'deploy')
|
||||||
|
env:
|
||||||
|
DRY_RUN: ${{ github.event.inputs.dry_run == 'yes' }}
|
||||||
concurrency:
|
concurrency:
|
||||||
group: production-deploy-telegram-helper-bot
|
group: production-deploy-telegram-helper-bot
|
||||||
cancel-in-progress: false
|
cancel-in-progress: false
|
||||||
@@ -34,9 +44,28 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: main
|
ref: master
|
||||||
|
|
||||||
|
- name: Dry run (simulate deploy steps)
|
||||||
|
if: github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'yes'
|
||||||
|
run: |
|
||||||
|
echo "🔍 DRY RUN — no SSH, no changes on server"
|
||||||
|
echo "Would run on server:"
|
||||||
|
echo " 1. cd /home/prod/bots/telegram-helper-bot"
|
||||||
|
echo " 2. Backup DB → database/tg-bot-database_YYYYMMDD-HHMMSS.db (удаляется при успехе)"
|
||||||
|
echo " 3. CURRENT_COMMIT + history; git fetch origin master && git reset --hard origin/master"
|
||||||
|
echo " 4. apply_migrations.py (бэкап БД делается в шаге 1, при успехе удаляется в конце)"
|
||||||
|
echo " 5. docker-compose -f /home/prod/docker-compose.yml config (validate)"
|
||||||
|
echo " 6. docker-compose stop telegram-bot; build --pull telegram-bot; up -d telegram-bot"
|
||||||
|
echo " 7. sleep 10; check container bots_telegram_bot"
|
||||||
|
echo ""
|
||||||
|
echo "Secrets/vars required: SERVER_HOST, SERVER_USER, SSH_PRIVATE_KEY, SSH_PORT, TELEGRAM_BOT_TOKEN, TELEGRAM_TEST_BOT_TOKEN"
|
||||||
|
if [ -f docker-compose.yml ]; then
|
||||||
|
echo "✅ docker-compose.yml present in repo (validation would run on server from /home/prod)"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Deploy to server
|
- name: Deploy to server
|
||||||
|
if: github.event_name != 'workflow_dispatch' || github.event.inputs.dry_run != 'yes'
|
||||||
uses: appleboy/ssh-action@v1.0.0
|
uses: appleboy/ssh-action@v1.0.0
|
||||||
with:
|
with:
|
||||||
host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }}
|
host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }}
|
||||||
@@ -50,9 +79,22 @@ jobs:
|
|||||||
|
|
||||||
echo "🚀 Starting deployment to production..."
|
echo "🚀 Starting deployment to production..."
|
||||||
|
|
||||||
cd /home/prod
|
DB_PATH="/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
|
||||||
|
DB_DIR="/home/prod/bots/telegram-helper-bot/database"
|
||||||
|
BACKUP_FILE=""
|
||||||
|
|
||||||
# Сохраняем информацию о коммите
|
sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true
|
||||||
|
cd /home/prod/bots/telegram-helper-bot
|
||||||
|
|
||||||
|
# Бэкап БД в самом начале; при успешном деплое удалим в конце
|
||||||
|
if [ -f "$DB_PATH" ]; then
|
||||||
|
echo "💾 Creating database backup (before any changes)..."
|
||||||
|
BACKUP_NAME="tg-bot-database_$(date +%Y%m%d-%H%M%S).db"
|
||||||
|
BACKUP_FILE="${DB_DIR}/${BACKUP_NAME}"
|
||||||
|
cp "$DB_PATH" "$BACKUP_FILE" && echo "✅ Backup: $BACKUP_FILE" || { echo "❌ Backup failed!"; exit 1; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Сохраняем информацию о коммите (до pull) — из репо telegram-helper-bot
|
||||||
CURRENT_COMMIT=$(git rev-parse HEAD)
|
CURRENT_COMMIT=$(git rev-parse HEAD)
|
||||||
COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s" || echo "Unknown")
|
COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s" || echo "Unknown")
|
||||||
COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an" || echo "Unknown")
|
COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an" || echo "Unknown")
|
||||||
@@ -69,20 +111,16 @@ jobs:
|
|||||||
tail -n "$HISTORY_SIZE" "$HISTORY_FILE" > "${HISTORY_FILE}.tmp" && mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE"
|
tail -n "$HISTORY_SIZE" "$HISTORY_FILE" > "${HISTORY_FILE}.tmp" && mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE"
|
||||||
|
|
||||||
# Обновляем код
|
# Обновляем код
|
||||||
echo "📥 Pulling latest changes from main..."
|
echo "📥 Pulling latest changes from master..."
|
||||||
sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true
|
git fetch origin master
|
||||||
cd /home/prod/bots/telegram-helper-bot
|
git reset --hard origin/master
|
||||||
git fetch origin main
|
|
||||||
git reset --hard origin/main
|
|
||||||
sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true
|
sudo chown -R deploy:deploy /home/prod/bots/telegram-helper-bot || true
|
||||||
|
|
||||||
NEW_COMMIT=$(git rev-parse HEAD)
|
NEW_COMMIT=$(git rev-parse HEAD)
|
||||||
echo "✅ Code updated: $CURRENT_COMMIT → $NEW_COMMIT"
|
echo "✅ Code updated: $CURRENT_COMMIT → $NEW_COMMIT"
|
||||||
|
|
||||||
# Применяем миграции БД перед перезапуском контейнера
|
# Применяем миграции БД
|
||||||
echo "🔄 Applying database migrations..."
|
echo "🔄 Applying database migrations..."
|
||||||
DB_PATH="/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
|
|
||||||
|
|
||||||
if [ -f "$DB_PATH" ]; then
|
if [ -f "$DB_PATH" ]; then
|
||||||
cd /home/prod/bots/telegram-helper-bot
|
cd /home/prod/bots/telegram-helper-bot
|
||||||
python3 scripts/apply_migrations.py --db "$DB_PATH" || {
|
python3 scripts/apply_migrations.py --db "$DB_PATH" || {
|
||||||
@@ -127,6 +165,10 @@ jobs:
|
|||||||
|
|
||||||
if docker ps | grep -q bots_telegram_bot; then
|
if docker ps | grep -q bots_telegram_bot; then
|
||||||
echo "✅ Container is running"
|
echo "✅ Container is running"
|
||||||
|
# Успешный деплой — удаляем бэкап (при ошибке на любом шаге бэкап остаётся для rollback)
|
||||||
|
if [ -n "${BACKUP_FILE:-}" ] && [ -f "$BACKUP_FILE" ]; then
|
||||||
|
rm -f "$BACKUP_FILE" && echo "✅ Backup removed (deploy success)"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo "❌ Container failed to start!"
|
echo "❌ Container failed to start!"
|
||||||
docker logs bots_telegram_bot --tail 50 || true
|
docker logs bots_telegram_bot --tail 50 || true
|
||||||
@@ -134,7 +176,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Update deploy history
|
- name: Update deploy history
|
||||||
if: always()
|
if: always() && env.DRY_RUN != 'true'
|
||||||
uses: appleboy/ssh-action@v1.0.0
|
uses: appleboy/ssh-action@v1.0.0
|
||||||
with:
|
with:
|
||||||
host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }}
|
host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }}
|
||||||
@@ -155,7 +197,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Send deployment notification
|
- name: Send deployment notification
|
||||||
if: always()
|
if: always() && env.DRY_RUN != 'true'
|
||||||
uses: appleboy/telegram-action@v1.0.0
|
uses: appleboy/telegram-action@v1.0.0
|
||||||
with:
|
with:
|
||||||
to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
@@ -164,30 +206,30 @@ jobs:
|
|||||||
${{ job.status == 'success' && '✅' || '❌' }} Deployment: ${{ job.status }}
|
${{ job.status == 'success' && '✅' || '❌' }} Deployment: ${{ job.status }}
|
||||||
|
|
||||||
📦 Repository: telegram-helper-bot
|
📦 Repository: telegram-helper-bot
|
||||||
🌿 Branch: main
|
🌿 Branch: master
|
||||||
📝 Commit: ${{ github.sha }}
|
📝 Commit: ${{ github.sha }}
|
||||||
👤 Author: ${{ github.actor }}
|
👤 Author: ${{ github.actor }}
|
||||||
|
|
||||||
${{ job.status == 'success' && '✅ Deployment successful! Container restarted with migrations applied.' || '❌ Deployment failed! Check logs for details.' }}
|
${{ 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 }}
|
🔗 View details: ${{ vars.GITEA_PUBLIC_URL || github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Get PR body from merged PR
|
- name: Get PR body from merged PR
|
||||||
if: job.status == 'success' && github.event_name == 'push'
|
if: job.status == 'success' && github.event_name == 'push' && env.DRY_RUN != 'true'
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
echo "🔍 Searching for merged PR associated with commit ${{ github.sha }}..."
|
echo "🔍 Searching for merged PR associated with commit ${{ github.sha }}..."
|
||||||
|
|
||||||
# Находим последний мерженный PR для main ветки по merge commit SHA
|
# Находим последний мерженный PR для master по merge commit SHA
|
||||||
COMMIT_SHA="${{ github.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)
|
PR_NUMBER=$(gh pr list --state merged --base master --limit 10 --json number,mergeCommit --jq ".[] | select(.mergeCommit.oid == \"$COMMIT_SHA\") | .number" | head -1)
|
||||||
|
|
||||||
# Если не нашли по merge commit, ищем последний мерженный PR
|
# Если не нашли по merge commit, ищем последний мерженный PR
|
||||||
if [ -z "$PR_NUMBER" ]; then
|
if [ -z "$PR_NUMBER" ]; then
|
||||||
echo "⚠️ PR not found by merge commit, trying to get latest merged PR..."
|
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')
|
PR_NUMBER=$(gh pr list --state merged --base master --limit 1 --json number --jq '.[0].number')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then
|
if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then
|
||||||
@@ -209,7 +251,7 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Send PR body to important logs
|
- name: Send PR body to important logs
|
||||||
if: job.status == 'success' && github.event_name == 'push' && env.PR_BODY != ''
|
if: job.status == 'success' && github.event_name == 'push' && env.DRY_RUN != 'true' && env.PR_BODY != ''
|
||||||
uses: appleboy/telegram-action@v1.0.0
|
uses: appleboy/telegram-action@v1.0.0
|
||||||
with:
|
with:
|
||||||
to: ${{ secrets.IMPORTANT_LOGS_CHAT }}
|
to: ${{ secrets.IMPORTANT_LOGS_CHAT }}
|
||||||
@@ -219,7 +261,7 @@ jobs:
|
|||||||
|
|
||||||
${{ env.PR_BODY }}
|
${{ env.PR_BODY }}
|
||||||
|
|
||||||
🔗 PR: ${{ github.server_url }}/${{ github.repository }}/pull/${{ env.PR_NUMBER }}
|
🔗 PR: ${{ vars.GITEA_PUBLIC_URL || github.server_url }}/${{ github.repository }}/pull/${{ env.PR_NUMBER }}
|
||||||
📝 Commit: ${{ github.sha }}
|
📝 Commit: ${{ github.sha }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
@@ -236,7 +278,7 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: main
|
ref: master
|
||||||
|
|
||||||
- name: Rollback on server
|
- name: Rollback on server
|
||||||
uses: appleboy/ssh-action@v1.0.0
|
uses: appleboy/ssh-action@v1.0.0
|
||||||
@@ -294,7 +336,7 @@ jobs:
|
|||||||
|
|
||||||
# Откатываем код
|
# Откатываем код
|
||||||
echo "🔄 Rolling back code..."
|
echo "🔄 Rolling back code..."
|
||||||
git fetch origin main
|
git fetch origin master
|
||||||
git reset --hard "$ROLLBACK_COMMIT"
|
git reset --hard "$ROLLBACK_COMMIT"
|
||||||
|
|
||||||
# Исправляем права после отката
|
# Исправляем права после отката
|
||||||
@@ -346,12 +388,12 @@ jobs:
|
|||||||
${{ job.status == 'success' && '🔄' || '❌' }} Rollback: ${{ job.status }}
|
${{ job.status == 'success' && '🔄' || '❌' }} Rollback: ${{ job.status }}
|
||||||
|
|
||||||
📦 Repository: telegram-helper-bot
|
📦 Repository: telegram-helper-bot
|
||||||
🌿 Branch: main
|
🌿 Branch: master
|
||||||
📝 Rolled back to: ${{ github.event.inputs.rollback_commit || 'Last successful commit' }}
|
📝 Rolled back to: ${{ github.event.inputs.rollback_commit || 'Last successful commit' }}
|
||||||
👤 Triggered by: ${{ github.actor }}
|
👤 Triggered by: ${{ github.actor }}
|
||||||
|
|
||||||
${{ job.status == 'success' && '✅ Rollback completed successfully! Services restored to previous version.' || '❌ Rollback failed! Check logs for details.' }}
|
${{ 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 }}
|
🔗 View details: ${{ vars.GITEA_PUBLIC_URL || github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user