Files
smartsoltech_site/bin/update.sh
Andrey K. Choi 8f1e0459fc 🔧 Restructure scripts and add CLI tool
 New features:
- Add CLI tool for container command execution
- Reorganize all scripts into bin/ directory
- Create convenient wrappers in project root
- Add local changes auto-commit functionality
- Enhanced backup repository management

📁 Structure changes:
- Move all scripts to bin/ directory
- Create wrapper scripts in root (cli, update, start, stop, logs)
- Add setup-backup.sh for backup repository management
- Update documentation with new CLI examples

🛠️ CLI capabilities:
- Django commands (shell, migrate, collectstatic, etc.)
- System commands (bash, logs, status)
- Container management (restart, status)
- Interactive and non-interactive modes

📚 Documentation:
- Updated SCRIPTS_README.md with CLI examples
- Added troubleshooting section
- Comprehensive usage examples
2025-11-25 06:51:52 +09:00

370 lines
13 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# =============================================================================
# SmartSolTech - Скрипт автоматического обновления
# =============================================================================
set -e # Выход при любой ошибке
# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Функция для логирования
log() {
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}
success() {
echo -e "${GREEN}$1${NC}"
}
warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
error() {
echo -e "${RED}$1${NC}"
}
# Функция проверки зависимостей
check_dependencies() {
log "Проверка зависимостей..."
if ! command -v git &> /dev/null; then
error "Git не установлен"
exit 1
fi
if ! command -v docker &> /dev/null; then
error "Docker не установлен"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
error "Docker Compose не установлен"
exit 1
fi
success "Все зависимости найдены"
}
# Функция очистки staticfiles
cleanup_staticfiles() {
log "Очистка staticfiles..."
if [ -d "smartsoltech/staticfiles" ]; then
warning "Найдена папка staticfiles, удаляем..."
chmod -R 755 smartsoltech/staticfiles 2>/dev/null || true
rm -rf smartsoltech/staticfiles
success "Staticfiles очищены"
fi
}
# Функция сохранения локальных изменений
save_local_changes() {
log "Проверка локальных изменений..."
# Проверяем есть ли изменения в рабочей директории или индексе
if [ -n "$(git status --porcelain)" ]; then
warning "Обнаружены локальные изменения, сохраняем в коммит..."
# Добавляем все изменения
git add .
# Создаем коммит с временной меткой
local commit_msg="Auto commit before update $(date '+%Y-%m-%d %H:%M:%S')"
if git commit -m "$commit_msg"; then
success "Локальные изменения сохранены в коммит"
log "Коммит: $commit_msg"
else
warning "Не удалось создать коммит (возможно нет изменений для коммита)"
fi
else
log "Локальных изменений не обнаружено"
fi
}
update_code() {
local remote_name="${1:-origin}"
log "Обновление кода из репозитория $remote_name..."
# Проверяем существование удаленного репозитория
if ! git remote | grep -q "^${remote_name}$"; then
error "Удаленный репозиторий '$remote_name' не найден"
log "Доступные репозитории:"
git remote -v
return 1
fi
# Настраиваем стратегию pull если не настроено
if [ -z "$(git config pull.rebase 2>/dev/null)" ]; then
log "Настраиваем стратегию Git pull..."
git config pull.rebase false
fi
# Получаем обновления
log "Получение обновлений из $remote_name..."
git fetch $remote_name
# Обновляем текущую ветку
local current_branch
current_branch=$(git rev-parse --abbrev-ref HEAD)
# Пробуем обновить с обработкой конфликтов
if ! git pull $remote_name $current_branch; then
error "Не удалось обновить код. Возможно есть конфликты."
log "Попробуйте выполнить команды вручную:"
log " git status"
log " git merge --abort # если нужно отменить"
log " git pull $remote_name $current_branch"
return 1
fi
success "Код обновлен с ветки $current_branch из $remote_name"
}
# Функция остановки контейнеров
stop_containers() {
log "Остановка контейнеров..."
if docker-compose ps | grep -q "Up"; then
docker-compose down
success "Контейнеры остановлены"
else
warning "Контейнеры уже остановлены"
fi
}
# Функция сборки образов
build_images() {
log "Сборка Docker образов..."
# Принудительная пересборка
docker-compose build --no-cache
success "Образы собраны"
}
# Функция запуска контейнеров
start_containers() {
log "Запуск контейнеров..."
# Запуск в фоновом режиме
docker-compose up -d
# Ожидание готовности
log "Ожидание готовности сервисов..."
sleep 10
# Проверка статуса
if docker-compose ps | grep -q "Exit"; then
error "Некоторые контейнеры завершились с ошибкой"
docker-compose ps
return 1
fi
success "Контейнеры запущены"
}
# Функция выполнения миграций
run_migrations() {
log "Выполнение миграций Django..."
# Ожидание готовности БД
log "Ожидание готовности базы данных..."
sleep 15
# Выполнение миграций
docker-compose exec -T web python smartsoltech/manage.py migrate
success "Миграции выполнены"
}
# Функция сбора статических файлов
collect_static() {
log "Сбор статических файлов..."
docker-compose exec -T web python smartsoltech/manage.py collectstatic --noinput
success "Статические файлы собраны"
}
# Функция проверки состояния сервисов
health_check() {
log "Проверка состояния сервисов..."
# Проверка веб-сервера
local max_attempts=30
local attempt=1
while [ $attempt -le $max_attempts ]; do
if curl -sf http://localhost:8000/ > /dev/null 2>&1; then
success "Веб-сервер доступен"
break
fi
if [ $attempt -eq $max_attempts ]; then
error "Веб-сервер недоступен после $max_attempts попыток"
return 1
fi
log "Попытка $attempt/$max_attempts - ожидание веб-сервера..."
sleep 5
((attempt++))
done
# Показать статус контейнеров
echo ""
log "Статус контейнеров:"
docker-compose ps
success "Проверка здоровья завершена"
}
# Функция отображения логов
show_logs() {
log "Последние логи сервисов:"
echo ""
docker-compose logs --tail=20 web
}
# Функция бэкапа в удаленный репозиторий
backup_to_remote() {
local backup_remote="${1:-backup}"
# Пропускаем если это тот же репозиторий что используется для обновления
local update_remote="${2:-origin}"
if [ "$backup_remote" = "$update_remote" ]; then
log "Пропускаем бэкап - используется тот же репозиторий для обновления"
return 0
fi
log "Создание бэкапа в удаленном репозитории $backup_remote..."
if git remote | grep -q "^${backup_remote}$"; then
# Пушим текущее состояние в backup (изменения уже сохранены в коммит)
if git push $backup_remote master; then
success "Бэкап создан в удаленном репозитории $backup_remote"
else
warning "Не удалось создать бэкап в $backup_remote"
fi
else
warning "$backup_remote репозиторий не настроен, пропускаем бэкап"
fi
}
# Главная функция
main() {
local remote_source="${1:-origin}"
local backup_remote="${2:-backup}"
echo ""
echo "🚀 SmartSolTech - Автоматическое обновление"
echo "=========================================="
echo "📡 Источник: $remote_source"
if git remote | grep -q "^${backup_remote}$"; then
echo "💾 Бэкап: $backup_remote"
fi
echo ""
# Проверка что мы в правильной директории
if [ ! -f "docker-compose.yml" ]; then
error "docker-compose.yml не найден. Запустите скрипт из корня проекта."
exit 1
fi
local start_time
start_time=$(date +%s)
# Выполняем все этапы
check_dependencies
save_local_changes
backup_to_remote "$backup_remote" "$remote_source"
cleanup_staticfiles
update_code "$remote_source"
stop_containers
build_images
start_containers
run_migrations
collect_static
health_check
local end_time
end_time=$(date +%s)
local duration=$((end_time - start_time))
echo ""
echo "🎉 Обновление завершено успешно!"
echo "⏱️ Время выполнения: ${duration} секунд"
echo "📡 Источник обновления: $remote_source"
echo ""
echo "📊 Полезная информация:"
echo " • Веб-сайт: http://localhost:8000"
echo " • Админка: http://localhost:8000/admin"
echo " • PgAdmin: http://localhost:8080"
echo ""
# Предложение показать логи
read -p "Показать логи сервисов? (y/N): " show_logs_choice
if [[ $show_logs_choice =~ ^[Yy]$ ]]; then
show_logs
fi
success "Готово!"
}
# Обработка прерываний
trap 'echo ""; error "Обновление прервано пользователем"; exit 130' INT TERM
# Обработка ошибок
error_handler() {
local line_no=$1
error "Ошибка на строке $line_no"
echo ""
echo "Для диагностики можете выполнить:"
echo " docker-compose logs"
echo " docker-compose ps"
exit 1
}
trap 'error_handler $LINENO' ERR
# Запуск с параметрами
case "${1:-}" in
--help|-h)
echo "SmartSolTech - Скрипт автоматического обновления"
echo ""
echo "Использование:"
echo " $0 - Полное обновление из origin (по умолчанию)"
echo " $0 origin - Обновление из origin репозитория"
echo " $0 backup - Обновление из backup репозитория"
echo " $0 origin backup - Обновление из origin с бэкапом в backup"
echo " $0 backup origin - Обновление из backup с бэкапом в origin"
echo " $0 --help - Показать эту справку"
echo " $0 --logs - Показать логи без обновления"
echo " $0 --status - Показать статус без обновления"
echo ""
echo "Примеры:"
echo " $0 # обновление из origin"
echo " $0 backup # обновление из backup репозитория"
echo " $0 origin backup # обновление из origin, бэкап в backup"
echo ""
exit 0
;;
--logs)
show_logs
exit 0
;;
--status)
docker-compose ps
health_check
exit 0
;;
*)
# Передаем все параметры в main
main "$@"
;;
esac