refactor(infra): 重构为 no-push 本地构建部署模式
Some checks failed
CI / quality-go (push) Failing after 3s
CI / quality-proto (push) Failing after 2s
CI / quality-ts (push) Failing after 47s
CI / deploy (push) Has been skipped

- 删除 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:
SpecialX
2026-07-08 17:12:57 +08:00
parent a1d7fcfd71
commit 68ddff1065
12 changed files with 613 additions and 812 deletions

View File

@@ -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-pushtag 镜像)+ 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 ComposeP1-P2 阶段K8sP3+ 阶段)
- **部署方式**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` | 部署用 composebuild: 替代 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开发测试
---