version: 8 # OneDev Build Spec Version jobs: # --- 后端 Spring Boot 应用作业 --- - name: "Backend CI/CD" executor: "docker-executor" triggers: - type: "branch-push" branches: "main" paths: "springboot-init-main/**" steps: - checkout - group: "Build Backend JAR" steps: - image: "maven:3.8-openjdk-8" shell: "sh" commands: | echo "Building Spring Boot JAR..." cd springboot-init-main mvn clean package -DskipTests -B - group: "Publish Backend Docker Image" steps: - shell: "sh" commands: | echo "Logging in to Docker Registry..." echo $env.get(\'DOCKER_PASSWORD\') | docker login -u $env.get(\'DOCKER_USER\') --password-stdin $env.get(\'DOCKER_REGISTRY\', \'docker.io\') echo "Building and Pushing Backend Docker Image..." cd springboot-init-main IMAGE_NAME="${env.get(\'DOCKER_REGISTRY\', \'docker.io\')}/your-docker-repo/mqtt-springboot-app" docker build -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8) . docker push ${IMAGE_NAME}:latest docker push ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8) echo "Logging out from Docker Registry..." docker logout $env.get(\'DOCKER_REGISTRY\', \'docker.io\') # --- 前端 Next.js 应用作业 --- - name: "Frontend CI/CD" executor: "docker-executor" triggers: - type: "branch-push" branches: "main" paths: "charging_web_app/**" steps: - checkout - group: "Build Frontend App" steps: - image: "node:18-alpine" shell: "sh" commands: | echo "Building Next.js App..." cd charging_web_app npm ci npm run build - group: "Publish Frontend Docker Image" steps: - shell: "sh" commands: | echo "Logging in to Docker Registry..." echo $env.get(\'DOCKER_PASSWORD\') | docker login -u $env.get(\'DOCKER_USER\') --password-stdin $env.get(\'DOCKER_REGISTRY\', \'docker.io\') echo "Building and Pushing Frontend Docker Image..." cd charging_web_app IMAGE_NAME="${env.get(\'DOCKER_REGISTRY\', \'docker.io\')}/your-docker-repo/mqtt-nextjs-app" docker build -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8) . docker push ${IMAGE_NAME}:latest docker push ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8) echo "Logging out from Docker Registry..." docker logout $env.get(\'DOCKER_REGISTRY\', \'docker.io\') # --- 统一应用部署作业 --- # 这个作业会在任一应用(后端或前端)成功构建并推送镜像后触发 # 或者也可以配置为仅在特定条件下手动触发,或依赖于两个镜像都构建完成 - name: "Deploy All Services" executor: "docker-executor" # 或一个配置了 SSH client 的 Shell executor # 触发器:这里用了一个手动触发的例子,或者可以依赖于前两个job的完成 # triggers: # - type: "manual" # 或者更复杂的依赖触发,例如当 backend 和 frontend 的镜像都推送到特定tag后 # 此处简化,假设在 backend 和 frontend CI/CD job 成功后可以手动触发或自动链式触发 (OneDev支持Job依赖) # 如果希望在每次后端或前端更新后都自动部署,可以将此部署逻辑合并到各自的CI/CD作业末尾, # 但要注意并发部署可能导致的问题,以及只更新变化部分的需求。 # 为简单起见,这里假设这是一个独立的部署步骤,手动或通过上游作业触发。 # 如果要自动触发,可以设置 dependsOn: ["Backend CI/CD", "Frontend CI/CD"] 并调整触发逻辑 steps: - checkout # 获取最新的 docker-compose.yml (如果它在仓库中) - group: "Deploy Services to Server" steps: - shell: "sh" # Secrets needed: SERVER_SSH_KEY, SERVER_HOST, SERVER_SSH_USER, DEPLOY_PATH # Secrets for .env file: MYSQL_ROOT_PASSWORD_SECRET, MYSQL_DATABASE_SECRET, MYSQL_USER_SECRET, MYSQL_PASSWORD_SECRET commands: | echo "Preparing deployment to Server..." echo "Creating .env file for docker-compose..." # 从 OneDev Job Secrets 生成 .env 文件内容 # 注意:这里的 $env.get 语法和可用性取决于 OneDev Executor 环境 # 确保 OneDev Secrets 名称与此处使用的 get() 中的名称一致 # 确保 shell 对多行字符串和特殊字符的处理是正确的 ENV_CONTENT="" ENV_CONTENT="${ENV_CONTENT}MYSQL_ROOT_PASSWORD=\"${env.get('MYSQL_ROOT_PASSWORD_SECRET')}\"\n" ENV_CONTENT="${ENV_CONTENT}MYSQL_DATABASE=\"${env.get('MYSQL_DATABASE_SECRET')}\"\n" ENV_CONTENT="${ENV_CONTENT}MYSQL_USER=\"${env.get('MYSQL_USER_SECRET')}\"\n" ENV_CONTENT="${ENV_CONTENT}MYSQL_PASSWORD=\"${env.get('MYSQL_PASSWORD_SECRET')}\"\n" # 添加其他 docker-compose.yml 中需要的环境变量,例如 EMQX 相关的 (如果需要密码) # ENV_CONTENT="${ENV_CONTENT}EMQX_ADMIN_PASSWORD=\"${env.get('EMQX_ADMIN_PASSWORD_SECRET')}\"\n" echo "Connecting to server and deploying..." # 将 SSH 私钥写入临时文件 mkdir -p ~/.ssh echo "$env.get(\'SERVER_SSH_KEY\')" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa # 1. 将生成的 .env 文件内容发送到服务器的部署目录 # 2. 将仓库中的 docker-compose.yml (如果已检出) 发送到服务器或确保服务器上有最新版本 # 3. 执行 docker-compose 命令 # 注意: scp 和 ssh 命令中的路径和用户需要正确配置 # DEPLOY_PATH 是服务器上的 /opt/deploy/mqtt-charging-system # @workspace@ 是 OneDev executor 中的工作目录,包含了检出的代码 # 创建一个包含 .env 内容的临时文件以便 scp echo -e "${ENV_CONTENT}" > env_for_server.env # 复制 .env 文件和 docker-compose.yml 到服务器 # 假设 docker-compose.yml 在仓库根目录 scp -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa env_for_server.env $env.get(\'SERVER_SSH_USER\')@$env.get(\'SERVER_HOST\'):$env.get(\'DEPLOY_PATH\')/.env scp -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa @workspace@/docker-compose.yml $env.get(\'SERVER_SSH_USER\')@$env.get(\'SERVER_HOST\'):$env.get(\'DEPLOY_PATH\')/docker-compose.yml # 在服务器上执行 docker-compose 命令 ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa $env.get(\'SERVER_SSH_USER\')@$env.get(\'SERVER_HOST\') \ "cd $env.get(\'DEPLOY_PATH\') && docker-compose down --remove-orphans && docker-compose pull && docker-compose up -d" echo "Deployment process initiated on server." # 清理 executor 中的临时 .env 文件 rm env_for_server.env