Files
Edu/docs/standards/cicd-runbook.md
SpecialX 68ddff1065
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
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
2026-07-08 17:12:57 +08:00

11 KiB
Raw Permalink Blame History

CI/CD 使用手册CI/CD Runbook

版本2.0no-push 本地构建模式) 日期2026-07-08 适用范围Edu 微服务项目Gitea Actions + Runner 本地构建部署) 关联文档:project_rules §15本地启动手册多 AI 协作指南 设计文档:2026-07-08-cicd-no-push-local-build-design.md


1. 架构总览

PR 触发(开发 AI 提 PR          push main 触发(协调 AI 合并)
     │                                    │
     ▼                                    ▼
┌─────────────────────────┐         ┌─────────────────────────┐
│       ci.yml            │         │       ci.yml            │
│  quality-ts (node:22)   │         │  quality-ts (node:22)   │
│  quality-go (golang)    │         │  quality-go (golang)    │
│  quality-proto (buf)    │         │  quality-proto (buf)    │
│  (并行,不部署)         │         │         │                 │
└─────────────────────────┘         │         ▼                 │
                                    │   deploy job             │
                                    │   (docker:25-git)        │
                                    │   挂载 /var/run/docker.sock│
                                    │         │                 │
                                    │         ▼                 │
                                    │   docker compose up      │
                                    │   --build本地构建    │
                                    │         │                 │
                                    │         ▼                 │
                                    │   健康检查轮询            │
                                    └─────────────────────────┘

1.1 核心特点

  • 单文件管理:一个 .github/workflows/ci.yml 管全部 CI/CD
  • no-push 本地构建:不推送到 registry构建即部署
  • 不依赖自建镜像全部使用官方镜像node/golang/buf/docker
  • DooD 模式deploy job 容器内挂载宿主机 /var/run/docker.sock

1.2 组件清单

组件 说明
Gitea git.eazygame.cn,代码托管 + Actions
Gitea Actions CI 运行器,兼容 GitHub Actions 语法
actrunner 跑在服务器上的 runner标签 ubuntu-latest
服务器 MySQL 已有容器,端口 3306
服务器 Redis 已有容器,端口 6379

1.3 流水线文件

文件 触发 作用
.github/workflows/ci.yml PR + push main + workflow_dispatch quality3 job 并行)+ deploy仅 push main
infra/docker-compose.deploy.yml deploy job 调用 多服务编排build: 替代 image:
infra/docker-compose.tools.yml 手动执行 一次性预拉所有 CI 镜像

2. 一次性配置

2.1 启用 Gitea Actions + actrunner

  1. 仓库设置 → Actions → 启用
  2. 安装 actrunner 并注册(标签 ubuntu-latest
  3. 配置 actrunner 允许挂载 docker.sock
# /etc/gitea/act_runner/config.yaml
container:
  valid_volumes:
    - /var/run/docker.sock

2.2 预拉所有 CI 镜像(一次性)

# 在服务器上,进入 Edu 仓库目录
cd /path/to/Edu
docker compose -f infra/docker-compose.tools.yml pull

拉取的镜像清单:

镜像 用途
node:22-alpine CI quality-ts job
golang:1.22-alpine CI quality-go job + api-gateway builder
bufbuild/buf:latest CI quality-proto job
docker:25-git CI deploy job自带 docker CLI + compose v2 + git
node:20-alpine teacher-portal / classes builder
alpine:3.20 api-gateway runner
mysql:8.0 开发测试用(生产用已有的)
redis:7-alpine 开发测试用(生产用已有的)

2.3 准备服务器网络

# 创建共享网络(若不存在)
docker network create edu-shared

# 将已有的 MySQL/Redis 加入网络(容器名按实际替换)
docker network connect edu-shared <实际mysql容器名>
docker network connect edu-shared <实际redis容器名>

2.4 初始化部署目录

# 1. 创建部署目录
sudo mkdir -p /opt/edu
sudo chown -R $USER:$USER /opt/edu

# 2. 创建生产 .env从模板
cp infra/deploy.env.example /opt/edu/.env
vim /opt/edu/.env
# 必须修改:
#   JWT_SECRET=<openssl rand -hex 32 生成的随机值>
#   DATABASE_URL=mysql://<user>:<pass>@<mysql容器名>:3306/<db>
#   REDIS_URL=redis://<redis容器名>:6379

注意:/opt/edu/repo/ 子目录由 CI 自动同步,不需要手动准备。


3. 日常使用

3.1 开发 AI 提 PR

PR 创建 → ci.yml 运行
  ├─ quality-tspnpm lint + typecheck + test + build
  ├─ quality-gogo vet + build + test
  └─ quality-protobuf lint + buf breaking
  3 个 job 并行,仅 quality不部署

CI 全绿 → 协调 AI 审核合并

3.2 协调 AI 合并 PR

PR 合并到 main 后自动触发:

push main → ci.yml
  ├─ quality-* 3 个 job 并行,确保 main 稳定)
  └─ deploy jobneeds: [quality-ts, quality-go, quality-proto]
        │
        ▼
     同步代码到 /opt/edu/repo/
        │
        ▼
     docker compose up -d --build本地构建 3 个服务)
        │
        ▼
     健康检查轮询10 次 × 6 秒)

