refactor(infra): 重构为 no-push 本地构建部署模式
- 删除 6 个分散 workflow(ci-ts/ci-go/ci-proto/ci-py/docker/deploy) - 合并为单个 ci.yml:3 个 quality job 并行 + deploy job 串行 - 全部使用官方镜像(node:22-alpine/golang:1.22-alpine/bufbuild/buf/docker:25-git) - deploy job 用 DooD 模式挂载 /var/run/docker.sock - docker-compose.deploy.yml 改用 build: 替代 image:(no-push) - 新增 docker-compose.tools.yml 一次性预拉所有 CI 镜像 - 支持 workflow_dispatch 指定 commit_sha 回滚 - 更新 project_rules §15 与 cicd-runbook.md 为 no-push 模式 - 新增设计文档 docs/superpowers/specs/2026-07-08-cicd-no-push-local-build-design.md
This commit is contained in:
@@ -455,77 +455,77 @@ services/[service]/src/
|
||||
|
||||
## 15. CI/CD 规范
|
||||
|
||||
> 详细配置见 `.github/workflows/`,本节为强制约束。
|
||||
> 详细配置见 `.github/workflows/ci.yml`,使用手册见 [cicd-runbook](../../docs/standards/cicd-runbook.md),设计文档见 [no-push-local-build-design](../../docs/superpowers/specs/2026-07-08-cicd-no-push-local-build-design.md)。
|
||||
|
||||
### 15.1 流水线阶段(强制)
|
||||
### 15.1 核心模式:no-push 本地构建
|
||||
|
||||
所有 PR 与 main 分支推送必须通过以下阶段:
|
||||
- **不推送镜像到 registry**:构建即部署,镜像只存在于构建机本地
|
||||
- **不依赖自建镜像**:全部使用官方镜像(node:22-alpine / golang:1.22-alpine / bufbuild/buf / docker:25-git)
|
||||
- **DooD 模式**:deploy job 容器挂载 `/var/run/docker.sock`,容器内 docker 命令作用于宿主机
|
||||
- **单文件管理**:一个 `.github/workflows/ci.yml` 管全部 CI/CD
|
||||
|
||||
| 阶段 | 并行 | 内容 | 失败策略 |
|
||||
| ---------------- | ------------ | ------------------------------------------ | -------- |
|
||||
| **lint** | ✅(按语言) | TS ESLint / Go vet / Python ruff | 失败阻断 |
|
||||
| **typecheck** | ✅ | TS `tsc --noEmit` | 失败阻断 |
|
||||
| **test** | ✅(按服务) | Go test / Vitest / pytest | 失败阻断 |
|
||||
| **build** | ✅(按服务) | Go build / nest build / next build | 失败阻断 |
|
||||
| **arch:scan** | ✅ | `pnpm run arch:scan` + 校验 arch.db 一致性 | 失败阻断 |
|
||||
| **docker-build** | ✅(按服务) | 构建镜像(不推送) | 失败阻断 |
|
||||
### 15.2 流水线阶段
|
||||
|
||||
> main 分支额外阶段:`docker-push`(推送镜像)+ `deploy`(部署到服务器)
|
||||
| 阶段 | 并行 | 内容 | 失败策略 |
|
||||
| ----------------- | ---- | ------------------------------------ | -------- |
|
||||
| **quality-ts** | ✅ | pnpm lint + typecheck + test + build | 失败阻断 |
|
||||
| **quality-go** | ✅ | go vet + build + test | 失败阻断 |
|
||||
| **quality-proto** | ✅ | buf lint + buf breaking(仅 PR) | 失败阻断 |
|
||||
| **deploy** | 串行 | docker compose up --build + 健康检查 | 失败阻断 |
|
||||
|
||||
### 15.2 触发条件
|
||||
> deploy job 仅在 `push main` 或 `workflow_dispatch` 时触发,PR 时不部署
|
||||
|
||||
| 事件 | 触发阶段 | 触发条件 |
|
||||
| ------------ | ---------------------------------------------------------- | ---------- |
|
||||
| PR 创建/更新 | lint + typecheck + test + build + arch:scan + docker-build | 所有路径 |
|
||||
| push 到 main | 上述全部 + docker-push + deploy | 合并后自动 |
|
||||
| tag `v*` | docker-push(tag 镜像)+ deploy(生产) | 手动打 tag |
|
||||
### 15.3 触发条件
|
||||
|
||||
### 15.3 镜像规范
|
||||
| 事件 | 触发阶段 | 触发条件 |
|
||||
| ----------------- | ----------------------------------------------- | -------------------------------- |
|
||||
| PR 创建/更新 | quality-ts + quality-go + quality-proto(并行) | 所有路径 |
|
||||
| push 到 main | 上述全部 + deploy | 合并后自动 |
|
||||
| workflow_dispatch | 上述全部 + deploy | 手动触发,支持 `commit_sha` 回滚 |
|
||||
|
||||
- **镜像名**:`edu/<service>:<tag>`
|
||||
- **tag 策略**:
|
||||
- `latest`:main 分支最新
|
||||
- `<git-sha>`:每次构建的 commit SHA(可追溯)
|
||||
- `v<version>`:正式发布 tag
|
||||
- **镜像扫描**:docker-push 后自动运行 Trivy 扫描,CRITICAL 漏洞阻断部署
|
||||
> **不再支持 tag 发布**:no-push 模式下不用 `git tag v*` 触发。版本管理通过 commit SHA 追溯。
|
||||
|
||||
### 15.4 部署策略
|
||||
### 15.4 镜像规范
|
||||
|
||||
- **不推送到 registry**,本地构建本地使用
|
||||
- **不保留历史镜像**:layer cache 在宿主机本地,未变更的层秒过
|
||||
- **回滚**:`git revert` 重跑 CI,或 `workflow_dispatch` 指定 `commit_sha`
|
||||
|
||||
### 15.5 部署策略
|
||||
|
||||
- **目标环境**:服务器 Docker Compose(P1-P2 阶段),K8s(P3+ 阶段)
|
||||
- **部署方式**:SSH 到服务器,`docker compose pull && docker compose up -d`
|
||||
- **健康检查**:部署后轮询 `/healthz` 端点,连续 3 次失败回滚
|
||||
- **回滚**:`docker compose rollback`(上一版本镜像 tag)
|
||||
|
||||
### 15.5 Secrets 管理
|
||||
|
||||
- **CI Secrets**:存于 GitHub Actions secrets / Gitea Actions secrets
|
||||
- **部署服务器**:`.env` 文件由 SRE AI 管理,不进版本库
|
||||
- **JWT_SECRET**:生产环境强随机值,不与开发环境共享
|
||||
- **部署方式**:`docker compose up -d --build --remove-orphans`(在 `/opt/edu/` 目录)
|
||||
- **部署目录**:`/opt/edu/`(compose 文件)+ `/opt/edu/repo/`(CI 同步的源码,供 build.context 使用)
|
||||
- **健康检查**:部署后轮询 `/healthz` 端点(10 次 × 6 秒),失败输出容器日志
|
||||
- **回滚**:`git revert + push` 或 `workflow_dispatch` 指定 `commit_sha`
|
||||
|
||||
### 15.6 必需的 CI 文件
|
||||
|
||||
| 文件 | 用途 |
|
||||
| ------------------------------ | ------------------------------------------- |
|
||||
| `.github/workflows/ci.yml` | 主流水线(lint + typecheck + test + build) |
|
||||
| `.github/workflows/docker.yml` | Docker 镜像构建与推送(main + tag 触发) |
|
||||
| `.github/workflows/deploy.yml` | 部署到服务器(main 触发,需环境审批) |
|
||||
| 文件 | 用途 |
|
||||
| --------------------------------- | ------------------------------------- |
|
||||
| `.github/workflows/ci.yml` | 唯一 CI/CD 流水线(quality + deploy) |
|
||||
| `infra/docker-compose.deploy.yml` | 部署用 compose(build: 替代 image:) |
|
||||
| `infra/docker-compose.tools.yml` | 一次性预拉所有 CI 镜像 |
|
||||
| `infra/deploy.env.example` | 部署环境变量模板 |
|
||||
|
||||
### 15.7 参考实现(强制参照)
|
||||
### 15.7 actrunner 配置
|
||||
|
||||
**所有 CI/CD 配置必须参照 `E:\Desktop\CICD\` 项目(同机 Gitea 仓库),不另行自创。**
|
||||
```toml
|
||||
# /etc/gitea/act_runner/config.yaml
|
||||
container:
|
||||
valid_volumes:
|
||||
- /var/run/docker.sock
|
||||
```
|
||||
|
||||
- **参考项目位置**:`E:\Desktop\CICD\.gitea\workflows\ci.yml`(同机单仓库 CI 实现)
|
||||
- **关键配置点(必须沿用)**:
|
||||
- **Runner 标签**:`ubuntu-latest`(actrunner 已配置;参考项目用 `CDCD`,Edu 改为 `ubuntu-latest`)
|
||||
- **容器化运行**:TS 类 job 必须使用 `container: dockerreg.eazygame.cn/node-with-docker:22`(带 docker 的 node 22 镜像,用于在 job 内执行 `docker build`/`docker run`)
|
||||
- **Go 类 job**:使用 `container: golang:1.22-alpine`(仅 quality 阶段),`docker-build` 阶段切换到 `node-with-docker:22` 镜像 + `setup-go`
|
||||
- **部署方式**:保留 `docker compose`(不照搬参考项目的 `docker run` 单容器方式,因 Edu 是微服务多容器)
|
||||
- **代理配置**:runner 已配置全局代理,CI 内不再设置 npm/docker 代理(参考项目中的 `172.17.0.1:7890` 代理段不要照搬)
|
||||
- **Next.js standalone 构建**:teacher-portal 沿用参考项目的 standalone 模式(`output: 'standalone'` + 复制 public/.next/static)
|
||||
- **网络**:部署用 `edu-shared` 外部网络连接服务器已有 MySQL/Redis(参考项目用 `1panel-network`,Edu 不同)
|
||||
- **改动需同步**:修改任何 workflow 文件前,先比对参考项目同类配置,确保不偏离上述约定
|
||||
### 15.8 镜像预拉(一次性)
|
||||
|
||||
> 当参考项目与本规范冲突时,以本规范为准(Edu 是微服务架构,参考项目是单体 Next.js)。
|
||||
部署前在服务器执行:
|
||||
|
||||
```bash
|
||||
docker compose -f infra/docker-compose.tools.yml pull
|
||||
```
|
||||
|
||||
拉取清单:node:22-alpine、golang:1.22-alpine、bufbuild/buf:latest、docker:25-git、node:20-alpine、alpine:3.20、mysql:8.0(开发测试)、redis:7-alpine(开发测试)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user