laobinghu 37742571ae feat: 完成项目初始化并重构部署流程
主要变更:
- 添加完整的项目结构和模块(admin、articles、comments、users、session、oauth2、email、moderation、analytics、jobs 等)
- 实现系统初始化 API(/init/status 和 /init/run)
- 重写部署流程:迁移到 package.json scripts,删除 Makefile
- 优化部署脚本:deploy.sh、healthcheck.sh、backup.sh、restore.sh、verify-env.sh
- 更新 README.md:简化文档,整合部署指南
- 优化 AGENTS.md:精简到约 150 行,包含完整的代码规范和命令速查
- 配置 Docker Compose 自动化部署(prisma migrate deploy + seed)
- 生成 OAuth2 RSA 密钥对支持
- 添加环境变量验证和数据库备份恢复功能
2026-03-28 16:53:25 +08:00

313 lines
8.6 KiB
Bash
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
# ============================================
# LinkShare Blog - 现代化一键部署脚本
# ============================================
# 用途: 自动化部署流程,支持初始化检查
# 用法: ./scripts/deploy.sh [options]
# 示例: ./scripts/deploy.sh
# ./scripts/deploy.sh --dev
# ./scripts/deploy.sh --init-check
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
cd "$PROJECT_ROOT"
# 颜色定义
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[✓]${NC} $1"; }
log_step() { echo -e "${BLUE}[→]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[!]${NC} $1"; }
log_error() { echo -e "${RED}[✗]${NC} $1"; }
print_banner() {
echo "=========================================="
echo " LinkShare Blog 一键部署"
echo "=========================================="
echo ""
}
show_usage() {
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " --dev, --development 开发环境部署"
echo " --prod, --production 生产环境部署 (默认)"
echo " --skip-build 跳过镜像构建"
echo " --skip-migrate 跳过数据库迁移"
echo " --skip-seed 跳过数据库种子"
echo " --init-check 部署后检查初始化状态"
echo " --admin-token TOKEN 管理员 token用于初始化检查"
echo " --no-deps 不启动依赖服务"
echo " --backup 部署前自动备份数据库"
echo " -h, --help 显示此帮助"
echo ""
echo "示例:"
echo " $0 # 完整生产部署"
echo " $0 --dev # 开发环境部署"
echo " $0 --skip-build --init-check # 跳过构建并检查初始化"
echo ""
exit 1
}
# 参数解析
ENV="production"
SKIP_BUILD=false
SKIP_MIGRATE=false
SKIP_SEED=false
INIT_CHECK=false
ADMIN_TOKEN=""
INCLUDE_DEPS=true
BACKUP_BEFORE=false
while [[ $# -gt 0 ]]; do
case $1 in
--dev|--development)
ENV="development"
shift
;;
--prod|--production)
ENV="production"
shift
;;
--skip-build)
SKIP_BUILD=true
shift
;;
--skip-migrate)
SKIP_MIGRATE=true
shift
;;
--skip-seed)
SKIP_SEED=true
shift
;;
--init-check)
INIT_CHECK=true
shift
;;
--admin-token)
ADMIN_TOKEN="$2"
shift 2
;;
--no-deps)
INCLUDE_DEPS=false
shift
;;
--backup)
BACKUP_BEFORE=true
shift
;;
-h|--help)
show_usage
;;
*)
log_error "未知选项: $1"
show_usage
;;
esac
done
# 工具函数
wait_for_service() {
local url=$1
local name=$2
local max_attempts=30
local attempt=1
log_step "等待 $name 就绪..."
while [ $attempt -le $max_attempts ]; do
if curl -sf "$url" >/dev/null 2>&1; then
log_info "$name 已就绪"
return 0
fi
echo -n "."
sleep 2
((attempt++))
done
echo ""
log_error "$name 未能在预期时间内就绪"
return 1
}
check_deployment_success() {
log_step "验证部署结果..."
# 基本健康检查
if ! curl -sf http://localhost:3001/health >/dev/null; then
log_error "API 健康检查失败"
return 1
fi
log_info "API 健康检查通过"
# 检查初始化状态(如果要求)
if [ "$INIT_CHECK" = true ] && [ -n "$ADMIN_TOKEN" ]; then
local init_response=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
http://localhost:3001/init/status)
if [ "$init_response" = "200" ]; then
log_info "初始化状态检查通过"
else
log_warn "初始化状态检查失败 (HTTP $init_response)"
fi
fi
return 0
}
# 主部署流程
main() {
print_banner
log_info "目标环境: $ENV"
echo ""
# 1. 环境验证
log_step "1/5 验证环境配置..."
if [ ! -f ".env" ]; then
log_warn ".env 文件不存在,从模板创建..."
if [ -f ".env.example" ]; then
cp .env.example .env
log_warn "请编辑 .env 文件设置必要的配置!"
else
log_error "未找到 .env.example 模板"
exit 1
fi
fi
if [ -f "scripts/verify-env.sh" ]; then
log_info "运行环境验证..."
if ! bash scripts/verify-env.sh; then
log_error "环境验证失败,请修复上述问题"
exit 1
fi
fi
echo ""
# 2. 备份数据库(可选)
if [ "$BACKUP_BEFORE" = true ]; then
log_step "2/5 备份数据库..."
if [ -f "scripts/backup.sh" ]; then
bash scripts/backup.sh "pre-deploy-$(date +%Y%m%d_%H%M%S)" || {
log_warn "备份失败,但继续部署..."
}
fi
echo ""
fi
# 3. 构建镜像
if [ "$SKIP_BUILD" = false ]; then
log_step "3/5 构建 Docker 镜像..."
if ! docker-compose build api; then
log_error "镜像构建失败"
exit 1
fi
log_info "镜像构建成功"
echo ""
fi
# 4. 启动服务
log_step "4/5 启动服务..."
if [ "$INCLUDE_DEPS" = false ]; then
docker-compose up -d api || {
log_error "API 服务启动失败"
exit 1
}
else
docker-compose up -d || {
log_error "服务启动失败"
exit 1
}
fi
log_info "服务已启动"
echo ""
# 5. 等待服务就绪
if ! wait_for_service "http://localhost:3001/health" "API"; then
log_error "API 服务未就绪"
docker-compose logs api --tail=50
exit 1
fi
echo ""
# 6. 数据库迁移和 seed
if [ "$SKIP_MIGRATE" = false ]; then
log_step "6/5 运行数据库迁移..."
if docker-compose exec -T api bunx prisma migrate deploy 2>/dev/null; then
log_info "数据库迁移完成"
else
log_warn "迁移失败或无需迁移"
fi
echo ""
fi
if [ "$SKIP_SEED" = false ] && [ "$SKIP_MIGRATE" = false ]; then
log_step "7/5 运行数据库种子..."
if docker-compose exec -T api bunx prisma db seed 2>/dev/null; then
log_info "数据库种子完成"
else
log_warn "种子执行失败或数据已存在"
fi
echo ""
fi
# 7. 验证部署
if ! check_deployment_success; then
log_error "部署验证失败"
echo ""
log_error "========== 部署失败 =========="
log_error "请检查以下内容:"
log_error " 1. 查看日志: docker-compose logs -f api"
log_error " 2. 检查配置: cat .env"
log_error " 3. 验证依赖: docker-compose ps"
log_error " 4. 手动健康检查: curl http://localhost:3001/health"
exit 1
fi
# 8. 显示部署信息
echo ""
log_step "部署完成!"
echo ""
echo "=========================================="
echo "服务状态:"
echo "=========================================="
docker-compose ps
echo ""
echo "=========================================="
echo "访问地址:"
echo "=========================================="
echo "API: http://localhost:3001"
echo "健康检查: http://localhost:3001/health"
echo "Swagger: http://localhost:3001/api-docs (开发环境)"
if [ "$INIT_CHECK" = true ]; then
echo "初始化状态: http://localhost:3001/init/status (需要管理员 Token)"
fi
echo ""
echo "=========================================="
echo "常用命令:"
echo "=========================================="
echo "查看日志: docker-compose logs -f api"
echo "重启服务: docker-compose restart"
echo "停止服务: docker-compose down"
echo "备份数据库: ./scripts/backup.sh"
echo "健康检查: ./scripts/healthcheck.sh"
if [ "$INIT_CHECK" = true ]; then
echo "初始化检查: ./scripts/healthcheck.sh --admin-token <token>"
fi
echo ""
if [ -f ".env" ]; then
log_warn "请确保 .env 文件中的敏感配置已正确设置!"
fi
}
main