chore: Обновление Docker Compose и CI/CD пайплайна
- Docker Compose теперь использует GitHub Secrets для токенов ботов (приоритет над .env) - Добавлена функция ручного отката с указанием коммита - Реализованы проверки работоспособности с экспоненциальной задержкой - Улучшены уведомления об откате
This commit is contained in:
1039
.github/workflows/deploy.yml
vendored
Normal file
1039
.github/workflows/deploy.yml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
382
.github/workflows/pipeline.yml
vendored
382
.github/workflows/pipeline.yml
vendored
@@ -5,11 +5,23 @@ on:
|
|||||||
branches: [ main, 'develop', 'dev-*', 'feature/**' ]
|
branches: [ main, 'develop', 'dev-*', 'feature/**' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main, develop ]
|
branches: [ main, develop ]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
action:
|
||||||
|
description: 'Action to perform'
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- rollback
|
||||||
|
rollback_to_commit:
|
||||||
|
description: 'Commit hash to rollback to (optional, uses last deploy if empty)'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Test
|
name: Test & Code Quality
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -25,6 +37,28 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -r tests/infra/requirements-test.txt
|
pip install -r tests/infra/requirements-test.txt
|
||||||
|
pip install flake8 black isort mypy || true
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
|
- 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 infrastructure tests
|
- name: Run infrastructure tests
|
||||||
run: |
|
run: |
|
||||||
@@ -34,6 +68,19 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -m pytest tests/infra/test_prometheus_config.py -v
|
python -m pytest tests/infra/test_prometheus_config.py -v
|
||||||
|
|
||||||
|
- name: Check for merge conflicts
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
run: |
|
||||||
|
echo "🔍 Checking for merge conflicts..."
|
||||||
|
git fetch origin main
|
||||||
|
if ! git merge --no-commit --no-ff origin/main; then
|
||||||
|
echo "❌ Merge conflicts detected!"
|
||||||
|
git merge --abort || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
git merge --abort || true
|
||||||
|
echo "✅ No merge conflicts detected"
|
||||||
|
|
||||||
- name: Upload test results
|
- name: Upload test results
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -51,31 +98,181 @@ jobs:
|
|||||||
to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
message: |
|
message: |
|
||||||
🧪 CI Tests ${{ job.status }}
|
${{ job.status == 'success' && '✅' || '❌' }} CI Tests: ${{ job.status }}
|
||||||
|
|
||||||
Repository: prod
|
📦 Repository: prod
|
||||||
Branch: ${{ github.ref_name }}
|
🌿 Branch: ${{ github.ref_name }}
|
||||||
Commit: ${{ github.sha }}
|
📝 Commit: ${{ github.sha }}
|
||||||
Author: ${{ github.actor }}
|
👤 Author: ${{ github.actor }}
|
||||||
|
|
||||||
${{ job.status == 'success' && '✅ All tests passed! Ready for deployment.' || '❌ Tests failed! Deployment blocked.' }}
|
${{ job.status == 'success' && '✅ All tests passed! Pull request will be created.' || '❌ Tests failed! Deployment blocked.' }}
|
||||||
|
|
||||||
View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
deploy:
|
create-pr:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Deploy
|
name: Create Pull Request
|
||||||
needs: test
|
needs: test
|
||||||
if: github.event_name == 'workflow_dispatch' # Только ручной запуск через кнопку
|
if: |
|
||||||
|
github.event_name == 'push' &&
|
||||||
|
needs.test.result == 'success' &&
|
||||||
|
github.ref_name != 'main' &&
|
||||||
|
github.ref_name != 'develop' &&
|
||||||
|
(startsWith(github.ref_name, 'dev-') || startsWith(github.ref_name, 'feature/'))
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Check if PR already exists
|
||||||
|
id: check-pr
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const branchName = context.ref.replace('refs/heads/', '');
|
||||||
|
const { data: prs } = await github.rest.pulls.list({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
head: `${context.repo.owner}:${branchName}`,
|
||||||
|
base: 'main',
|
||||||
|
state: 'open'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (prs.length > 0) {
|
||||||
|
core.setOutput('exists', 'true');
|
||||||
|
core.setOutput('number', prs[0].number);
|
||||||
|
core.setOutput('url', prs[0].html_url);
|
||||||
|
} else {
|
||||||
|
core.setOutput('exists', 'false');
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Update existing PR
|
||||||
|
if: steps.check-pr.outputs.exists == 'true'
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const prNumber = parseInt('${{ steps.check-pr.outputs.number }}');
|
||||||
|
const branchName = context.ref.replace('refs/heads/', '');
|
||||||
|
|
||||||
|
await github.rest.pulls.update({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
pull_number: prNumber,
|
||||||
|
title: `Merge ${branchName} into main`,
|
||||||
|
body: `## Updated Changes\n\nPR updated with new commits after successful CI tests.\n\n- Latest commit: ${{ github.sha }}\n- Branch: \`${branchName}\`\n- Author: @${{ github.actor }}\n\n## Test Results\n\n✅ All tests passed successfully!\n\nPlease review the changes and merge when ready.`
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`✅ PR #${prNumber} updated successfully`);
|
||||||
|
|
||||||
|
- name: Create Pull Request
|
||||||
|
if: steps.check-pr.outputs.exists == 'false'
|
||||||
|
id: create-pr
|
||||||
|
uses: peter-evans/create-pull-request@v5
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
branch: ${{ github.ref_name }}
|
||||||
|
base: main
|
||||||
|
title: "Merge ${{ github.ref_name }} into main"
|
||||||
|
body: |
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
This PR was automatically created after successful CI tests.
|
||||||
|
|
||||||
|
- Branch: `${{ github.ref_name }}`
|
||||||
|
- Commit: `${{ github.sha }}`
|
||||||
|
- Author: @${{ github.actor }}
|
||||||
|
|
||||||
|
## Test Results
|
||||||
|
|
||||||
|
✅ All tests passed successfully!
|
||||||
|
|
||||||
|
Please review the changes and merge when ready.
|
||||||
|
labels: |
|
||||||
|
automated
|
||||||
|
ready-for-review
|
||||||
|
draft: false
|
||||||
|
|
||||||
|
- name: Get created PR number
|
||||||
|
if: steps.check-pr.outputs.exists == 'false' && steps.create-pr.outcome == 'success'
|
||||||
|
id: get-pr-number
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const branchName = context.ref.replace('refs/heads/', '');
|
||||||
|
const { data: prs } = await github.rest.pulls.list({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
head: `${context.repo.owner}:${branchName}`,
|
||||||
|
base: 'main',
|
||||||
|
state: 'open'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (prs.length > 0) {
|
||||||
|
core.setOutput('number', prs[0].number);
|
||||||
|
core.setOutput('url', prs[0].html_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Send PR notification - PR exists
|
||||||
|
if: steps.check-pr.outputs.exists == 'true'
|
||||||
|
uses: appleboy/telegram-action@v1.0.0
|
||||||
|
with:
|
||||||
|
to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
|
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
|
message: |
|
||||||
|
ℹ️ Pull Request Updated
|
||||||
|
|
||||||
|
📦 Repository: prod
|
||||||
|
🌿 Branch: ${{ github.ref_name }} → main
|
||||||
|
📝 Commit: ${{ github.sha }}
|
||||||
|
👤 Author: ${{ github.actor }}
|
||||||
|
|
||||||
|
✅ All tests passed! PR #${{ steps.check-pr.outputs.number }} already exists and has been updated.
|
||||||
|
|
||||||
|
🔗 View PR: ${{ steps.check-pr.outputs.url }}
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Send PR notification - PR created
|
||||||
|
if: steps.check-pr.outputs.exists == 'false' && steps.create-pr.outcome == 'success'
|
||||||
|
uses: appleboy/telegram-action@v1.0.0
|
||||||
|
with:
|
||||||
|
to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
|
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
|
message: |
|
||||||
|
📝 Pull Request Created
|
||||||
|
|
||||||
|
📦 Repository: prod
|
||||||
|
🌿 Branch: ${{ github.ref_name }} → main
|
||||||
|
📝 Commit: ${{ github.sha }}
|
||||||
|
👤 Author: ${{ github.actor }}
|
||||||
|
|
||||||
|
✅ All tests passed! Pull request #${{ steps.get-pr-number.outputs.number }} has been created and is ready for review.
|
||||||
|
|
||||||
|
🔗 View PR: ${{ steps.get-pr-number.outputs.url }}
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
rollback:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Manual Rollback
|
||||||
|
if: |
|
||||||
|
github.event_name == 'workflow_dispatch' &&
|
||||||
|
github.event.inputs.action == 'rollback'
|
||||||
environment:
|
environment:
|
||||||
name: production
|
name: production
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
|
||||||
- name: Deploy to server
|
- name: Manual Rollback
|
||||||
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 }}
|
||||||
@@ -84,126 +281,135 @@ jobs:
|
|||||||
port: ${{ vars.SSH_PORT || secrets.SSH_PORT || 22 }}
|
port: ${{ vars.SSH_PORT || secrets.SSH_PORT || 22 }}
|
||||||
script: |
|
script: |
|
||||||
set -e
|
set -e
|
||||||
echo "🚀 Starting deployment..."
|
echo "🔄 Starting manual rollback..."
|
||||||
|
|
||||||
# Переходим в директорию проекта
|
|
||||||
cd /home/prod
|
cd /home/prod
|
||||||
|
DEPLOY_HISTORY="/home/prod/.deploy_history.txt"
|
||||||
|
DEPLOY_HISTORY_SIZE="${DEPLOY_HISTORY_SIZE:-10}"
|
||||||
|
|
||||||
# Сохраняем текущий коммит для отката
|
# Определяем коммит для отката
|
||||||
CURRENT_COMMIT=$(git rev-parse HEAD)
|
if [ -n "${{ github.event.inputs.rollback_to_commit }}" ]; then
|
||||||
echo "Current commit: $CURRENT_COMMIT" > /tmp/last_deploy_commit.txt
|
ROLLBACK_COMMIT="${{ github.event.inputs.rollback_to_commit }}"
|
||||||
|
echo "📝 Using specified commit: $ROLLBACK_COMMIT"
|
||||||
|
else
|
||||||
|
# Используем последний успешный деплой из истории
|
||||||
|
ROLLBACK_COMMIT=$(grep "|success" "$DEPLOY_HISTORY" 2>/dev/null | tail -1 | cut -d'|' -f2 || echo "")
|
||||||
|
|
||||||
# Обновляем код
|
# Если нет в истории, используем сохраненный коммит
|
||||||
echo "📥 Pulling latest changes..."
|
if [ -z "$ROLLBACK_COMMIT" ]; then
|
||||||
|
if [ -f "/tmp/last_deploy_commit.txt" ]; then
|
||||||
# Исправляем права на файлы перед обновлением
|
ROLLBACK_COMMIT=$(cat /tmp/last_deploy_commit.txt)
|
||||||
sudo chown -R deploy:deploy /home/prod || true
|
echo "📝 Using saved commit from /tmp/last_deploy_commit.txt: $ROLLBACK_COMMIT"
|
||||||
|
else
|
||||||
|
echo "❌ No commit specified and no previous deploy found!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "📝 Using last successful deploy from history: $ROLLBACK_COMMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Проверяем что коммит существует
|
||||||
git fetch origin main
|
git fetch origin main
|
||||||
git reset --hard origin/main
|
if ! git rev-parse --verify "$ROLLBACK_COMMIT" > /dev/null 2>&1; then
|
||||||
|
echo "❌ Commit $ROLLBACK_COMMIT not found!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Устанавливаем правильные права после обновления
|
# Откатываем код
|
||||||
|
echo "🔄 Rolling back to commit: $ROLLBACK_COMMIT"
|
||||||
|
|
||||||
|
# Исправляем права на файлы
|
||||||
sudo chown -R deploy:deploy /home/prod || true
|
sudo chown -R deploy:deploy /home/prod || true
|
||||||
|
|
||||||
# Проверяем, что изменения есть
|
git reset --hard "$ROLLBACK_COMMIT"
|
||||||
NEW_COMMIT=$(git rev-parse HEAD)
|
|
||||||
if [ "$CURRENT_COMMIT" = "$NEW_COMMIT" ]; then
|
|
||||||
echo "ℹ️ No new changes to deploy"
|
|
||||||
else
|
|
||||||
echo "✅ Code updated: $CURRENT_COMMIT → $NEW_COMMIT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Перезапускаем сервисы
|
# Устанавливаем правильные права после отката
|
||||||
echo "🔄 Restarting services..."
|
sudo chown -R deploy:deploy /home/prod || true
|
||||||
if command -v make &> /dev/null; then
|
|
||||||
make restart || docker-compose restart
|
|
||||||
else
|
|
||||||
cd /home/prod
|
|
||||||
docker-compose down
|
|
||||||
docker-compose up -d --build
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✅ Deployment completed"
|
echo "✅ Code rolled back to: $ROLLBACK_COMMIT"
|
||||||
|
|
||||||
- name: Health check
|
# Пересобираем все контейнеры с обновлением базовых образов и кешированием
|
||||||
uses: appleboy/ssh-action@v1.0.0
|
echo "🔨 Rebuilding all containers with --pull (updating base images, using cache)..."
|
||||||
with:
|
docker-compose down || true
|
||||||
host: ${{ vars.SERVER_HOST || secrets.SERVER_HOST }}
|
docker-compose build --pull
|
||||||
username: ${{ vars.SERVER_USER || secrets.SERVER_USER }}
|
docker-compose up -d
|
||||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
||||||
port: ${{ vars.SSH_PORT || secrets.SSH_PORT || 22 }}
|
|
||||||
script: |
|
|
||||||
echo "🏥 Running health checks..."
|
|
||||||
|
|
||||||
# Проверяем статус контейнеров сначала
|
echo "✅ Containers rebuilt and started"
|
||||||
echo "📊 Checking container status..."
|
|
||||||
cd /home/prod
|
|
||||||
docker-compose ps || docker ps --filter "name=bots_"
|
|
||||||
|
|
||||||
# Ждем запуска сервисов (увеличено время)
|
# Ждем запуска сервисов
|
||||||
echo "⏳ Waiting for services to start (30 seconds)..."
|
echo "⏳ Waiting for services to start (45 seconds)..."
|
||||||
sleep 30
|
sleep 45
|
||||||
|
|
||||||
# Функция для проверки с повторными попытками
|
# Health checks с экспоненциальным retry
|
||||||
check_health() {
|
check_health() {
|
||||||
local service=$1
|
local service=$1
|
||||||
local url=$2
|
local url=$2
|
||||||
local max_attempts=5
|
|
||||||
local attempt=1
|
local attempt=1
|
||||||
|
local delays=(5 15 45)
|
||||||
|
local max_attempts=${#delays[@]}
|
||||||
|
|
||||||
echo "🔍 Checking $service health..."
|
echo "🔍 Checking $service health..."
|
||||||
|
|
||||||
while [ $attempt -le $max_attempts ]; do
|
while [ $attempt -le $max_attempts ]; do
|
||||||
if curl -f -s --max-time 5 "$url" > /dev/null 2>&1; then
|
if curl -f -s --max-time 10 "$url" > /dev/null 2>&1; then
|
||||||
echo "✅ $service is healthy (attempt $attempt/$max_attempts)"
|
echo "✅ $service is healthy (attempt $attempt/$max_attempts)"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo "⏳ $service not ready yet (attempt $attempt/$max_attempts), waiting 10 seconds..."
|
if [ $attempt -lt $max_attempts ]; then
|
||||||
sleep 10
|
delay=${delays[$((attempt - 1))]}
|
||||||
attempt=$((attempt + 1))
|
echo "⏳ $service not ready yet (attempt $attempt/$max_attempts), waiting ${delay} seconds..."
|
||||||
|
sleep $delay
|
||||||
|
else
|
||||||
|
echo "❌ $service health check failed after $max_attempts attempts"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
attempt=$((attempt + 1))
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "❌ $service health check failed after $max_attempts attempts"
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Проверяем Prometheus с повторными попытками
|
HEALTH_CHECK_FAILED=0
|
||||||
if ! check_health "Prometheus" "http://localhost:9090/-/healthy"; then
|
|
||||||
echo "⚠️ Prometheus health check failed, but continuing..."
|
check_health "Prometheus" "http://localhost:9090/-/healthy" || HEALTH_CHECK_FAILED=1
|
||||||
echo "📊 Checking Prometheus logs:"
|
check_health "Grafana" "http://localhost:3000/api/health" || HEALTH_CHECK_FAILED=1
|
||||||
docker-compose logs --tail=20 prometheus || true
|
check_health "Telegram Bot" "http://localhost:8080/health" || HEALTH_CHECK_FAILED=1
|
||||||
|
check_health "AnonBot" "http://localhost:8081/health" || HEALTH_CHECK_FAILED=1
|
||||||
|
|
||||||
|
if [ $HEALTH_CHECK_FAILED -eq 1 ]; then
|
||||||
|
echo "⚠️ Some health checks failed, but rollback completed"
|
||||||
|
else
|
||||||
|
echo "✅ All health checks passed after rollback!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Проверяем Grafana с повторными попытками
|
# Обновляем историю
|
||||||
if ! check_health "Grafana" "http://localhost:3000/api/health"; then
|
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
|
||||||
echo "⚠️ Grafana health check failed, but continuing..."
|
COMMIT_MESSAGE=$(git log -1 --pretty=format:"%s" "$ROLLBACK_COMMIT" 2>/dev/null || echo "Manual rollback")
|
||||||
echo "📊 Checking Grafana logs:"
|
COMMIT_AUTHOR="${{ github.actor }}"
|
||||||
docker-compose logs --tail=20 grafana || true
|
echo "${TIMESTAMP}|${ROLLBACK_COMMIT}|${COMMIT_MESSAGE}|${COMMIT_AUTHOR}|rolled_back" >> "$DEPLOY_HISTORY"
|
||||||
fi
|
|
||||||
|
|
||||||
# Проверяем статус контейнеров
|
# Оставляем только последние N записей
|
||||||
echo "📊 Container status:"
|
tail -n "$DEPLOY_HISTORY_SIZE" "$DEPLOY_HISTORY" > "${DEPLOY_HISTORY}.tmp" && mv "${DEPLOY_HISTORY}.tmp" "$DEPLOY_HISTORY"
|
||||||
cd /home/prod
|
|
||||||
docker-compose ps || docker ps --filter "name=bots_"
|
|
||||||
|
|
||||||
echo "✅ Health checks completed"
|
echo "✅ Rollback completed successfully"
|
||||||
|
|
||||||
- name: Send deployment notification
|
- name: Send rollback notification
|
||||||
if: always()
|
if: always()
|
||||||
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 }}
|
||||||
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
message: |
|
message: |
|
||||||
🚀 Deployment ${{ job.status }}
|
🔄 Manual Rollback: ${{ job.status }}
|
||||||
|
|
||||||
Repository: prod
|
📦 Repository: prod
|
||||||
Branch: ${{ github.ref_name }}
|
🌿 Branch: main
|
||||||
Commit: ${{ github.sha }}
|
📝 Commit: ${{ github.event.inputs.rollback_to_commit || 'Previous successful deploy' }}
|
||||||
Author: ${{ github.actor }}
|
👤 Author: ${{ github.actor }}
|
||||||
|
|
||||||
${{ job.status == 'success' && '✅ Deployment successful!' || '❌ Deployment failed!' }}
|
${{ job.status == 'success' && '✅ Rollback completed successfully! Services restored to specified version.' || '❌ Rollback failed! Check logs for details.' }}
|
||||||
|
|
||||||
View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
🔗 View details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|||||||
@@ -148,10 +148,10 @@ services:
|
|||||||
- LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-30}
|
- LOG_RETENTION_DAYS=${LOG_RETENTION_DAYS:-30}
|
||||||
- METRICS_HOST=${METRICS_HOST:-0.0.0.0}
|
- METRICS_HOST=${METRICS_HOST:-0.0.0.0}
|
||||||
- METRICS_PORT=${METRICS_PORT:-8080}
|
- METRICS_PORT=${METRICS_PORT:-8080}
|
||||||
# Telegram settings
|
# Telegram settings (токены из GitHub Secrets имеют приоритет над .env)
|
||||||
- TELEGRAM_BOT_TOKEN=${BOT_TOKEN}
|
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-${BOT_TOKEN}}
|
||||||
- TELEGRAM_LISTEN_BOT_TOKEN=${LISTEN_BOT_TOKEN}
|
- TELEGRAM_LISTEN_BOT_TOKEN=${TELEGRAM_LISTEN_BOT_TOKEN:-${LISTEN_BOT_TOKEN}}
|
||||||
- TELEGRAM_TEST_BOT_TOKEN=${TEST_BOT_TOKEN}
|
- TELEGRAM_TEST_BOT_TOKEN=${TELEGRAM_TEST_BOT_TOKEN:-${TEST_BOT_TOKEN}}
|
||||||
- TELEGRAM_PREVIEW_LINK=${PREVIEW_LINK:-false}
|
- TELEGRAM_PREVIEW_LINK=${PREVIEW_LINK:-false}
|
||||||
- TELEGRAM_MAIN_PUBLIC=${MAIN_PUBLIC}
|
- TELEGRAM_MAIN_PUBLIC=${MAIN_PUBLIC}
|
||||||
- TELEGRAM_GROUP_FOR_POSTS=${GROUP_FOR_POSTS}
|
- TELEGRAM_GROUP_FOR_POSTS=${GROUP_FOR_POSTS}
|
||||||
@@ -205,8 +205,8 @@ services:
|
|||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- DOCKER_CONTAINER=true
|
- DOCKER_CONTAINER=true
|
||||||
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
||||||
# AnonBot settings
|
# AnonBot settings (токен из GitHub Secrets имеет приоритет над .env)
|
||||||
- ANON_BOT_TOKEN=${BOT_TOKEN}
|
- ANON_BOT_TOKEN=${ANON_BOT_TOKEN:-${BOT_TOKEN}}
|
||||||
- ANON_BOT_ADMINS=${ADMINS}
|
- ANON_BOT_ADMINS=${ADMINS}
|
||||||
- ANON_BOT_DATABASE_PATH=/app/database/anon_qna.db
|
- ANON_BOT_DATABASE_PATH=/app/database/anon_qna.db
|
||||||
- ANON_BOT_DEBUG=${DEBUG:-false}
|
- ANON_BOT_DEBUG=${DEBUG:-false}
|
||||||
|
|||||||
Reference in New Issue
Block a user