build-flow.portal/docs/superpowers/specs/2026-06-27-buildflow-cicd-design.md

11 KiB
Raw Blame History

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/<name>,双 tag:$BUILD_NUMBER + latest
  • 部署目录:/home/xiangning/deploy/<name>
  • 部署方式: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 承担。

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 阶段加质量门禁)

# 现状:RUN pnpm build
# 改为:
RUN pnpm lint && pnpm check && pnpm build

pnpm check = tsc -b --noEmit,pnpm lint = eslint .。两者皆过方进入 vite build。

6.2 nginx.conf

- 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(本地)

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 仓库初始化与推送

由末将代为执行:

cd buildflow
git init
git add .
git commit -m "chore: init buildflow repo with CICD"
git branch -M main
git remote add origin http://<token>@<gitea-host>:<port>/<owner>/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 缓存层)。
  • 单元测试与镜像扫描。