This commit is contained in:
2025-05-23 15:12:29 +08:00
parent 236a1cffb8
commit 4c2d2e5b93
2 changed files with 82 additions and 133 deletions

View File

@@ -1,135 +1,68 @@
version: 8 # OneDev Build Spec Version
version: 8
jobs:
# --- 后端 Spring Boot 应用作业 ---
- name: "Backend CI/CD"
executor: "docker-executor"
- name: Build and Deploy mqtt_power on myagent
agentMatcher: name_is("myagent") # 确保 "myagent" 是您 OneDev 中 agent 的确切名称
# 如果 myagent 是通过标签选择的,请使用类似 agentMatcher: has_tag("your-agent-tag") 的形式
steps:
- checkout # OneDev 会自动检出与触发事件相关的代码
- group: "Prepare Environment and Build"
steps:
- shell: "sh" # 或者 powershell -Command取决于您的 agent 环境
# 如果 agent 是 Windows并且您希望使用 PowerShell请将 shell 改为 "powershell"
# 并在下面的 commands 中使用 PowerShell 语法
commands: |
echo "Running on agent: $ONEDEV_AGENT_NAME"
echo "Workspace: $ONEDEV_WORKSPACE"
echo "Generating .env file for Docker Compose..."
# 使用 get_job_secret 函数从 OneDev Job Secrets 获取值
# 确保在 OneDev 项目的 Job Secrets 中定义了这些 secret
echo "MYSQL_ROOT_PASSWORD=${get_job_secret('DB_ROOT_PASSWORD')}" > .env
echo "MYSQL_DATABASE=${get_job_secret('DB_NAME')}" >> .env
echo "MYSQL_USER=${get_job_secret('DB_USER')}" >> .env
echo "MYSQL_PASSWORD=${get_job_secret('DB_PASSWORD')}" >> .env
echo "SPRING_DATASOURCE_URL=jdbc:mysql://mysql-db:3306/${get_job_secret('DB_NAME')}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false" >> .env
echo "SPRING_DATASOURCE_USERNAME=${get_job_secret('DB_USER')}" >> .env
echo "SPRING_DATASOURCE_PASSWORD=${get_job_secret('DB_PASSWORD')}" >> .env
echo "SPRING_MQTT_BROKER_HOST=emqx-broker" >> .env # docker-compose 服务名
echo "SPRING_MQTT_BROKER_PORT=1883" >> .env
echo "SPRING_MQTT_USERNAME=${get_job_secret('MQTT_USER')}" >> .env
echo "SPRING_MQTT_PASSWORD=${get_job_secret('MQTT_PASSWORD')}" >> .env
# 使用 $ONEDEV_BUILD_NUMBER 保证客户端 ID 唯一性
echo "SPRING_MQTT_CLIENT_ID_BACKEND=springboot-mqtt-client-backend-$ONEDEV_BUILD_NUMBER" >> .env
echo "SPRING_MQTT_LOG_CLIENT_ID=springboot-mqtt-log-client-$ONEDEV_BUILD_NUMBER" >> .env
echo ".env file generated."
# cat .env # 可选: 在构建日志中打印 .env 内容以供调试
echo "Ensuring docker-compose.yml is present..."
if [ ! -f docker-compose.yml ]; then
echo "ERROR: docker-compose.yml not found in workspace root ($ONEDEV_WORKSPACE/docker-compose.yml)!"
exit 1
fi
echo "Stopping existing services (if any)..."
docker-compose -f docker-compose.yml down --remove-orphans || echo "No services were running or an error occurred during down, continuing..."
echo "Building Docker images locally for springboot-app and nextjs-app..."
# 确保 docker-compose.yml 中的 build context 指向正确
# 例如: springboot-init-main 和 charging_web_app
docker-compose -f docker-compose.yml build --no-cache springboot-app nextjs-app
echo "Starting all services via Docker Compose..."
docker-compose -f docker-compose.yml up -d
echo "Deployment process finished."
docker-compose -f docker-compose.yml ps # 显示正在运行的服务状态
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
- type: "BRANCH_UPDATE" # 当分支有代码推送时触发
params:
branches: "main,master" # 监听的分支,请根据您的实际主分支名称修改
# paths: # 可选:仅当特定路径下的文件发生变化时才触发
# includes:
# - "springboot-init-main/**"
# - "charging_web_app/**"
# - "docker-compose.yml"
# - ".onedev-buildspec.yml"