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: 从本地文件安装 JDK 17 run: | echo "使用本地 JDK 文件..." # 强制使用本地文件,不依赖网络 if [ -f "/opt/jdk-dist/openjdk-17.0.2_linux-x64_bin.tar.gz" ]; then echo "复制本地 JDK 文件..." cp "/opt/jdk-dist/openjdk-17.0.2_linux-x64_bin.tar.gz" jdk.tar.gz else echo "本地 JDK 文件不存在,从网络下载..." wget http://192.168.171.223:8082/openjdk-17.0.2_linux-x64_bin.tar.gz -O jdk.tar.gz fi echo "安装 JDK..." sudo mkdir -p /opt/java sudo tar -xzf jdk.tar.gz -C /opt/java --strip-components=1 # 强制设置环境变量,覆盖任何其他设置 echo "JAVA_HOME=/opt/java" >> $GITHUB_ENV echo "/opt/java/bin" >> $GITHUB_PATH rm -f jdk.tar.gz - name: 安装 Maven run: | echo "安装 Maven..." sudo apt update sudo apt install -y maven echo "Maven 版本:" mvn --version - name: 验证环境 run: | echo "Runner 工作目录: $(pwd)" echo "Java 版本:" java -version echo "Maven 版本:" mvn --version echo "JAVA_HOME: $JAVA_HOME" echo "实际 JAVA_HOME 路径:" ls -la $JAVA_HOME - 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}}')"