[CI/CD]小型技术团队开发规范与最小化 DevOps CI/CD 研发流程实施指南
绝大部分公司开发团队配置一般为小型技术开发团队(5-15人)设计,旨在提供一套轻量、高效、可落地的开发规范与 CI/CD 实施方案。方案以 Gitea 为核心代码托管与 CI/CD 引擎,避免引入重型工具(如 Jenkins/GitLab),实现最小化 DevOps 闭环,供灵活参考。
第一部分:开发与分支管理规范
1. 分支模型设计 (简化版 GitFlow)
针对小型团队,摒弃繁琐的分支模型,采用以交付为导向的简化分支策略:
- **
main(或prod)**:生产环境分支。始终保持可发布状态,仅接受来自test的合并。打 Tag 管理版本(如v1.2.0)。 - **
test**:测试环境分支。接受来自dev的合并,部署至测试环境供 QA 验证。 - **
dev**:开发环境主分支。所有特性分支的汇聚地,部署至开发环境进行联调。 - **
feature/***:特性分支。从dev切出,开发完成后合并回dev。(如feature/user-login) - **
hotfix/*:热修复分支。从main切出,修复线上紧急 Bug,修复后必须同时合并回main和dev**。
2. 分支合并与 Deadline 流程
为防止分支长期不合并导致“合并地狱”,制定严格的合并 Deadline 规范。
graph TD
subgraph 需求与开发阶段
A[需求评审完成] --> B[从 dev 创建 feature 分支]
B --> C{开发进行中}
C -->|每日提交| D[保持与 dev 分支同步 rebase]
end
subgraph 合并与 Deadline 控制
D --> E["开发完成, 发起
PR/MR 到 dev"]
E --> F{Code Review & 自动化检查}
F -->|不通过| C
F -->|通过| G[合并入 dev]
G --> H{"Dev 环境联调 Deadline:
1天或一个发布周期内,切记不能堆积"}
H -->|超时未通过| I[打回重构, 记录延期原因]
H -->|按时通过| J[发起 PR/MR 到 test]
J --> K{"QA 测试 Deadline:
3天或一个发布周期内,切记不能堆积"}
K -->|发现 Bug| L[在 feature 分支修复, 重新走合并流程]
K -->|测试通过| M[合并入 test]
M --> N{"UAT/预发验证 Deadline:
1天或一个发布周期内,切记不能堆积"}
N -->|通过| O[发起 PR/MR 到 main]
N -->|不通过| L
end
subgraph 发布阶段
O --> P[合并入 main, 打 Tag]
P --> Q[触发 Prod 环境自动化部署]
end
style H fill:#ffcccc,stroke:#ff0000
style K fill:#ffcccc,stroke:#ff0000
style N fill:#ffcccc,stroke:#ff00003. 配置文件与敏感信息管理
- 代码与配置分离:严禁将数据库密码、API Key、第三方 Secret 等硬编码在代码中。
- 环境变量:Go 项目推荐使用
godotenv或viper读取环境变量。 - 配置模板:仓库中必须提供
.env.example或config.yaml.example,包含所有配置项的 Key 和默认值/注释,但不包含真实敏感值。 - 环境差异化:不同环境(dev/test/prod)的配置通过 CI/CD 注入,或在目标服务器上维护独立的
.env文件。
4. 核心注意事项
- Commit 规范:遵循 Conventional Commits(如
feat: 增加用户登录,fix: 修复空指针),便于自动生成 Changelog。 - 冲突解决:合并前,开发者必须在本地将
dev分支 rebase 或 merge 到自己的feature分支,解决冲突后再推送到远端发起 PR。 - 禁止强推:
dev、test、main分支在 Gitea 中必须开启分支保护,禁止git push -f,必须通过 Pull Request 合并。
第二部分:最小化 DevOps CI/CD 实施规范
基于 Gitea + Gitea Actions(兼容 GitHub Actions 语法),我们无需额外搭建 Jenkins,即可实现最小化 CI/CD。以下针对三种不同底层技术栈的场景提供实施规范。
场景一:GIT + Gitea + Bash (极简物理机/虚拟机部署)
- 适用场景:项目初期,服务器资源有限,无需容器化,直接运行二进制文件。
- CI 流程:Gitea Actions 负责代码检查、单元测试、交叉编译生成 Linux 二进制包。
- CD 流程:通过 SSH 将二进制包和配置文件传输到目标服务器,执行 Bash 脚本重启
systemd服务。
场景二:GIT + Gitea + Docker/Containerd (容器化单机/集群部署)
- 适用场景:需要环境一致性,便于迁移,使用 Docker 或 Containerd 作为运行时。
- CI 流程:Gitea Actions 构建 Docker 镜像,推送到 Gitea 内置的 Package Registry(或阿里云/腾讯云镜像仓库)。
- CD 流程:目标服务器通过 SSH 执行脚本,拉取最新镜像,停止旧容器,启动新容器(推荐使用
docker-compose管理)。
场景三:GIT + Gitea + Containerd + K8S (云原生 Kubernetes 部署)
- 适用场景:中后期,需要高可用、弹性伸缩、滚动更新。
- CI 流程:同场景二,构建镜像并推送到 Registry。
- CD 流程:CI 更新 K8S 部署清单(Deployment YAML 中的镜像 Tag),或使用
kubectl set image命令,触发 K8S 的滚动更新机制。
第三部分:Go Web 应用完整发布部署实战
假设我们有一个基于 Gin 框架的 Go Web 应用 go-web-app,监听 8080 端口。
环境 IP 规划 (192.168.100.x 网段)
- Gitea 服务器:
192.168.100.10(包含 Gitea 及 Gitea Actions Runner) - Dev/Test 服务器:
192.168.100.20(场景一、二使用) - Prod 物理机:
192.168.100.30(场景一、二使用) - K8S 集群:Master
192.168.100.40,Worker192.168.100.41(场景三使用)
基础项目准备
1. 极简 Go 代码 (main.go)
1 | package main |
2. 配置文件模板 (.env.example)
1 | APP_PORT=8080 |
场景一实施:Bash 极简部署
1. 目标服务器准备 (192.168.100.20 和 192.168.100.30)
配置 systemd 服务 /etc/systemd/system/go-web-app.service:
1 | [Unit] |
2. Gitea CI/CD 配置 (.gitea/workflows/deploy-bash.yml)
1 | name: Build and Deploy via Bash |
场景二实施:Docker/Containerd 容器化部署
1. 编写 Dockerfile
1 | FROM golang:1.21-alpine AS builder |
2. 目标服务器准备 (192.168.100.20)
编写 docker-compose.yml:
1 | version: '3' |
3. Gitea CI/CD 配置 (.gitea/workflows/deploy-docker.yml)
1 | name: Build and Deploy Docker |
场景三实施:Containerd + K8S 云原生部署
1. 编写 K8S 部署清单 (k8s/deployment.yaml)
1 | apiVersion: apps/v1 |
2. K8S 节点准备 (192.168.100.40 Master)
配置 Containerd 允许拉取 Gitea 的 HTTP insecure 镜像:
修改 /etc/containerd/config.toml,添加:
1 | [plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.100.10:3000"] |
重启 containerd:systemctl restart containerd。
3. Gitea CI/CD 配置 (.gitea/workflows/deploy-k8s.yml)
1 | name: Build and Deploy to K8S |
第四部分:分支间配置 Config 文件管理、版本控制与注意事项深度指南
本部分作为整个开发规范与 CI/CD 实施指南的延续,聚焦于多分支、多环境下配置文件的全生命周期管理。为确保文档编号的全局连贯性,本节子序号自第一部分(1-4)之后顺延。
5. 核心原则与配置文件分层模型
在展开具体方案之前,必须确立三条不可逾越的铁律:
| 编号 | 铁律 | 说明 |
|---|---|---|
| R1 | 代码中零敏感信息 | 密码、Token、密钥、证书等绝对禁止提交到任何分支 |
| R2 | 配置模板随代码走,真实值随环境走 | 仓库中只保留 .env.example / config.yaml.example,真实配置文件由 CI/CD 注入或从配置中心拉取 |
| R3 | 配置变更必须可追溯 | 配置文件的每一次修改都必须有 commit 记录或审计日志 |
针对 dev → test → main(prod) 的分支流转,配置文件应严格分为 三层:
1 | ┌─────────────────────────────────────────────────────────┐ |
配置加载优先级(Go 项目推荐 Viper 实现):环境变量 > Layer 3 (环境级) > Layer 2 (环境差异化) > Layer 1 (默认值)
6. Git 仓库目录结构与版本控制规范
标准目录树:
1 | go-web-app/ |
.gitignore 必须包含的条目:
1 | # 真实配置文件 - 绝对禁止提交 |
7. 敏感信息管理方案(Layer 3 落地)
对于小型团队,推荐直接使用 Gitea Secrets 进行统一管理,避免引入重型 Vault 组件。
在 Gitea 仓库的 Settings → Actions → Secrets 中配置:
| Secret 名称 | 示例值 | 用途 |
|---|---|---|
DB_PASSWORD_DEV | dev_pass_123 | 开发环境数据库密码 |
DB_PASSWORD_PROD | prod_pass_789 | 生产环境数据库密码 |
JWT_SECRET | jwt_super_secret | JWT 签名密钥 |
SSH_PRIVATE_KEY | -----BEGIN... | 部署用 SSH 私钥 |
.env.example 模板规范:
1 | # ============================================ |
8. 分支合并中配置文件的冲突处理
冲突高发区:多个开发者同时修改 config/dev.yaml 导致合并冲突。
预防措施:
- 按模块分区:在 YAML 中按功能模块(如
auth:、payment:)分区,减少同一行冲突概率。 - 独立配置文件:大型模块拆分为
config/dev/auth.yaml、config/dev/payment.yaml。 - 合并前强制同步:发起 PR 前,必须在本地执行
git rebase origin/dev解决冲突。
冲突解决 SOP:
- 定位
<<<<<<<标记,判断是“不同模块冲突(两者都保留)”还是“同一配置项冲突(需沟通确认)”。 - 解决冲突后,必须在本地启动应用验证,确保配置格式正确且无缺失项。
- 提交并推送。
9. 配置文件版本管理与变更原子性
配置版本号机制:
在 config/default.yaml 中维护版本号,应用启动时校验,防止代码与配置不匹配:
1 | # config/default.yaml |
1 | // Go 代码启动时检查 |
变更原子性原则:
新增配置项的代码和配置模板必须在同一个 PR 中提交。 严禁“先合代码,三天后再补配置”的做法,这会导致中间状态的应用启动直接 panic。
配置回滚与备份:
每次 Bash/Docker 部署前,CI 脚本应自动备份当前配置文件:
1 | cp /opt/go-web-app/.env /opt/go-web-app/.env.bak.$(date +%Y%m%d%H%M%S) |
10. 三种部署场景下的配置注入流程
| 场景 | Layer 1/2 注入方式 | Layer 3 (敏感值) 注入方式 |
|---|---|---|
| Bash | SCP 传输 config/*.yaml 到服务器 | CI 读取 Gitea Secrets,通过 sed 替换 .env 占位符后 SCP 传输 |
| Docker | 打包进镜像(或挂载宿主机 config 目录) | docker-compose.yml 通过 environment 或 env_file 从宿主机 .env 注入 |
| K8S | 通过 ConfigMap 挂载到 Pod 内部 | 通过 Secret 注入为环境变量,或使用 External Secrets Operator |
11. 配置漂移检测与治理机制
配置漂移:代码仓库中的配置与生产服务器实际运行的配置不一致(如运维手动改了服务器配置但未提交 Git)。
检测手段:
在目标服务器(如 192.168.100.30)配置 Cron 定时巡检脚本:
1 |
|
12. 完整注意事项清单 (Checklist)
开发阶段
- 新增功能需要新配置项时,同步更新
default.yaml、环境文件、.env.example - 敏感配置只写占位符
<your_xxx_here> .gitignore已包含所有真实配置文件模式
合并阶段
- 发起 PR 前,已在本地 rebase 目标分支并解决配置冲突
- Code Review 时重点检查配置文件中是否误提交了敏感信息
部署阶段
- CI 从 Gitea Secrets 注入敏感值,而非硬编码在 workflow 文件中
- 部署前已备份目标服务器上的当前配置文件
- 部署后验证应用启动日志中的配置加载信息是否正确
运维阶段
- 手动修改服务器配置后,必须同步提交 PR 到 Git 仓库
- 配置漂移巡检脚本正常运行
- 定期轮换 Secrets,轮换后更新 Gitea Secrets 并重新部署
结语
本规范通过 Gitea + Gitea Actions 构建了最小化 DevOps 闭环,避免了小型团队陷入工具链维护的泥潭。
- 初期:使用 Bash 场景,快速验证业务,成本最低。
- 中期:平滑过渡到 Docker 场景,解决环境一致性问题,利用 Gitea Package Registry 管理镜像。
- 后期:演进至 K8S 场景,实现高可用与弹性伸缩。
团队应严格遵守分支 Deadline 与合并规范,确保代码流转的高效与安全。配置与代码分离是贯穿始终的红线,务必通过 Secrets 和环境变量进行安全管理。
[CI/CD]小型技术团队开发规范与最小化 DevOps CI/CD 研发流程实施指南
![[CI/CD]小型技术团队开发规范与最小化 DevOps CI/CD 研发流程实施指南](/assets/images/cloud01.jpg)

![[RSI]关于 Geoffrey Hinton 最新 2026 年 10 月参与论文 RSI 解读和警告解析](/assets/images/ai-logo.png)
