# BuildFlow CICD 设计文档 - **日期**:2026-06-27 - **状态**:待主公审阅 - **范围**:将 `buildflow` 门户网站接入现有 Jenkins + 私有 Registry 的 CICD 体系,并初始化为独立 Gitea 仓库 --- ## 1. 背景与目标 ### 1.1 背景 `buildflow` 是 BuildFlow 低代码平台的门户网站(React 18 + Vite 6 + Tailwind + Nginx 静态托管),项目骨架已搭好,具备: - 完整源码与 4 个页面(首页 / 功能 / 组件库 / 定价) - 多阶段 `Dockerfile`(Node 构建 + Nginx 运行) - `docker-compose.yml`、`nginx.conf`、`.gitignore` 同 workspace 的 `rag-frontend` 已有成熟的 Jenkins CICD 流水线,复用同一套基建(私有 Registry、部署目录、Jenkins agent)。 ### 1.2 目标 1. 把 `buildflow` 初始化为独立 git 仓库并推送到 Gitea(`192.168.1.154`)。 2. 为 `buildflow` 配置 Jenkins 流水线:提交代码即自动构建镜像 → 推送 Registry → 部署到 `192.168.1.154`。 3. 在 rag-frontend 模式基础上做**轻量增强**:加入质量门禁(lint + 类型检查)与部署后健康检查。 ### 1.3 非目标(YAGNI) - 不做单元测试、镜像漏洞扫描、蓝绿/回滚、构建缓存优化(留待后续按需迭代)。 - 不改造其他仓库的 CICD。 --- ## 2. 现状分析(已勘验) ### 2.1 buildflow 现状 | 项 | 现状 | 备注 | |---|---|---| | 构建 | `pnpm build` = `tsc -b && vite build`,产物 `dist/` | 质量门禁可用 `pnpm lint` + `pnpm check` | | Dockerfile | 多阶段:`node:20-alpine` 构建 → `nginx:1.27-alpine` 运行 | 仅 `pnpm build`,无 lint/check | | nginx.conf | `listen 80` | **需改为 5173** | | docker-compose.yml | bridge 网络,`ports: 80:80` | 需改端口与网络策略 | | 端口占用 | 占宿主 80 | 与 rag-frontend(host 模式占 80)冲突 | ### 2.2 现有 CICD 基建(取自 `rag-frontend/Jenkinsfile`) - **私有 Registry**:`192.168.1.154:31010` - **Registry 账号**:`docker` / `dockerxn001624.`(与 rag-frontend 一致) - **镜像命名**:`docker/`,双 tag:`$BUILD_NUMBER` + `latest` - **部署目录**:`/home/xiangning/deploy/` - **部署方式**:Jenkins agent 在 `192.168.1.154` 本机执行 `docker compose`,生成 `network_mode: host` 的 compose 文件,`pull → down → up` - **流水线阶段**:Checkout → Build → Push → Deploy(无质量门禁、无健康检查) --- ## 3. 关键设计决策 ### 3.1 端口与网络策略(核心关隘) **问题**:主公要求部署到 154、端口 5173,并沿用 rag-frontend 的 `network_mode: host`。host 模式下容器端口即宿主端口;若镜像内 Nginx 仍 `listen 80`,则与 rag-frontend 争夺宿主 80 端口。 **决策**:让镜像内 Nginx **监听 5173**,host 模式下 5173 直接暴露在宿主,互不冲突。 | 环境 | 网络模式 | 端口 | 访问 | |---|---|---|---| | 本地 `docker compose up` | bridge | `5173:5173` | `http://localhost:5173` | | 生产(Jenkins 部署) | host | Nginx 监听 5173 | `http://192.168.1.154:5173` | > 镜像统一 `listen 5173`;本地用 bridge 映射规避 macOS host 网络限制,生产用 host 与 rag-frontend 体系一致。 ### 3.2 质量门禁的落点 **问题**:rag-frontend 流水线无质量检查。若在 Jenkins 增加 `pnpm lint` stage,需 Jenkins agent 预装 Node + pnpm。 **决策**:将质量门禁**内嵌进 Dockerfile 的 builder 阶段**(`pnpm lint && pnpm check && pnpm build`),随 `docker build` 自动执行,失败即构建失败。 **收益**: - 不依赖 Jenkins agent 的 Node 环境 - Jenkins 结构保持与 rag-frontend 一致(改动最小) - 质量门禁与构建产物同源,本地 `docker build` 也强制过门禁 ### 3.3 部署后健康检查 在 Deploy 之后增加一个轻量 HealthCheck stage,`wget --spider http://127.0.0.1:5173`,确认服务起来;失败则流水线标红。 --- ## 4. 文件改动清单 | 文件 | 动作 | 改动要点 | |---|---|---| | `buildflow/Jenkinsfile` | 新建 | 见 §5 | | `buildflow/Dockerfile` | 改 | builder 阶段插入 `pnpm lint && pnpm check`(见 §6.1) | | `buildflow/nginx.conf` | 改 | `listen 80` → `listen 5173`(见 §6.2) | | `buildflow/docker-compose.yml` | 改 | bridge `5173:5173`,注释说明生产用 host(见 §6.3) | | `buildflow/README.md` | 改 | 部署端口 80 → 5173,补 CICD 段落 | | `buildflow/.gitignore` | 不动 | 已忽略 `node_modules`/`dist`,足够 | --- ## 5. Jenkinsfile 设计 结构与 rag-frontend 对齐,仅新增 HealthCheck stage,质量门禁由 Dockerfile 承担。 ```groovy pipeline { agent any environment { CI_REGISTRY = '192.168.1.154:31010' DOCKER_IMAGE = 'docker/buildflow-web' DOCKER_TAG = "${BUILD_NUMBER}" DEPLOY_DIR = '/home/xiangning/deploy/buildflow' APP_PORT = '5173' } stages { stage('Checkout') { steps { checkout scm sh 'git log --oneline -5' } } stage('Build') { // docker build 内部执行 pnpm install → lint → check → build // 任一步失败则本 stage 失败(质量门禁) steps { sh """ docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} . docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${DOCKER_IMAGE}:latest """ } } stage('Push') { steps { sh """ echo 'dockerxn001624.' | docker login -u docker --password-stdin ${CI_REGISTRY} docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${CI_REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG} docker tag ${DOCKER_IMAGE}:latest ${CI_REGISTRY}/${DOCKER_IMAGE}:latest docker push ${CI_REGISTRY}/${DOCKER_IMAGE}:${DOCKER_TAG} docker push ${CI_REGISTRY}/${DOCKER_IMAGE}:latest """ } } stage('Deploy') { steps { sh """ mkdir -p ${DEPLOY_DIR} cd ${DEPLOY_DIR} cat > docker-compose.yml << 'DCOF' services: buildflow-web: image: ${CI_REGISTRY}/${DOCKER_IMAGE}:latest container_name: buildflow-web network_mode: host restart: unless-stopped DCOF docker compose pull docker compose down --remove-orphans || true docker compose up -d docker image prune -f docker compose ps """ } } stage('HealthCheck') { steps { // 等待 Nginx 起来后探测本机 5173 sh """ sleep 3 wget -q --spider http://127.0.0.1:${APP_PORT}/ || exit 1 echo "=== HealthCheck OK: http://192.168.1.154:${APP_PORT} ===" """ } } } post { success { echo '=== BuildFlow CI/CD SUCCESS ===' } failure { echo '=== BuildFlow CI/CD FAILED ===' } always { deleteDir() } } } ``` --- ## 6. 其他文件改动细节 ### 6.1 Dockerfile(builder 阶段加质量门禁) ```dockerfile # 现状:RUN pnpm build # 改为: RUN pnpm lint && pnpm check && pnpm build ``` > `pnpm check` = `tsc -b --noEmit`,`pnpm lint` = `eslint .`。两者皆过方进入 `vite build`。 ### 6.2 nginx.conf ```diff - listen 80; - listen [::]:80; + listen 5173; + listen [::]:5173; ``` Dockerfile 的 `EXPOSE 80` 同步改为 `EXPOSE 5173`;`HEALTHCHECK` 探测 `http://127.0.0.1:5173/`。 ### 6.3 docker-compose.yml(本地) ```yaml services: buildflow-web: build: { context: ., dockerfile: Dockerfile } image: buildflow-web:latest container_name: buildflow-web restart: unless-stopped ports: - "5173:5173" # 本地 bridge;生产由 Jenkins 生成 host network compose healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:5173/"] interval: 30s timeout: 3s retries: 3 start_period: 5s networks: [buildflow-net] networks: buildflow-net: { driver: bridge } ``` --- ## 7. Gitea 仓库初始化与推送 由末将代为执行: ```bash cd buildflow git init git add . git commit -m "chore: init buildflow repo with CICD" git branch -M main git remote add origin http://@://buildflow.git git push -u origin main ``` **待主公提供(实现前)**: | 项 | 说明 | 默认值 | |---|---|---| | Gitea 端口 | 主公给 3000,但 Grafana 亦占 3000,须核实 | 待确认 | | owner | 用户名或组织名 | 待确认 | | 仓库名 | | 默认 `buildflow` | | access token | 推送凭证 | 待提供 | > 安全:token 仅用于本次 `git push` 的 URL,末将提醒主公**事后清理 shell history**,并建议使用 Gitea 的限定范围 token(仅 `repo` 写权限)。 --- ## 8. 部署参数总览 | 项 | 值 | |---|---| | Registry | `192.168.1.154:31010` | | 镜像 | `docker/buildflow-web`(tag: `$BUILD_NUMBER` + `latest`) | | 部署目录 | `/home/xiangning/deploy/buildflow` | | 生产网络 | `network_mode: host` | | 访问地址 | `http://192.168.1.154:5173` | --- ## 9. 风险与待确认项 1. **Gitea 端口冲突**:`192.168.1.154:3000` 既标为 Gitea,又是 Grafana(`docker-compose.infra.yml`)端口。需主公确认 Gitea 真实端口,否则推送地址错误。 2. **5173 占用**:需确认 154 上 5173 空闲(Vite dev 默认端口,生产服务器一般空闲)。 3. **Jenkins agent 假设**:沿用 rag-frontend 的"agent 在 154 本机执行 docker compose"假设,需确认 buildflow 使用的 agent 节点一致。 4. **lint 严格度**:buildflow 现为默认 eslint 配置,质量门禁应可通过;若规则触发误报,可调整规则或暂将 `pnpm lint` 降级为告警。 5. **本地 macOS host 网络**:本地 `docker compose` 采用 bridge 规避,生产用 host,两者端口访问一致。 --- ## 10. 验收标准 - [ ] `buildflow` 已 git 初始化并成功推送到 Gitea。 - [ ] Gitea Webhook/轮询触发 Jenkins 构建(或手动触发)。 - [ ] `docker build` 内 lint + typecheck + build 全通过。 - [ ] 镜像成功推送至 `192.168.1.154:31010/docker/buildflow-web`。 - [ ] `192.168.1.154` 上容器以 host 模式运行,`http://192.168.1.154:5173` 可访问且返回门户首页。 - [ ] HealthCheck stage 通过。 --- ## 11. 后续可选迭代(非本期) - Jenkinsfile 参数化(环境、版本号)。 - 失败通知(钉钉/企业微信 webhook)。 - 构建缓存优化(pnpm store 缓存层)。 - 单元测试与镜像扫描。