name: 构建并部署 Spring Boot 应用 on: push: branches: [master, develop] pull_request: branches: [master, develop] jobs: build-and-deploy: runs-on: ubuntu-latest # 使用自托管 Runner steps: - name: 检出代码 uses: actions/checkout@v4.1.1 with: fetch-depth: 0 - name: 设置 Java uses: actions/setup-java@v4.2.1 with: distribution: 'temurin' # 使用 Eclipse Temurin JDK java-version: '17' cache: 'maven' - name: 验证 Java 安装 run: | echo "验证 Java 安装:" java -version javac -version echo "JAVA_HOME: $JAVA_HOME" - name: 验证环境 run: | echo "Runner 工作目录: $(pwd)" echo "Java 版本:" java -version echo "Maven 版本:" mvn --version echo "Docker 信息:" docker --version docker info - name: 缓存 Maven 依赖 uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: 编译和打包项目 run: | mvn clean package -DskipTests ls -la target/ - name: 运行测试 run: mvn test - name: 构建 Docker 镜像 run: | # 使用 Dockerfile 构建镜像 docker build -t light-delivery-app:latest . - name: 验证镜像构建 run: | echo "构建的 Docker 镜像:" docker images | grep light-delivery-app echo "镜像详情:" docker inspect light-delivery-app:latest --format='Size: {{.Size}} bytes, Created: {{.Created}}' - name: 停止旧容器 run: | # 优雅停止旧容器 docker stop light-delivery-container 2>/dev/null || echo "没有运行中的容器" docker rm light-delivery-container 2>/dev/null || echo "没有可删除的容器" - name: 备份当前镜像(可选) run: | # 为当前运行中的镜像创建备份标签 if docker images light-delivery-app:latest --quiet | grep -q .; then BACKUP_TAG="backup-$(date +%Y%m%d-%H%M%S)" docker tag light-delivery-app:latest light-delivery-app:$BACKUP_TAG echo "已创建备份: light-delivery-app:$BACKUP_TAG" fi - name: 运行新容器 run: | # 创建必要的目录 sudo mkdir -p /app/logs sudo mkdir -p /etc/ssl/certs sudo chown $USER:$USER /app/logs 2>/dev/null || true echo "使用统一的部署配置启动新容器..." docker compose -f deploy.yml up -d - name: 等待应用启动并健康检查 run: | echo "等待应用启动..." # 最大重试次数 MAX_RETRIES=12 RETRY_COUNT=0 while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do # 使用正确的端口 (8443) 和协议 (HTTPS),不跳过SSL验证 if curl -f -s https://localhost:8443/actuator/health > /dev/null 2>&1; then echo "✅ 应用健康检查通过" # 获取详细的健康信息 HEALTH_INFO=$(curl -s https://localhost:8443/actuator/health) echo "健康状态: $HEALTH_INFO" break fi RETRY_COUNT=$((RETRY_COUNT + 1)) echo "健康检查失败 ($RETRY_COUNT/$MAX_RETRIES),10秒后重试..." sleep 10 done if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then echo "❌ 应用启动超时,查看日志:" docker logs light-delivery-container --tail 50 exit 1 fi - name: 清理资源 run: | # 清理旧的备份镜像(保留最近5个) echo "清理旧的备份镜像..." docker images light-delivery-app --filter "reference=light-delivery-app:backup-*" \ --format "{{.Tag}}\t{{.CreatedAt}}" | \ sort -k2 -r | \ tail -n +6 | \ awk '{print $1}' | \ xargs -r -I {} docker rmi light-delivery-app:{} || echo "无需清理" # 清理无用镜像和容器 docker system prune -f - name: 部署完成通知 run: | echo "🎉 部署完成!" echo "应用运行在: http://localhost:8080" echo "容器状态: $(docker inspect light-delivery-container --format='{{.State.Status}}')" echo "启动时间: $(docker inspect light-delivery-container --format='{{.State.StartedAt}}')"