3.3 手动触发部署

在 Gitea → Actions → CI → Run workflow

  • commit_sha(可选):回滚到指定 commit留空则部署当前 HEAD

3.4 不再支持 tag 发布

no-push 模式下,镜像不存放到 registry因此不再使用 git tag v* 触发发布。版本管理通过 git commit SHA 追溯。


4. 部署验证

4.1 CI 自动验证

deploy job 部署后会自动轮询健康检查:

  • http://localhost:8080/healthz — api-gateway
  • http://localhost:3001/healthz — classes
  • http://localhost:3000/ — teacher-portal

失败时输出容器状态与日志,方便排查。

4.2 手动验证

cd /opt/edu

# 容器状态
docker compose ps

# 健康检查
curl http://localhost:8080/healthz
curl http://localhost:3001/healthz
curl http://localhost:3000/

# 鉴权验证(生产模式 dev-token 应被拒绝)
curl -H "Authorization: Bearer dev-token" http://localhost:8080/api/v1/classes
# 预期401 INVALID_TOKEN

# 查看日志
docker compose logs -f api-gateway
docker compose logs -f classes
docker compose logs -f teacher-portal

5. 回滚

5.1 git revert推荐

git revert <bad-commit>
git push origin main
# CI 自动重新构建部署

5.2 手动触发指定 commit

在 Gitea → Actions → CI → Run workflow

  • commit_sha:填入上一个稳定版本的 commit SHA

CI 会 checkout 指定 commit → 本地重新 build → deploy。

5.3 不再支持镜像 tag 回滚

no-push 模式下没有 registry tag不能像旧方案那样切换 IMAGE_TAG。回滚必须重新构建。


6. 常见问题

6.1 CI: pnpm install 失败

症状pnpm install --frozen-lockfile 报错。

排查

  1. pnpm-lock.yaml 未提交:git add pnpm-lock.yaml && git commit
  2. Node 版本不匹配:确认 CI 用 Node 22本地一致

6.2 CI: deploy job 无法访问 docker

症状docker compose upCannot connect to the Docker daemon

原因actrunner 没有挂载 /var/run/docker.sock,或 valid_volumes 未配置。

修复

# /etc/gitea/act_runner/config.yaml
container:
  valid_volumes:
    - /var/run/docker.sock

重启 actrunner 后重试。

6.3 CD: 健康检查失败

症状deploy job 健康检查 10 次后失败。

排查

  1. CI 输出会自动打印容器状态和日志
  2. 常见原因:
    • DATABASE_URL 连不上 MySQL检查容器名与网络
    • JWT_SECRET 未配置
    • 端口被占用:docker ps 检查冲突
    • /opt/edu/.env 不存在或格式错误

6.4 CD: 连不上 MySQL/Redis

症状classes 容器报 ECONNREFUSED edu-mysql:3306

修复

# 1. 确认 MySQL 容器名
docker ps --format "{{.Names}}" | grep mysql

# 2. 确认 MySQL 在 edu-shared 网络
docker network inspect edu-shared | grep -A5 Containers

# 3. 若不在,加入网络
docker network connect edu-shared <实际mysql容器名>

# 4. 修改 /opt/edu/.env 的 DATABASE_URL
# DATABASE_URL=mysql://edu:changeme@<实际容器名>:3306/next_edu_cloud

6.5 Gitea Actions 未触发

排查

  1. 仓库设置 → Actions → 确认已启用
  2. Runner 在线Gitea → 设置 → Actions → Runners
  3. workflow 文件在 .github/workflows/ 目录
  4. on: 触发条件匹配

7. 排查命令速查

# === 在服务器上 ===

# 查看所有 edu 容器
docker compose -f /opt/edu/docker-compose.yml ps

# 查看实时日志
docker compose -f /opt/edu/docker-compose.yml logs -f

# 重启单个服务
docker compose -f /opt/edu/docker-compose.yml restart api-gateway

# 重新构建并启动(手动触发部署)
cd /opt/edu/repo
git pull
cd /opt/edu
docker compose up -d --build

# 进入容器
docker exec -it edu-api-gateway sh
docker exec -it edu-classes sh

# 查看网络
docker network inspect edu-shared

# 查看本地镜像
docker images | grep -E "node|golang|docker|alpine|buf"

# === 在 Gitea Web UI ===
# 仓库 → Actions → 查看流水线运行记录
# 仓库 → 设置 → Actions → Runners → 查看 Runner 状态

8. 安全注意事项

  1. .env 文件不入库.gitignore 已忽略,仅存在于服务器 /opt/edu/.env
  2. JWT_SECRET 强随机:生产必须用 openssl rand -hex 32 生成
  3. DEV_MODE=falsedocker-compose.deploy.yml 强制设为 false
  4. docker.sock 安全actrunner 仅在部署服务器运行,已隔离
  5. Runner 隔离runner 跑在服务器上,不暴露公网 SSH

9. 相关文档