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

307 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 承担。
```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://<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 缓存层)。
- 单元测试与镜像扫描。