ci/cd
This commit is contained in:
@@ -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"
|
||||
Reference in New Issue
Block a user